Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryData.cs =================================================================== diff -u -r3893 -r4000 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryData.cs (.../GeometryData.cs) (revision 3893) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryData.cs (.../GeometryData.cs) (revision 4000) @@ -33,23 +33,10 @@ /// public class GeometryData : GeometryObject { + private readonly GeometryPointString surfaceLine = new GeometryPointString(); private GeometryGenerator geometryGenerator; - private readonly List newlyEffectedCurves = new List(); - private readonly List newlyEffectedPoints = new List(); private bool isRegeneratingGeometry; - private readonly List curveDataList = new List(); - - private readonly List loopDataList = new List(); - private readonly List pointDataList = new List(); - private readonly List surfaceDataList = new List(); - private readonly GeometryPointString surfaceLine = new GeometryPointString(); - private double bottom = GeometryConstants.DefaultBottomLimitGeometry; - - private double left = GeometryConstants.DefaultLeftLimitGeometry; - - private double right = GeometryConstants.DefaultRightLimitGeometry; - private bool updatingSurfaceLine; /// @@ -60,90 +47,397 @@ geometryGenerator = null; } - #region properties + /// + /// Ordered list of all geometry points at the surface + /// + public virtual GeometryPointString SurfaceLine + { + get + { + if (surfaceLine.CalcPoints.Count == 0 && Points.Count > 0) + { + UpdateSurfaceLine(); + } + return surfaceLine; + } + } + /// - /// Gets the points. + /// Checks geometry for loose curves and AutoRegeneration /// - /// - /// The points. - /// + /// [Validate] - public List Points + public ValidationResult[] ValidateGeometry() { - get + var validationList = new List(); { - return pointDataList; + foreach (Point2D point in Points) + { + foreach (Point2D point1 in Points) + { + if (point != point1) + { + var isValidated = false; + foreach (ValidationResult validatedItem in validationList) + { + if (validatedItem.Subject == point) + { + isValidated = true; + } + } + + if (!isValidated) + { + if (Math.Abs(point.X - point1.X) < GeometryConstants.Accuracy && + Math.Abs(point.Z - point1.Z) < GeometryConstants.Accuracy) + { + validationList.Add(new ValidationResult(ValidationResultType.Error, + point + " and " + + point1 + " values are same.", + point1)); + } + } + } + } + } } + if (Surfaces.Count < 1) + { + validationList.Add(new ValidationResult(ValidationResultType.Error, "No soil surface available.", + this)); + } + + return validationList.ToArray(); } /// - /// Gets the newly effected points. + /// Deletes the point and the curves it belongs too. /// - /// - /// The newly effected points. - /// - public List NewlyEffectedPoints + /// The point. + public void DeletePointWithCurves(Point2D point) { - get + var curvesToDelete = new List(); + foreach (GeometryCurve curve in Curves) { - return newlyEffectedPoints; + if (curve.ContainsPoint(point)) + { + curvesToDelete.Add(curve); + } } + + foreach (GeometryCurve curveToDelete in curvesToDelete) + { + Curves.Remove(curveToDelete); + } + + Points.Remove(point); } /// - /// gets the Curve data list. + /// Synchronizes the loops. /// - /// - /// The curves. - /// - public List Curves + public void SynchronizeLoops() { - get + DeleteAllLoops(); + foreach (GeometrySurface surface in Surfaces) { - return curveDataList; + // #Bka: as real donuts (or holes in geom) are not allowed, there can be no innerloop that + // is NOT an outerloop for another surface. So no need to sync innerloops. + if (surface.OuterLoop != null && surface.OuterLoop.IsLoop()) + { + Loops.Add(surface.OuterLoop); + } } } /// - /// Gets the newly effected curves. + /// Returns a that represents this instance. /// - /// - /// The newly effected curves. - /// - public List NewlyEffectedCurves + /// + /// A that represents this instance. + /// + public override string ToString() { - get + return LocalizationManager.GetTranslatedText(this, "GeometryData"); + } + + /// + /// Removes the boundary curves from the given list of curves. + /// The boundaries themselves are determined from the given geometry + /// + /// The curves. + /// The geometry (as string). + private static void RemoveBoundaryCurves(List curves, GeometryPointString geometry) + { + double minX = geometry.GetMinX(); + double maxX = geometry.GetMaxX(); + double minZ = geometry.GetMinZ(); + foreach (GeometryCurve curve in curves.ToArray()) { - return newlyEffectedCurves; + if (IsBoundaryCurve(curve, minX, maxX, minZ)) + { + curves.Remove(curve); + } } } /// - /// gets the Loop data list. + /// get all geometrypoints from all geometrycurves /// - /// - /// The loops. - /// - public List Loops + /// + /// + private static GeometryPointString GetAllPointsFromCurveList(List curveList) { - get + var result = new GeometryPointString(); + foreach (GeometryCurve curve in curveList) { - return loopDataList; + result.CalcPoints.Add(curve.EndPoint); + result.CalcPoints.Add(curve.HeadPoint); } + + return result; } /// - /// gets the Surface data list. + /// Gets next connected top curve in list of curves /// - public List Surfaces + /// + /// + /// + /// + private GeometryCurve GetNextTopCurve(GeometryCurve curve, List boundaryCurves, + List excludedCurves) { - get + // if current curve ends on right limit then that must have been the last one so stop the search + if (Math.Abs(curve.HeadPoint.X - Right) < GeometryConstants.Accuracy || Math.Abs(curve.EndPoint.X - Right) < GeometryConstants.Accuracy) { - return surfaceDataList; + return null; } + + foreach (GeometryCurve geometryCurve in boundaryCurves) + { + if (geometryCurve != curve && !excludedCurves.Contains(geometryCurve)) + { + if (AreConnected(curve, geometryCurve)) + { + return geometryCurve; + } + } + } + + return null; } + /// + /// create a copy of the curves + /// + /// + /// + private List GetCurvesCopy(List bCurves) + { + var outerloopCurvesCopy = new List(bCurves); + return outerloopCurvesCopy; + } + + /// + /// Create a surface line from points in curves + /// Precondition is that the curves start at the left boundary and are connected left to right + /// (not neccesarily neat head-end) + /// + /// + /// + private void CreateSurfaceLinePointString(List curves) + { + surfaceLine.CalcPoints.Clear(); + + if (curves.Count == 0) + { + return; + } + + var reversed = false; + // The headpoint of the first curve must be on the left boundary otherwise the + // surface line will be in the wrong order. So make sure. + if (!(Math.Abs(curves[0].HeadPoint.X - Left) < GeometryConstants.Accuracy)) + { + curves[0].Reverse(); + reversed = true; + } + + foreach (GeometryCurve curve in curves) + { + if (!surfaceLine.CalcPoints.Contains(curve.HeadPoint)) + { + surfaceLine.CalcPoints.Add(curve.HeadPoint); + } + + if (!surfaceLine.CalcPoints.Contains(curve.EndPoint)) + { + surfaceLine.CalcPoints.Add(curve.EndPoint); + } + } + + if (reversed) + { + curves[0].Reverse(); + } + } + + /// + /// get curves of the top side of the outerloop, vertical curves are omitted + /// + /// + /// + private List GetTopCurves(List curves) + { + GeometryCurve topCurve; + // Remove all curves on the geometry boundary + if (GetLeftPoints().Count > 0 && GetRightPoints().Count > 0) + { + foreach (GeometryCurve curve in curves.ToArray()) + { + if (IsBoundaryCurve(curve, Left, Right, Bottom)) + { + curves.Remove(curve); + } + } + + // Make sure you start with topcurve = curve at the left top position + topCurve = curves.Where(g => Math.Abs(g.HeadPoint.X - Left) < GeometryConstants.Accuracy || + Math.Abs(g.EndPoint.X - Left) < GeometryConstants.Accuracy) + .OrderByDescending(c => c.HeadPoint.Z) + .FirstOrDefault(); + } + else + { + GeometryPointString gString = GetAllPointsFromCurveList(curves); + RemoveBoundaryCurves(curves, gString); + double minX = gString.GetMinX(); + // Make sure you start with topcurve = curve at the left top position + topCurve = + curves.Where(g => Math.Abs(g.HeadPoint.X - minX) < GeometryConstants.Accuracy || + Math.Abs(g.EndPoint.X - minX) < GeometryConstants.Accuracy).OrderByDescending(c => c.HeadPoint.Z).FirstOrDefault(); + } + + var topCurvesLocal = new List(); + while (topCurve != null) + { + topCurvesLocal.Add(topCurve); + topCurve = GetNextTopCurve(topCurve, curves, topCurvesLocal); + } + + return topCurvesLocal; + } + + /// + /// Indicates whether a curve is on the boundary of the geometry + /// + /// + /// + /// + /// + /// + private static bool IsBoundaryCurve(GeometryCurve curve, double minX, double maxX, double minZ) + { + if (Math.Abs(curve.HeadPoint.X - minX) < GeometryConstants.Accuracy && Math.Abs(curve.EndPoint.X - minX) < GeometryConstants.Accuracy) + { + return true; + } + + if (Math.Abs(curve.HeadPoint.X - maxX) < GeometryConstants.Accuracy && Math.Abs(curve.EndPoint.X - maxX) < GeometryConstants.Accuracy) + { + return true; + } + + if (Math.Abs(curve.HeadPoint.Z - minZ) < GeometryConstants.Accuracy && Math.Abs(curve.EndPoint.Z - minZ) < GeometryConstants.Accuracy) + { + return true; + } + + return false; + } + + private bool AreConnected(GeometryCurve curve1, GeometryCurve curve2) + { + return (curve1.HeadPoint == curve2.HeadPoint || curve1.HeadPoint == curve2.EndPoint || + curve1.EndPoint == curve2.HeadPoint || curve1.EndPoint == curve2.EndPoint); + } + + /// + /// Updates the line at the top of the geometry + /// + private void UpdateSurfaceLine() + { + if (updatingSurfaceLine) + { + return; + } + + updatingSurfaceLine = true; + + List bCurves = GetBoundaryCurves(); + if (bCurves.Count == 0) + { + surfaceLine.CalcPoints.Clear(); + } + + List curvesCopy = GetCurvesCopy(bCurves); + List curves = GetTopCurves(curvesCopy); + CreateSurfaceLinePointString(curves); + + updatingSurfaceLine = false; + surfaceLine.SyncPoints(); + } + + #region properties + + /// + /// Gets the points. + /// + /// + /// The points. + /// + [Validate] + public List Points { get; } = new List(); + + /// + /// Gets the newly effected points. + /// + /// + /// The newly effected points. + /// + public List NewlyEffectedPoints { get; } = new List(); + + /// + /// gets the Curve data list. + /// + /// + /// The curves. + /// + public List Curves { get; } = new List(); + + /// + /// Gets the newly effected curves. + /// + /// + /// The newly effected curves. + /// + public List NewlyEffectedCurves { get; } = new List(); + + /// + /// gets the Loop data list. + /// + /// + /// The loops. + /// + public List Loops { get; } = new List(); + + /// + /// gets the Surface data list. + /// + public List Surfaces { get; } = new List(); + public void RegenerateGeometry() { if (isRegeneratingGeometry) @@ -156,22 +450,24 @@ { geometryGenerator = new GeometryGenerator(this); } + lock (this) { SynchronizeLoops(); RemoveDoublesFromNewlyEffectedPointsAndCurves(); Curves.Clear(); Points.Clear(); - Points.AddRange(newlyEffectedPoints); - Curves.AddRange(newlyEffectedCurves); + Points.AddRange(NewlyEffectedPoints); + Curves.AddRange(NewlyEffectedCurves); geometryGenerator.GenerateGeometry(); - newlyEffectedPoints.Clear(); - newlyEffectedCurves.Clear(); + NewlyEffectedPoints.Clear(); + NewlyEffectedCurves.Clear(); UpdateSurfaceLine(); SynchronizeLoops(); } + isRegeneratingGeometry = false; } @@ -249,62 +545,32 @@ /// /// The left. /// - public double Left - { - get - { - return left; - } - set - { - left = value; - } - } + public double Left { get; set; } = GeometryConstants.DefaultLeftLimitGeometry; /// /// Gets or sets the right. /// /// /// The right. /// - public double Right - { - get - { - return right; - } - set - { - right = value; - } - } + public double Right { get; set; } = GeometryConstants.DefaultRightLimitGeometry; /// /// Gets or sets the bottom. /// /// /// The bottom. /// - public double Bottom - { - get - { - return bottom; - } - set - { - bottom = value; - } - } + public double Bottom { get; set; } = GeometryConstants.DefaultBottomLimitGeometry; /// /// Removes the doubles from newly effected points and curves. /// public void RemoveDoublesFromNewlyEffectedPointsAndCurves() { var pdel = new List(); - var par = newlyEffectedPoints.ToArray(); - for (int i = 0; i < par.Length; i++) + Point2D[] par = NewlyEffectedPoints.ToArray(); + for (var i = 0; i < par.Length; i++) { for (int j = i; j < par.Length; j++) { @@ -317,29 +583,32 @@ } } } - foreach (var point in pdel) + + foreach (Point2D point in pdel) { - newlyEffectedPoints.Remove(point); + NewlyEffectedPoints.Remove(point); } var cdel = new List(); - var car = newlyEffectedCurves.ToArray(); + GeometryCurve[] car = NewlyEffectedCurves.ToArray(); // First remove all "illegal" newlyeffected curves - for (int i = 0; i < car.Length; i++) + for (var i = 0; i < car.Length; i++) { if (car[i].HeadPoint == null || car[i].EndPoint == null || car[i].HeadPoint.LocationEquals(car[i].EndPoint)) { cdel.Add(car[i]); } } - foreach (var curve in cdel) + + foreach (GeometryCurve curve in cdel) { - newlyEffectedCurves.Remove(curve); + NewlyEffectedCurves.Remove(curve); } + // then remove all real doubles - var car2 = newlyEffectedCurves.ToArray(); + GeometryCurve[] car2 = NewlyEffectedCurves.ToArray(); cdel.Clear(); - for (int i = 0; i < car2.Length; i++) + for (var i = 0; i < car2.Length; i++) { for (int j = i; j < car2.Length; j++) { @@ -352,9 +621,10 @@ } } } - foreach (var curve in cdel) + + foreach (GeometryCurve curve in cdel) { - newlyEffectedCurves.Remove(curve); + NewlyEffectedCurves.Remove(curve); } } @@ -364,7 +634,7 @@ /// private List GetLeftPoints() { - var geometryPoints = pointDataList.Where(gp => Math.Abs(gp.X - Left) < GeometryConstants.Accuracy).ToList(); + List geometryPoints = Points.Where(gp => Math.Abs(gp.X - Left) < GeometryConstants.Accuracy).ToList(); return geometryPoints; } @@ -374,7 +644,7 @@ /// private List GetRightPoints() { - var geometryPoints = pointDataList.Where(point => Math.Abs(point.X - Right) < GeometryConstants.Accuracy).ToList(); + List geometryPoints = Points.Where(point => Math.Abs(point.X - Right) < GeometryConstants.Accuracy).ToList(); return geometryPoints; } @@ -399,21 +669,22 @@ /// public void Rebox() { - double xMin = double.MaxValue; - double xMax = double.MinValue; - double zMin = double.MaxValue; - double zMax = double.MinValue; + var xMin = double.MaxValue; + var xMax = double.MinValue; + var zMin = double.MaxValue; + var zMax = double.MinValue; - foreach (var point in pointDataList) + foreach (Point2D point in Points) { xMin = Math.Min(point.X, xMin); xMax = Math.Max(point.X, xMax); zMin = Math.Min(point.Z, zMin); zMax = Math.Max(point.Z, zMax); } - bottom = zMin; - left = xMin; - right = xMax; + + Bottom = zMin; + Left = xMin; + Right = xMax; } #endregion @@ -425,11 +696,11 @@ /// public void Clear() { - pointDataList.Clear(); - curveDataList.Clear(); - surfaceDataList.Clear(); - newlyEffectedPoints.Clear(); - newlyEffectedCurves.Clear(); + Points.Clear(); + Curves.Clear(); + Surfaces.Clear(); + NewlyEffectedPoints.Clear(); + NewlyEffectedCurves.Clear(); } /// @@ -443,7 +714,7 @@ #endregion #region other functions - + #region calculation function /// @@ -457,16 +728,17 @@ /// Intersection coordinates /// True if lines intersect each other private static bool CheckIfIntersectStricktly(Point2D beginPoint1, Point2D endPoint1, - Point2D beginPoint2, Point2D endPoint2, - ref Point2D intersect) + Point2D beginPoint2, Point2D endPoint2, + ref Point2D intersect) { Point2D ip; - var res = Routines2D.DetermineIf2DLinesIntersectStrickly(beginPoint1, endPoint1, - beginPoint2, endPoint2, out ip); + LineIntersection res = Routines2D.DetermineIf2DLinesIntersectStrickly(beginPoint1, endPoint1, + beginPoint2, endPoint2, out ip); if (ip != null) { intersect = ip; } + return res == LineIntersection.Intersects; } @@ -488,12 +760,13 @@ var p3 = new Point2D(aL2P1[0], aL2P1[1]); var p4 = new Point2D(aL2P2[0], aL2P2[1]); var ip = new Point2D(); - var res = CheckIfIntersectStricktly(p1, p2, p3, p4, ref ip); + bool res = CheckIfIntersectStricktly(p1, p2, p3, p4, ref ip); if (res) { aIntersect[0] = ip.X; aIntersect[1] = ip.Z; } + return res; } @@ -506,7 +779,7 @@ { double surfaceHeight = -Double.MaxValue; double[] intersectionPoints = IntersectLayers(x, -9999); - for (int i = 0; i < intersectionPoints.Length; i++) + for (var i = 0; i < intersectionPoints.Length; i++) { if (intersectionPoints[i] > surfaceHeight) { @@ -530,24 +803,26 @@ throw new Exception("Empty Surfaces in IntersectLayers"); } - var beginPoint2 = new Point2D() + var beginPoint2 = new Point2D { - X = aXCoord, Z = aZCoord + X = aXCoord, + Z = aZCoord }; - var endPoint2 = new Point2D() + var endPoint2 = new Point2D { - X = aXCoord, Z = 99999 + X = aXCoord, + Z = 99999 }; var referencePoint = new Point2D(); var intersections = new List(); - for (int surfaceIndexLocal = 0; surfaceIndexLocal < Surfaces.Count; surfaceIndexLocal++) + for (var surfaceIndexLocal = 0; surfaceIndexLocal < Surfaces.Count; surfaceIndexLocal++) { - var outerLoopCurveList = Surfaces[surfaceIndexLocal].OuterLoop.CurveList; - for (int curveIndexLocal = 0; curveIndexLocal < outerLoopCurveList.Count; curveIndexLocal++) + List outerLoopCurveList = Surfaces[surfaceIndexLocal].OuterLoop.CurveList; + for (var curveIndexLocal = 0; curveIndexLocal < outerLoopCurveList.Count; curveIndexLocal++) { //Check for each curve if it intersects with x coordinate Point2D beginPoint1 = outerLoopCurveList[curveIndexLocal].GetHeadPoint(CurveDirection.Forward); @@ -570,7 +845,7 @@ return intersections.ToArray(); } - + /// /// Returns a list of boundary curves. These are curves which are used in only one surface so they have to be on a boundary (inner or outer) /// @@ -579,7 +854,7 @@ { var curves = new List(); var loops = new List(); - foreach (var surface in Surfaces) + foreach (GeometrySurface surface in Surfaces) { loops.Add(surface.OuterLoop); // Todo Ask Rob/Tom: when a real "doughnut" type surface (so hole in the center) is permitted, adding the innerloops here will @@ -589,9 +864,9 @@ loops.AddRange(surface.InnerLoops); } - foreach (var loop in loops) + foreach (GeometryLoop loop in loops) { - foreach (var curve in loop.CurveList) + foreach (GeometryCurve curve in loop.CurveList) { if (curves.Contains(curve)) { @@ -604,347 +879,14 @@ } } } + return curves; } #endregion - #endregion #endregion - - /// - /// Ordered list of all geometry points at the surface - /// - public virtual GeometryPointString SurfaceLine - { - get - { - if (surfaceLine.CalcPoints.Count == 0 && pointDataList.Count > 0) - { - UpdateSurfaceLine(); - } - return surfaceLine; - } - } - - /// - /// Checks geometry for loose curves and AutoRegeneration - /// - /// - [Validate] - public ValidationResult[] ValidateGeometry() - { - var validationList = new List(); - { - foreach (var point in Points) - { - foreach (var point1 in Points) - { - if (point != point1) - { - bool isValidated = false; - foreach (var validatedItem in validationList) - { - if (validatedItem.Subject == point) - { - isValidated = true; - } - } - if (!isValidated) - { - if (Math.Abs(point.X - point1.X) < GeometryConstants.Accuracy && - Math.Abs(point.Z - point1.Z) < GeometryConstants.Accuracy) - { - validationList.Add(new ValidationResult(ValidationResultType.Error, - point + " and " + - point1 + " values are same.", - point1)); - } - } - } - } - } - } - if (Surfaces.Count < 1) - { - validationList.Add(new ValidationResult(ValidationResultType.Error, "No soil surface available.", - this)); - } - return validationList.ToArray(); - } - - /// - /// Deletes the point and the curves it belongs too. - /// - /// The point. - public void DeletePointWithCurves(Point2D point) - { - var curvesToDelete = new List(); - foreach (var curve in Curves) - { - if (curve.ContainsPoint(point)) - { - curvesToDelete.Add(curve); - } - } - - foreach (var curveToDelete in curvesToDelete) - { - Curves.Remove(curveToDelete); - } - - Points.Remove(point); - } - - /// - /// Removes the boundary curves from the given list of curves. - /// The boundaries themselves are determined from the given geometry - /// - /// The curves. - /// The geometry (as string). - private static void RemoveBoundaryCurves(List curves, GeometryPointString geometry) - { - var minX = geometry.GetMinX(); - var maxX = geometry.GetMaxX(); - var minZ = geometry.GetMinZ(); - foreach (var curve in curves.ToArray()) - { - if (IsBoundaryCurve(curve, minX, maxX, minZ)) - { - curves.Remove(curve); - } - } - } - - /// - /// get all geometrypoints from all geometrycurves - /// - /// - /// - private static GeometryPointString GetAllPointsFromCurveList(List curveList) - { - var result = new GeometryPointString(); - foreach (var curve in curveList) - { - result.CalcPoints.Add(curve.EndPoint); - result.CalcPoints.Add(curve.HeadPoint); - } - return result; - } - - /// - /// Gets next connected top curve in list of curves - /// - /// - /// - /// - /// - private GeometryCurve GetNextTopCurve(GeometryCurve curve, List boundaryCurves, - List excludedCurves) - { - // if current curve ends on right limit then that must have been the last one so stop the search - if (Math.Abs(curve.HeadPoint.X - Right) < GeometryConstants.Accuracy || Math.Abs(curve.EndPoint.X - Right) < GeometryConstants.Accuracy) - { - return null; - } - foreach (var geometryCurve in boundaryCurves) - { - if (geometryCurve != curve && !excludedCurves.Contains(geometryCurve)) - { - if (AreConnected(curve, geometryCurve)) - { - return geometryCurve; - } - } - } - return null; - } - - /// - /// Returns a that represents this instance. - /// - /// - /// A that represents this instance. - /// - public override string ToString() - { - return LocalizationManager.GetTranslatedText(this, "GeometryData"); - } - - /// - /// Synchronizes the loops. - /// - public void SynchronizeLoops() - { - DeleteAllLoops(); - foreach (var surface in Surfaces) - { - // #Bka: as real donuts (or holes in geom) are not allowed, there can be no innerloop that - // is NOT an outerloop for another surface. So no need to sync innerloops. - if (surface.OuterLoop != null && surface.OuterLoop.IsLoop()) - { - loopDataList.Add(surface.OuterLoop); - } - } - } - - /// - /// create a copy of the curves - /// - /// - /// - private List GetCurvesCopy(List bCurves) - { - var outerloopCurvesCopy = new List(bCurves); - return outerloopCurvesCopy; - } - - /// - /// Create a surface line from points in curves - /// Precondition is that the curves start at the left boundary and are connected left to right - /// (not neccesarily neat head-end) - /// - /// - /// - private void CreateSurfaceLinePointString(List curves) - { - surfaceLine.CalcPoints.Clear(); - - if (curves.Count == 0) - { - return; - } - - var reversed = false; - // The headpoint of the first curve must be on the left boundary otherwise the - // surface line will be in the wrong order. So make sure. - if (!(Math.Abs(curves[0].HeadPoint.X - Left) < GeometryConstants.Accuracy)) - { - curves[0].Reverse(); - reversed = true; - } - - foreach (var curve in curves) - { - if (!surfaceLine.CalcPoints.Contains(curve.HeadPoint)) - { - surfaceLine.CalcPoints.Add(curve.HeadPoint); - } - if (!surfaceLine.CalcPoints.Contains(curve.EndPoint)) - { - surfaceLine.CalcPoints.Add(curve.EndPoint); - } - } - - if (reversed) - { - curves[0].Reverse(); - } - } - - /// - /// get curves of the top side of the outerloop, vertical curves are omitted - /// - /// - /// - private List GetTopCurves(List curves) - { - GeometryCurve topCurve; - // Remove all curves on the geometry boundary - if (GetLeftPoints().Count > 0 && GetRightPoints().Count > 0) - { - foreach (var curve in curves.ToArray()) - { - if (IsBoundaryCurve(curve, Left, Right, Bottom)) - { - curves.Remove(curve); - } - } - // Make sure you start with topcurve = curve at the left top position - topCurve = curves.Where(g => Math.Abs(g.HeadPoint.X - Left) < GeometryConstants.Accuracy || - Math.Abs(g.EndPoint.X - Left) < GeometryConstants.Accuracy) - .OrderByDescending(c => c.HeadPoint.Z) - .FirstOrDefault(); - } - else - { - GeometryPointString gString = GetAllPointsFromCurveList(curves); - RemoveBoundaryCurves(curves, gString); - var minX = gString.GetMinX(); - // Make sure you start with topcurve = curve at the left top position - topCurve = - curves.Where(g => Math.Abs(g.HeadPoint.X - minX) < GeometryConstants.Accuracy || - Math.Abs(g.EndPoint.X - minX) < GeometryConstants.Accuracy).OrderByDescending(c => c.HeadPoint.Z).FirstOrDefault(); - } - var topCurvesLocal = new List(); - while (topCurve != null) - { - topCurvesLocal.Add(topCurve); - topCurve = GetNextTopCurve(topCurve, curves, topCurvesLocal); - } - - return topCurvesLocal; - } - - /// - /// Indicates whether a curve is on the boundary of the geometry - /// - /// - /// - /// - /// - /// - private static bool IsBoundaryCurve(GeometryCurve curve, double minX, double maxX, double minZ) - { - if (Math.Abs(curve.HeadPoint.X - minX) < GeometryConstants.Accuracy && Math.Abs(curve.EndPoint.X - minX) < GeometryConstants.Accuracy) - { - return true; - } - - if (Math.Abs(curve.HeadPoint.X - maxX) < GeometryConstants.Accuracy && Math.Abs(curve.EndPoint.X - maxX) < GeometryConstants.Accuracy) - { - return true; - } - - if (Math.Abs(curve.HeadPoint.Z - minZ) < GeometryConstants.Accuracy && Math.Abs(curve.EndPoint.Z - minZ) < GeometryConstants.Accuracy) - { - return true; - } - - return false; - } - - private bool AreConnected(GeometryCurve curve1, GeometryCurve curve2) - { - return (curve1.HeadPoint == curve2.HeadPoint || curve1.HeadPoint == curve2.EndPoint || - curve1.EndPoint == curve2.HeadPoint || curve1.EndPoint == curve2.EndPoint); - } - - /// - /// Updates the line at the top of the geometry - /// - private void UpdateSurfaceLine() - { - if (updatingSurfaceLine) - { - return; - } - - updatingSurfaceLine = true; - - var bCurves = GetBoundaryCurves(); - if (bCurves.Count == 0) - { - surfaceLine.CalcPoints.Clear(); - } - var curvesCopy = GetCurvesCopy(bCurves); - var curves = GetTopCurves(curvesCopy); - CreateSurfaceLinePointString(curves); - - updatingSurfaceLine = false; - surfaceLine.SyncPoints(); - } } } \ No newline at end of file