Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryPointString.cs =================================================================== diff -u -r3893 -r4000 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryPointString.cs (.../GeometryPointString.cs) (revision 3893) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryPointString.cs (.../GeometryPointString.cs) (revision 4000) @@ -35,16 +35,19 @@ /// Indicates that the object is considered 'on' the geometric line. /// OnGeometricLine, + /// /// Indicates that the object is considered 'above' the geometric line (object Z /// coordinate higher than that of the line). /// AboveGeometricLine, + /// /// Indicates that the object is considered 'below' the geometric line (object Z /// coordinates lower than that of the line). /// BelowGeometricLine, + /// /// Indicates that the object is considered 'outside the scope' of the geometric line. /// @@ -60,6 +63,7 @@ /// No extrapolation should be used. /// Beyond, + /// /// Used constant (0th order) extrapolation at the extremes. /// @@ -75,11 +79,13 @@ /// Matching distance where a point within this range is considered on the same point. /// private const double epsilon = GeometryConstants.Accuracy; - private readonly List points = new List(); + /// /// The calculate points as protected field (to be able to prevent recursive calls to CalcPoints) /// protected readonly List calcPoints = new List(); + + private readonly List points = new List(); private bool isFrozen; private bool hasNaNx; private double frozenMaxZ = double.NaN; @@ -90,33 +96,31 @@ private List sortedPoints; /// - /// The calculate points (to be used in calcualtion instead of Points for better performance) + /// Gets the at the specified index. /// - public virtual List CalcPoints + /// + /// The . + /// + /// The index. + /// When less + /// than zero or is greater or equals to . + public Point2D this[int index] { get { - return calcPoints; + return calcPoints[index]; } } - + /// - /// Freezes this instance. + /// The calculate points (to be used in calcualtion instead of Points for better performance) /// - public void Freeze() + public virtual List CalcPoints { - if (!isFrozen) + get { - sortedPoints = new List(calcPoints.Count); - foreach (Point2D point in calcPoints) - { - sortedPoints.Add(point); - hasNaNx = hasNaNx || double.IsNaN(point.X); - frozenMaxZ = Math.Max(frozenMaxZ, point.Z); - } - sortedPoints.Sort(); + return calcPoints; } - isFrozen = true; } /// @@ -134,37 +138,40 @@ } /// - /// Gets the at the specified index. + /// Gets the count of the points. /// /// - /// The . + /// The count. /// - /// The index. - /// When less - /// than zero or is greater or equals to . - public Point2D this[int index] + public int Count { get { - return calcPoints[index]; + return calcPoints.Count; } } /// - /// Gets the count of the points. + /// Freezes this instance. /// - /// - /// The count. - /// - public int Count + public void Freeze() { - get + if (!isFrozen) { - return calcPoints.Count; + sortedPoints = new List(calcPoints.Count); + foreach (Point2D point in calcPoints) + { + sortedPoints.Add(point); + hasNaNx = hasNaNx || double.IsNaN(point.X); + frozenMaxZ = Math.Max(frozenMaxZ, point.Z); + } + + sortedPoints.Sort(); } + + isFrozen = true; } - /// /// Clones this object except the points /// @@ -174,10 +181,11 @@ var clone = new GeometryPointString(); this.CloneProperties(clone); // exludes the points ! clone.Points.Clear(); - foreach (var point in Points) + foreach (GeometryPoint point in Points) { clone.Points.Add(new GeometryPoint(point)); } + clone.SyncCalcPoints(); return clone; } @@ -203,7 +211,11 @@ /// public double GetMaxZ() { - if (isFrozen) return frozenMaxZ; + if (isFrozen) + { + return frozenMaxZ; + } + return CalcPoints.Any() ? CalcPoints.Max(p => p.Z) : double.NaN; @@ -217,7 +229,11 @@ /// The minimal X value or in case there are no points. public double GetMinX() { - if (isFrozen && !hasNaNx) return sortedPoints[0].X; + if (isFrozen && !hasNaNx) + { + return sortedPoints[0].X; + } + return CalcPoints.Any(p => !double.IsNaN(p.X)) ? CalcPoints.Where(p => !double.IsNaN(p.X)).Min(p => p.X) : double.NaN; @@ -231,7 +247,11 @@ /// public double GetMaxX() { - if (isFrozen && !hasNaNx) return sortedPoints[sortedPoints.Count - 1].X; + if (isFrozen && !hasNaNx) + { + return sortedPoints[sortedPoints.Count - 1].X; + } + return CalcPoints.Any(p => !double.IsNaN(p.X)) ? CalcPoints.Where(p => !double.IsNaN(p.X)).Max(p => p.X) : double.NaN; @@ -253,14 +273,23 @@ { if (calcPoints.Count > 0) { - var verticalLineAtX = new Line(new Point2D {X = x, Z= GetMaxZ()}, - new Point2D { X = x, Z = GetMinZ() }); + var verticalLineAtX = new Line(new Point2D + { + X = x, + Z = GetMaxZ() + }, + new Point2D + { + X = x, + Z = GetMinZ() + }); if (Math.Abs(verticalLineAtX.BeginPoint.Z - verticalLineAtX.EndPoint.Z) < GeometryConstants.Accuracy) { verticalLineAtX.BeginPoint.Z += 1.0; verticalLineAtX.EndPoint.Z -= 1.0; } - var intersectionPoints = IntersectionPointsXzWithLineXz(verticalLineAtX); + + IList intersectionPoints = IntersectionPointsXzWithLineXz(verticalLineAtX); if (intersectionPoints.Count != 0) { return intersectionPoints.Max(gp => gp.Z); @@ -273,6 +302,7 @@ return zAtX; } } + return double.NaN; } @@ -297,25 +327,28 @@ return zAtX; } } - for (int i = 0; i < calcPoints.Count - 1; i++) + + for (var i = 0; i < calcPoints.Count - 1; i++) { - var current = calcPoints[i]; - var next = calcPoints[i + 1]; + Point2D current = calcPoints[i]; + Point2D next = calcPoints[i + 1]; - var leftOffset = x - current.X; - var rightOffset = next.X - x; + double leftOffset = x - current.X; + double rightOffset = next.X - x; if (Math.Abs(leftOffset) < epsilon) { return current.Z; } + if (Math.Abs(rightOffset) < epsilon) { return next.Z; } + if (leftOffset >= 0 && rightOffset >= 0) { - var fraction = leftOffset / (leftOffset + rightOffset); + double fraction = leftOffset / (leftOffset + rightOffset); return (1.0 - fraction) * current.Z + fraction * next.Z; } @@ -335,20 +368,22 @@ { for (; i < calcPoints.Count - 1; i++) { - var current = calcPoints[i]; - var leftOffset = x - current.X; - var next = calcPoints[i + 1]; - var rightOffset = next.X - x; + Point2D current = calcPoints[i]; + double leftOffset = x - current.X; + Point2D next = calcPoints[i + 1]; + double rightOffset = next.X - x; if (leftOffset < epsilon) { return current.Z; } + if (rightOffset >= epsilon) { - var fraction = leftOffset / (leftOffset + rightOffset); + double fraction = leftOffset / (leftOffset + rightOffset); return (1.0 - fraction) * current.Z + fraction * next.Z; } + if (i + 1 == calcPoints.Count - 1) { return next.Z; @@ -405,15 +440,15 @@ { for (int i = start; i < calcPoints.Count - 1; i++) { - var current = calcPoints[i]; - var next = calcPoints[i + 1]; + Point2D current = calcPoints[i]; + Point2D next = calcPoints[i + 1]; if (IsSegmentNotCrossingZ(z, current, next)) // Performance micro-optimization { continue; } - var x = GetXIntersectingZ(z, current, next); + double x = GetXIntersectingZ(z, current, next); if (x > xmin) { return x; @@ -485,7 +520,7 @@ { if (Points.Contains(point)) { - Points.Remove(point); + Points.Remove(point); } } } @@ -530,20 +565,6 @@ return IntersectionPointsWithLineCore(line, false); } - private IList IntersectionPointsXzClosedStringWithLineXz(Line line) - { - IList intersectionPointsWithLine = IntersectionPointsXzWithLineXz(line); - - // close the poly line - if (calcPoints.Count > 0) - { - DoIntersectAndAddToCollection(line, calcPoints[calcPoints.Count - 1], calcPoints[0], - intersectionPointsWithLine, false); - } - - return intersectionPointsWithLine; - } - /// /// Find intersection (xz-plane) from this surface with another surface /// or phratic line @@ -559,18 +580,6 @@ } /// - /// Finds all intersections in the XZ-plane the given list. - /// - /// The list. - /// - /// - /// - private List IntersectionXzPointsWithGeometryPointList(IList list) - { - return IntersectWithPointsListCore(list, false); - } - - /// /// Finds all intersections in the XZ-plane the given . /// /// The geometry point string. @@ -616,10 +625,10 @@ public GeometryPointString GetPart(double begin, double end) { var part = new GeometryPointString(); - bool filling = false; - bool filled = false; + var filling = false; + var filled = false; - for (int i = 0; i < calcPoints.Count; i++) + for (var i = 0; i < calcPoints.Count; i++) { if (!filling && !filled) { @@ -658,6 +667,7 @@ { part.calcPoints.Add(endPoint); } + SyncPoints(); return part; } @@ -699,6 +709,40 @@ } /// + /// Synchronizes the calculation points. + /// + public void SyncCalcPoints() + { + calcPoints.Clear(); + foreach (GeometryPoint geometryPoint in Points) + { + var p2D = new Point2D + { + X = geometryPoint.X, + Z = geometryPoint.Z + }; + calcPoints.Add(p2D); + } + } + + /// + /// Synchronizes the points. + /// + public void SyncPoints() + { + points.Clear(); + foreach (Point2D p2D in calcPoints) + { + var geometryPoint = new GeometryPoint + { + X = p2D.X, + Z = p2D.Z + }; + points.Add(geometryPoint); + } + } + + /// /// Gets the surrounding rectangle around the geometry point string /// /// @@ -709,7 +753,10 @@ // Sync with calcPoints SyncPoints(); // if still no points, then return null - if (!Points.Any()) return null; + if (!Points.Any()) + { + return null; + } } GeometryBounds bounds = Points[0].GetGeometryBounds(); @@ -726,7 +773,33 @@ return bounds; } + private IList IntersectionPointsXzClosedStringWithLineXz(Line line) + { + IList intersectionPointsWithLine = IntersectionPointsXzWithLineXz(line); + + // close the poly line + if (calcPoints.Count > 0) + { + DoIntersectAndAddToCollection(line, calcPoints[calcPoints.Count - 1], calcPoints[0], + intersectionPointsWithLine, false); + } + + return intersectionPointsWithLine; + } + /// + /// Finds all intersections in the XZ-plane the given list. + /// + /// The list. + /// + /// + /// + private List IntersectionXzPointsWithGeometryPointList(IList list) + { + return IntersectWithPointsListCore(list, false); + } + + /// /// Checks if constant extrapolation can be applied, and if so set the Z value. /// /// The evaluated X coordinate. @@ -737,14 +810,14 @@ { if (calcPoints.Count > 0) { - var first = calcPoints[0]; + Point2D first = calcPoints[0]; if (x < first.X || Math.Abs(x - first.X) < epsilon) { z = first.Z; return true; } - var last = calcPoints[calcPoints.Count - 1]; + Point2D last = calcPoints[calcPoints.Count - 1]; if (x > last.X) { z = last.Z; @@ -774,12 +847,13 @@ result.Add(calcPoints[0].Z); } - var pointsCount = calcPoints.Count - 1; + int pointsCount = calcPoints.Count - 1; if (asSurface) { pointsCount = calcPoints.Count; } - for (int i = 0; i < pointsCount; i++) + + for (var i = 0; i < pointsCount; i++) { Point2D current; Point2D next; @@ -794,33 +868,35 @@ next = calcPoints[i + 1]; } - var leftOffset = x - current.X; - var rightOffset = next.X - x; + double leftOffset = x - current.X; + double rightOffset = next.X - x; var matchedWithAPoint = false; if (Math.Abs(leftOffset) < epsilon) { result.Add(current.Z); matchedWithAPoint = true; } + if (Math.Abs(rightOffset) < epsilon) { result.Add(next.Z); matchedWithAPoint = true; } + if (!matchedWithAPoint) { if (leftOffset > 0 && rightOffset > 0) { - var fraction = leftOffset / (leftOffset + rightOffset); + double fraction = leftOffset / (leftOffset + rightOffset); result.Add((1.0 - fraction) * current.Z + fraction * next.Z); } // if both ofsets are negative the waterline goes back if ((leftOffset < 0) && (rightOffset < 0)) { - var fraction = rightOffset / (rightOffset + leftOffset); + double fraction = rightOffset / (rightOffset + leftOffset); result.Add((1.0 - fraction) * next.Z + fraction * current.Z); } @@ -837,8 +913,8 @@ return true; } - var leftOffset = Math.Abs(current.Z - z); - var rightOffset = Math.Abs(next.Z - z); + double leftOffset = Math.Abs(current.Z - z); + double rightOffset = Math.Abs(next.Z - z); int currentSign = leftOffset < epsilon ? 0 : Math.Sign(current.Z - z); int nextSign = rightOffset < epsilon ? 0 : Math.Sign(next.Z - z); @@ -847,40 +923,42 @@ private static double GetXIntersectingZ(double z, Point2D current, Point2D next) { - var leftOffset = Math.Abs(current.Z - z); + double leftOffset = Math.Abs(current.Z - z); if (leftOffset < epsilon) { return current.X; } - var rightOffset = Math.Abs(next.Z - z); + + double rightOffset = Math.Abs(next.Z - z); if (rightOffset < epsilon) { return next.X; } - var fraction = leftOffset / (leftOffset + rightOffset); + double fraction = leftOffset / (leftOffset + rightOffset); return GeneralMathRoutines.LinearInterpolate(current.X, next.X, fraction); } private IList IntersectionPointsWithLineCore(Line line, bool allowDuplicates) { var intersectionPointsWithLine = new List(); - for (int pointIndex = 0; pointIndex < calcPoints.Count - 1; pointIndex++) + for (var pointIndex = 0; pointIndex < calcPoints.Count - 1; pointIndex++) { - DoIntersectAndAddToCollection(line, calcPoints[pointIndex], calcPoints[pointIndex + 1], - intersectionPointsWithLine, allowDuplicates); + DoIntersectAndAddToCollection(line, calcPoints[pointIndex], calcPoints[pointIndex + 1], + intersectionPointsWithLine, allowDuplicates); } + return intersectionPointsWithLine; } private static void DoIntersectAndAddToCollection(Line line, Point2D begin, Point2D end, ICollection intersectionPointsWithLine, bool allowDuplicates) { var lineInPoly = new Line - { - BeginPoint = begin, - EndPoint = end - }; + { + BeginPoint = begin, + EndPoint = end + }; Point2D intersectionPoint = lineInPoly.GetIntersectPointXz(line); if (intersectionPoint != null && (allowDuplicates || NoPointSameXzLocation(intersectionPointsWithLine, intersectionPoint))) { @@ -891,15 +969,15 @@ private static bool NoPointSameXzLocation(IEnumerable collection, Point2D point) { return !collection.Any( - p => Math.Abs(p.X - point.X) < GeometryConstants.Accuracy && - Math.Abs(p.Z - point.Z) < GeometryConstants.Accuracy); + p => Math.Abs(p.X - point.X) < GeometryConstants.Accuracy && + Math.Abs(p.Z - point.Z) < GeometryConstants.Accuracy); } private List IntersectWithPointsListCore(IList list, bool closePointString) { var result = new List(); var line = new Line(); - for (int externalPointIndex = 0; externalPointIndex < list.Count - 1; externalPointIndex++) + for (var externalPointIndex = 0; externalPointIndex < list.Count - 1; externalPointIndex++) { line.BeginPoint = list[externalPointIndex]; line.EndPoint = list[externalPointIndex + 1]; @@ -911,41 +989,5 @@ return result; } - - /// - /// Synchronizes the calculation points. - /// - public void SyncCalcPoints() - { - calcPoints.Clear(); - foreach (var geometryPoint in Points) - { - var p2D = new Point2D - { - X = geometryPoint.X, - Z = geometryPoint.Z - - }; - calcPoints.Add(p2D); - } - } - - /// - /// Synchronizes the points. - /// - public void SyncPoints() - { - points.Clear(); - foreach (var p2D in calcPoints) - { - var geometryPoint = new GeometryPoint - { - X = p2D.X, - Z = p2D.Z - - }; - points.Add(geometryPoint); - } - } } } \ No newline at end of file