Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryPointString.cs
===================================================================
diff -u -r4000 -r4052
--- DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryPointString.cs (.../GeometryPointString.cs) (revision 4000)
+++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryPointString.cs (.../GeometryPointString.cs) (revision 4052)
@@ -24,970 +24,969 @@
using System.Linq;
using Deltares.DamEngine.Data.Standard;
-namespace Deltares.DamEngine.Data.Geometry
+namespace Deltares.DamEngine.Data.Geometry;
+
+///
+/// Classifications of an objected with regards to a geometric line in the XZ-plane.
+///
+public enum RelativeXzPosition
{
///
- /// Classifications of an objected with regards to a geometric line in the XZ-plane.
+ /// Indicates that the object is considered 'on' the geometric line.
///
- public enum RelativeXzPosition
- {
- ///
- /// Indicates that the object is considered 'on' the geometric line.
- ///
- OnGeometricLine,
+ 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 '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 '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.
- ///
- BeyondGeometricLine
- }
+ ///
+ /// Indicates that the object is considered 'outside the scope' of the geometric line.
+ ///
+ BeyondGeometricLine
+}
+///
+/// Type of extrapolation
+///
+public enum ExtraPolationMode
+{
///
- /// Type of extrapolation
+ /// No extrapolation should be used.
///
- public enum ExtraPolationMode
- {
- ///
- /// No extrapolation should be used.
- ///
- Beyond,
+ Beyond,
- ///
- /// Used constant (0th order) extrapolation at the extremes.
- ///
- Horizontal
- }
+ ///
+ /// Used constant (0th order) extrapolation at the extremes.
+ ///
+ Horizontal
+}
+///
+/// Collection of points (X,Z) in world coordinates used for describing Surface lines
+///
+public class GeometryPointString : GeometryObject
+{
///
- /// Collection of points (X,Z) in world coordinates used for describing Surface lines
+ /// Matching distance where a point within this range is considered on the same point.
///
- public class GeometryPointString : GeometryObject
- {
- ///
- /// Matching distance where a point within this range is considered on the same point.
- ///
- private const double epsilon = GeometryConstants.Accuracy;
+ private const double epsilon = GeometryConstants.Accuracy;
- ///
- /// The calculate points as protected field (to be able to prevent recursive calls to CalcPoints)
- ///
- protected readonly List calcPoints = 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;
+ private readonly List points = new List();
+ private bool isFrozen;
+ private bool hasNaNx;
+ private double frozenMaxZ = double.NaN;
- // sortedPoints must never be used outside this class. Either the GPS concerned must have sorted points but then they already are
- // (eg. surfaceline, headline) or they may be unsorted in which case using the sorted list in other classes leads to errors (eg.
- // geometrysurfaces, waternetlines)
- private List sortedPoints;
+ // sortedPoints must never be used outside this class. Either the GPS concerned must have sorted points but then they already are
+ // (eg. surfaceline, headline) or they may be unsorted in which case using the sorted list in other classes leads to errors (eg.
+ // geometrysurfaces, waternetlines)
+ private List sortedPoints;
- ///
- /// Gets the at the specified index.
- ///
- ///
- /// The .
- ///
- /// The index.
- /// When less
- /// than zero or is greater or equals to .
- public Point2D this[int index]
+ ///
+ /// Gets the at the specified index.
+ ///
+ ///
+ /// The .
+ ///
+ /// The index.
+ /// When less
+ /// than zero or is greater or equals to .
+ public Point2D this[int index]
+ {
+ get
{
- get
- {
- return calcPoints[index];
- }
+ return calcPoints[index];
}
+ }
- ///
- /// The calculate points (to be used in calcualtion instead of Points for better performance)
- ///
- public virtual List CalcPoints
+ ///
+ /// The calculate points (to be used in calcualtion instead of Points for better performance)
+ ///
+ public virtual List CalcPoints
+ {
+ get
{
- get
- {
- return calcPoints;
- }
+ return calcPoints;
}
+ }
- ///
- /// List of points that describe the physical surface line or surface.
- ///
- ///
- /// The points.
- ///
- public virtual IList Points
+ ///
+ /// List of points that describe the physical surface line or surface.
+ ///
+ ///
+ /// The points.
+ ///
+ public virtual IList Points
+ {
+ get
{
- get
- {
- return points;
- }
+ return points;
}
+ }
- ///
- /// Gets the count of the points.
- ///
- ///
- /// The count.
- ///
- public int Count
+ ///
+ /// Gets the count of the points.
+ ///
+ ///
+ /// The count.
+ ///
+ public int Count
+ {
+ get
{
- get
- {
- return calcPoints.Count;
- }
+ return calcPoints.Count;
}
+ }
- ///
- /// Freezes this instance.
- ///
- public void Freeze()
+ ///
+ /// Freezes this instance.
+ ///
+ public void Freeze()
+ {
+ if (!isFrozen)
{
- if (!isFrozen)
+ sortedPoints = new List(calcPoints.Count);
+ foreach (Point2D point in calcPoints)
{
- 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();
+ sortedPoints.Add(point);
+ hasNaNx = hasNaNx || double.IsNaN(point.X);
+ frozenMaxZ = Math.Max(frozenMaxZ, point.Z);
}
- isFrozen = true;
+ sortedPoints.Sort();
}
- ///
- /// Clones this object except the points
- ///
- ///
- public virtual GeometryPointString Clone()
- {
- var clone = new GeometryPointString();
- this.CloneProperties(clone); // exludes the points !
- clone.Points.Clear();
- foreach (GeometryPoint point in Points)
- {
- clone.Points.Add(new GeometryPoint(point));
- }
+ isFrozen = true;
+ }
- clone.SyncCalcPoints();
- return clone;
+ ///
+ /// Clones this object except the points
+ ///
+ ///
+ public virtual GeometryPointString Clone()
+ {
+ var clone = new GeometryPointString();
+ this.CloneProperties(clone); // exludes the points !
+ clone.Points.Clear();
+ foreach (GeometryPoint point in Points)
+ {
+ clone.Points.Add(new GeometryPoint(point));
}
- ///
- /// Gets the minimum z.
- /// Note: CalcPoints must be used instead of calcPoints as otherwise unclear behaviour of Linq spoils the result
- /// Change back to calcPoints and Benchmark4_01l in the WaternetCreatorTests will fail!
- ///
- ///
- public double GetMinZ()
+ clone.SyncCalcPoints();
+ return clone;
+ }
+
+ ///
+ /// Gets the minimum z.
+ /// Note: CalcPoints must be used instead of calcPoints as otherwise unclear behaviour of Linq spoils the result
+ /// Change back to calcPoints and Benchmark4_01l in the WaternetCreatorTests will fail!
+ ///
+ ///
+ public double GetMinZ()
+ {
+ return CalcPoints.Any()
+ ? CalcPoints.Min(p => p.Z)
+ : double.NaN;
+ }
+
+ ///
+ /// Gets the maximum z.
+ /// Note: CalcPoints must be used instead of calcPoints as otherwise unclear behaviour of Linq spoils the result
+ /// Change back to calcPoints and Benchmark4_01l in the WaternetCreatorTests will fail!
+ ///
+ ///
+ public double GetMaxZ()
+ {
+ if (isFrozen)
{
- return CalcPoints.Any()
- ? CalcPoints.Min(p => p.Z)
- : double.NaN;
+ return frozenMaxZ;
}
- ///
- /// Gets the maximum z.
- /// Note: CalcPoints must be used instead of calcPoints as otherwise unclear behaviour of Linq spoils the result
- /// Change back to calcPoints and Benchmark4_01l in the WaternetCreatorTests will fail!
- ///
- ///
- public double GetMaxZ()
+ return CalcPoints.Any()
+ ? CalcPoints.Max(p => p.Z)
+ : double.NaN;
+ }
+
+ ///
+ /// The minimal X value among .
+ /// Note: CalcPoints must be used instead of calcPoints as otherwise unclear behaviour of Linq spoils the result
+ /// Change back to calcPoints and Benchmark4_01l in the WaternetCreatorTests will fail!
+ ///
+ /// The minimal X value or in case there are no points.
+ public double GetMinX()
+ {
+ if (isFrozen && !hasNaNx)
{
- if (isFrozen)
- {
- return frozenMaxZ;
- }
+ return sortedPoints[0].X;
+ }
- return CalcPoints.Any()
- ? CalcPoints.Max(p => p.Z)
- : double.NaN;
+ return CalcPoints.Any(p => !double.IsNaN(p.X))
+ ? CalcPoints.Where(p => !double.IsNaN(p.X)).Min(p => p.X)
+ : double.NaN;
+ }
+
+ ///
+ /// Gets the maximum x.
+ /// Note: CalcPoints must be used instead of calcPoints as otherwise unclear behaviour of Linq spoils the result
+ /// Change back to calcPoints and Benchmark4_01l in the WaternetCreatorTests will fail!
+ ///
+ ///
+ public double GetMaxX()
+ {
+ if (isFrozen && !hasNaNx)
+ {
+ return sortedPoints[sortedPoints.Count - 1].X;
}
- ///
- /// The minimal X value among .
- /// Note: CalcPoints must be used instead of calcPoints as otherwise unclear behaviour of Linq spoils the result
- /// Change back to calcPoints and Benchmark4_01l in the WaternetCreatorTests will fail!
- ///
- /// The minimal X value or in case there are no points.
- public double GetMinX()
+ return CalcPoints.Any(p => !double.IsNaN(p.X))
+ ? CalcPoints.Where(p => !double.IsNaN(p.X)).Max(p => p.X)
+ : double.NaN;
+ }
+
+ ///
+ /// Finds all vertical XZ intersections with this geometric point string, returning
+ /// the highest value among the intersections.
+ ///
+ /// X coordinate
+ ///
+ /// The z value determined by or
+ /// when is empty.
+ ///
+ ///
+ /// Uses constant extrapolation and linear interpolation.
+ ///
+ public double GetZAtUnsortedX(double x)
+ {
+ if (calcPoints.Count > 0)
{
- if (isFrozen && !hasNaNx)
+ 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)
{
- return sortedPoints[0].X;
+ verticalLineAtX.BeginPoint.Z += 1.0;
+ verticalLineAtX.EndPoint.Z -= 1.0;
}
- return CalcPoints.Any(p => !double.IsNaN(p.X))
- ? CalcPoints.Where(p => !double.IsNaN(p.X)).Min(p => p.X)
- : double.NaN;
+ IList intersectionPoints = IntersectionPointsXzWithLineXz(verticalLineAtX);
+ if (intersectionPoints.Count != 0)
+ {
+ return intersectionPoints.Max(gp => gp.Z);
+ }
+
+ // Remain consistent with GetZAtX, do constant extrapolation:
+ double zAtX;
+ if (DoConstantExtrapolationXz(x, out zAtX))
+ {
+ return zAtX;
+ }
}
- ///
- /// Gets the maximum x.
- /// Note: CalcPoints must be used instead of calcPoints as otherwise unclear behaviour of Linq spoils the result
- /// Change back to calcPoints and Benchmark4_01l in the WaternetCreatorTests will fail!
- ///
- ///
- public double GetMaxX()
+ return double.NaN;
+ }
+
+ ///
+ /// Retrieves the Z value for the given x.
+ ///
+ /// X coordinate
+ ///
+ /// The z value determined by or
+ /// when is empty.
+ ///
+ ///
+ /// Uses constant extrapolation and linear interpolation.
+ ///
+ public virtual double GetZatX(double x)
+ {
+ if (calcPoints.Any())
{
- if (isFrozen && !hasNaNx)
+ double zAtX;
+ if (DoConstantExtrapolationXz(x, out zAtX))
{
- return sortedPoints[sortedPoints.Count - 1].X;
+ return zAtX;
}
-
- return CalcPoints.Any(p => !double.IsNaN(p.X))
- ? CalcPoints.Where(p => !double.IsNaN(p.X)).Max(p => p.X)
- : double.NaN;
}
- ///
- /// Finds all vertical XZ intersections with this geometric point string, returning
- /// the highest value among the intersections.
- ///
- /// X coordinate
- ///
- /// The z value determined by or
- /// when is empty.
- ///
- ///
- /// Uses constant extrapolation and linear interpolation.
- ///
- public double GetZAtUnsortedX(double x)
+ for (var i = 0; i < calcPoints.Count - 1; i++)
{
- if (calcPoints.Count > 0)
- {
- 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;
- }
+ Point2D current = calcPoints[i];
+ Point2D next = calcPoints[i + 1];
- IList intersectionPoints = IntersectionPointsXzWithLineXz(verticalLineAtX);
- if (intersectionPoints.Count != 0)
- {
- return intersectionPoints.Max(gp => gp.Z);
- }
+ double leftOffset = x - current.X;
+ double rightOffset = next.X - x;
- // Remain consistent with GetZAtX, do constant extrapolation:
- double zAtX;
- if (DoConstantExtrapolationXz(x, out zAtX))
- {
- return zAtX;
- }
+ if (Math.Abs(leftOffset) < epsilon)
+ {
+ return current.Z;
}
- return double.NaN;
- }
-
- ///
- /// Retrieves the Z value for the given x.
- ///
- /// X coordinate
- ///
- /// The z value determined by or
- /// when is empty.
- ///
- ///
- /// Uses constant extrapolation and linear interpolation.
- ///
- public virtual double GetZatX(double x)
- {
- if (calcPoints.Any())
+ if (Math.Abs(rightOffset) < epsilon)
{
- double zAtX;
- if (DoConstantExtrapolationXz(x, out zAtX))
- {
- return zAtX;
- }
+ return next.Z;
}
- for (var i = 0; i < calcPoints.Count - 1; i++)
+ if (leftOffset >= 0 && rightOffset >= 0)
{
- Point2D current = calcPoints[i];
- Point2D next = calcPoints[i + 1];
+ double fraction = leftOffset / (leftOffset + rightOffset);
- double leftOffset = x - current.X;
- double rightOffset = next.X - x;
+ return (1.0 - fraction) * current.Z + fraction * next.Z;
+ }
+ }
- if (Math.Abs(leftOffset) < epsilon)
- {
- return current.Z;
- }
+ return Double.NaN;
+ }
- if (Math.Abs(rightOffset) < epsilon)
- {
- return next.Z;
- }
+ ///
+ /// Gets the z at x starting from index i in the point list.
+ /// This is only meant as a fast(er) version for GetZAtX for lists that are sorted by X, so use with care.
+ ///
+ /// The x.
+ /// The i.
+ ///
+ public virtual double GetZatX(double x, ref int i)
+ {
+ for (; i < calcPoints.Count - 1; i++)
+ {
+ Point2D current = calcPoints[i];
+ double leftOffset = x - current.X;
+ Point2D next = calcPoints[i + 1];
+ double rightOffset = next.X - x;
- if (leftOffset >= 0 && rightOffset >= 0)
- {
- double fraction = leftOffset / (leftOffset + rightOffset);
+ if (leftOffset < epsilon)
+ {
+ return current.Z;
+ }
- return (1.0 - fraction) * current.Z + fraction * next.Z;
- }
+ if (rightOffset >= epsilon)
+ {
+ double fraction = leftOffset / (leftOffset + rightOffset);
+ return (1.0 - fraction) * current.Z + fraction * next.Z;
}
- return Double.NaN;
+ if (i + 1 == calcPoints.Count - 1)
+ {
+ return next.Z;
+ }
}
- ///
- /// Gets the z at x starting from index i in the point list.
- /// This is only meant as a fast(er) version for GetZAtX for lists that are sorted by X, so use with care.
- ///
- /// The x.
- /// The i.
- ///
- public virtual double GetZatX(double x, ref int i)
- {
- for (; i < calcPoints.Count - 1; i++)
- {
- Point2D current = calcPoints[i];
- double leftOffset = x - current.X;
- Point2D next = calcPoints[i + 1];
- double rightOffset = next.X - x;
+ return Double.NaN;
+ }
- if (leftOffset < epsilon)
- {
- return current.Z;
- }
+ ///
+ /// Gets all z-values at x for a line.
+ ///
+ /// The x.
+ ///
+ public List GetAllZatXForLine(double x)
+ {
+ return GetAllZatX(x, false);
+ }
- if (rightOffset >= epsilon)
- {
- double fraction = leftOffset / (leftOffset + rightOffset);
- return (1.0 - fraction) * current.Z + fraction * next.Z;
- }
+ ///
+ /// Gets all z values at x for a surface.
+ ///
+ /// The x.
+ ///
+ public List GetAllZatXForSurface(double x)
+ {
+ return GetAllZatX(x, true);
+ }
- if (i + 1 == calcPoints.Count - 1)
- {
- return next.Z;
- }
+ ///
+ /// Finds the first intersection of the line with a given horizontal line.
+ ///
+ /// The height level of the horizontal line.
+ /// Optional: Discard intersections whose X value is less then
+ /// or equal to this value.
+ /// The first intersection point matching the criteria.
+ ///
+ public double GetXatZ(double z, double xmin = Double.MinValue)
+ {
+ return GetXatZStartingAt(0, z, xmin);
+ }
+
+ ///
+ /// Finds the first intersection of the line with a given horizontal line.
+ ///
+ /// Start considering instances from
+ /// starting from this index.
+ /// The height level of the horizontal line.
+ /// Optional: Discard intersections whose X value is less then
+ /// or equal to this value.
+ /// The first intersection point matching the criteria.
+ ///
+ public double GetXatZStartingAt(int start, double z, double xmin = Double.MinValue)
+ {
+ for (int i = start; i < calcPoints.Count - 1; i++)
+ {
+ Point2D current = calcPoints[i];
+ Point2D next = calcPoints[i + 1];
+
+ if (IsSegmentNotCrossingZ(z, current, next)) // Performance micro-optimization
+ {
+ continue;
}
- return Double.NaN;
+ double x = GetXIntersectingZ(z, current, next);
+ if (x > xmin)
+ {
+ return x;
+ }
}
- ///
- /// Gets all z-values at x for a line.
- ///
- /// The x.
- ///
- public List GetAllZatXForLine(double x)
+ return Double.NaN;
+ }
+
+ ///
+ /// Gets the points at x.
+ ///
+ /// The x.
+ ///
+ public IEnumerable GetPointsAtX(double x)
+ {
+ return (from Point2D point in calcPoints
+ where point.X.AlmostEquals(x, GeometryPoint.Precision)
+ select point);
+ }
+
+ ///
+ /// Gets the Point2D at the specified coordinates.
+ ///
+ /// The x.
+ /// The z.
+ ///
+ public Point2D GetPointAt(double x, double z)
+ {
+ return calcPoints.FirstOrDefault(
+ point => point.X.AlmostEquals(x, GeometryPoint.Precision) &&
+ point.Z.AlmostEquals(z, GeometryPoint.Precision));
+ }
+
+ ///
+ /// Gets the GeometryPoint at the specified coordinates.
+ ///
+ /// The x.
+ /// The z.
+ ///
+ public GeometryPoint GetGeometryPointAt(double x, double z)
+ {
+ return Points.FirstOrDefault(
+ point => point.X.AlmostEquals(x, GeometryPoint.Precision) &&
+ point.Z.AlmostEquals(z, GeometryPoint.Precision));
+ }
+
+ //#Bka: this should never be 1 method! Split it into 2 methods
+ // It is used for sliplanes only and therefor uses Points instead of calcPoints
+ ///
+ /// Adds the or remove list object.
+ ///
+ /// a point.
+ /// if set to true [a to add].
+ /// a index.
+ public virtual void AddOrRemoveListObject(object aPoint, bool aToAdd, int aIndex)
+ {
+ var point = aPoint as GeometryPoint;
+ if (point == null)
{
- return GetAllZatX(x, false);
+ return;
}
- ///
- /// Gets all z values at x for a surface.
- ///
- /// The x.
- ///
- public List GetAllZatXForSurface(double x)
+ if (aToAdd)
{
- return GetAllZatX(x, true);
+ Points.Insert(aIndex, point); //#bka what happens if index already exists? what if point exists? What if both???
}
-
- ///
- /// Finds the first intersection of the line with a given horizontal line.
- ///
- /// The height level of the horizontal line.
- /// Optional: Discard intersections whose X value is less then
- /// or equal to this value.
- /// The first intersection point matching the criteria.
- ///
- public double GetXatZ(double z, double xmin = Double.MinValue)
+ else
{
- return GetXatZStartingAt(0, z, xmin);
+ if (Points.Contains(point))
+ {
+ Points.Remove(point);
+ }
}
+ }
- ///
- /// Finds the first intersection of the line with a given horizontal line.
- ///
- /// Start considering instances from
- /// starting from this index.
- /// The height level of the horizontal line.
- /// Optional: Discard intersections whose X value is less then
- /// or equal to this value.
- /// The first intersection point matching the criteria.
- ///
- public double GetXatZStartingAt(int start, double z, double xmin = Double.MinValue)
+ ///
+ /// Returns ALL intersection points that are found for a line costructed at level z,
+ /// including the double ones as the number of points can be relevant!
+ ///
+ /// the level at which the line for intersections is constructed.
+ ///
+ public IList IntersectionsXAtZ(double z)
+ {
+ var intersectionsX = new List();
+
+ var lineAtZ = new Line
{
- for (int i = start; i < calcPoints.Count - 1; i++)
- {
- Point2D current = calcPoints[i];
- Point2D next = calcPoints[i + 1];
+ BeginPoint = new Point2D(GetMinX(), z),
+ EndPoint = new Point2D(GetMaxX(), z)
+ };
- if (IsSegmentNotCrossingZ(z, current, next)) // Performance micro-optimization
- {
- continue;
- }
+ intersectionsX.AddRange(IntersectionPointsXzWithLineXzWithAllPoints(lineAtZ).Select(gp => gp.X));
+ return intersectionsX;
+ }
- double x = GetXIntersectingZ(z, current, next);
- if (x > xmin)
- {
- return x;
- }
- }
+ ///
+ /// Returns ALL intersection points that are found, including the double ones as the number of points can be relevant!
+ ///
+ ///
+ ///
+ public IList IntersectionPointsXzWithLineXzWithAllPoints(Line line)
+ {
+ return IntersectionPointsWithLineCore(line, true);
+ }
- return Double.NaN;
- }
+ ///
+ /// Returns the UNIQUE intersectionpoints (so can not be used where number of interscections is relevant)
+ ///
+ ///
+ ///
+ public IList IntersectionPointsXzWithLineXz(Line line)
+ {
+ return IntersectionPointsWithLineCore(line, false);
+ }
- ///
- /// Gets the points at x.
- ///
- /// The x.
- ///
- public IEnumerable GetPointsAtX(double x)
- {
- return (from Point2D point in calcPoints
- where point.X.AlmostEquals(x, GeometryPoint.Precision)
- select point);
- }
+ ///
+ /// Find intersection (xz-plane) from this surface with another surface
+ /// or phratic line
+ ///
+ ///
+ ///
+ /// Considers all in to
+ /// such that they describe a closed loop.
+ ///
+ public IList ClosedGeometryIntersectionXzPointsWithGeometryPointList(IList list)
+ {
+ return IntersectWithPointsListCore(list, true);
+ }
- ///
- /// Gets the Point2D at the specified coordinates.
- ///
- /// The x.
- /// The z.
- ///
- public Point2D GetPointAt(double x, double z)
- {
- return calcPoints.FirstOrDefault(
- point => point.X.AlmostEquals(x, GeometryPoint.Precision) &&
- point.Z.AlmostEquals(z, GeometryPoint.Precision));
- }
+ ///
+ /// Finds all intersections in the XZ-plane the given .
+ ///
+ /// The geometry point string.
+ ///
+ ///
+ public List IntersectionXzPointsWithGeometryString(GeometryPointString externalSurface)
+ {
+ return IntersectionXzPointsWithGeometryPointList(externalSurface.CalcPoints);
+ }
- ///
- /// Gets the GeometryPoint at the specified coordinates.
- ///
- /// The x.
- /// The z.
- ///
- public GeometryPoint GetGeometryPointAt(double x, double z)
- {
- return Points.FirstOrDefault(
- point => point.X.AlmostEquals(x, GeometryPoint.Precision) &&
- point.Z.AlmostEquals(z, GeometryPoint.Precision));
- }
+ ///
+ /// Sorts the points by x ascending (only to be used for Surface lines).
+ ///
+ public virtual void SortPointsByXAscending()
+ {
+ calcPoints.Sort();
+ points.Sort();
+ }
- //#Bka: this should never be 1 method! Split it into 2 methods
- // It is used for sliplanes only and therefor uses Points instead of calcPoints
- ///
- /// Adds the or remove list object.
- ///
- /// a point.
- /// if set to true [a to add].
- /// a index.
- public virtual void AddOrRemoveListObject(object aPoint, bool aToAdd, int aIndex)
+ ///
+ /// Removes the non ascending points on surface line.
+ ///
+ public void RemoveNonAscendingPointsOnSurfaceLine()
+ {
+ for (int i = points.Count - 1; i > 0; i--)
{
- var point = aPoint as GeometryPoint;
- if (point == null)
+ if (Math.Abs(points[i].X - points[i - 1].X) < GeometryConstants.Accuracy)
{
- return;
+ if (Math.Abs(points[i].Z - points[i - 1].Z) > GeometryConstants.Accuracy)
+ {
+ points.Remove(points[i]);
+ }
}
+ }
+ }
- if (aToAdd)
+ ///
+ /// Gets a part of the geometry point string defined by a begin and end point
+ ///
+ ///
+ ///
+ ///
+ public GeometryPointString GetPart(double begin, double end)
+ {
+ var part = new GeometryPointString();
+ var filling = false;
+ var filled = false;
+
+ for (var i = 0; i < calcPoints.Count; i++)
+ {
+ if (!filling && !filled)
{
- Points.Insert(aIndex, point); //#bka what happens if index already exists? what if point exists? What if both???
+ filling = calcPoints[i].X >= begin - epsilon;
}
else
{
- if (Points.Contains(point))
+ filled = calcPoints[i].X >= end - epsilon;
+ if (filled)
{
- Points.Remove(point);
+ filling = false;
}
}
- }
- ///
- /// Returns ALL intersection points that are found for a line costructed at level z,
- /// including the double ones as the number of points can be relevant!
- ///
- /// the level at which the line for intersections is constructed.
- ///
- public IList IntersectionsXAtZ(double z)
- {
- var intersectionsX = new List();
-
- var lineAtZ = new Line
+ if (filling)
{
- BeginPoint = new Point2D(GetMinX(), z),
- EndPoint = new Point2D(GetMaxX(), z)
- };
-
- intersectionsX.AddRange(IntersectionPointsXzWithLineXzWithAllPoints(lineAtZ).Select(gp => gp.X));
- return intersectionsX;
+ part.calcPoints.Add(calcPoints[i]);
+ }
}
- ///
- /// Returns ALL intersection points that are found, including the double ones as the number of points can be relevant!
- ///
- ///
- ///
- public IList IntersectionPointsXzWithLineXzWithAllPoints(Line line)
- {
- return IntersectionPointsWithLineCore(line, true);
- }
+ var beginPoint = new Point2D(begin, GetZatX(begin));
+ var endPoint = new Point2D(end, GetZatX(end));
- ///
- /// Returns the UNIQUE intersectionpoints (so can not be used where number of interscections is relevant)
- ///
- ///
- ///
- public IList IntersectionPointsXzWithLineXz(Line line)
+ if (part.calcPoints.Count == 0)
{
- return IntersectionPointsWithLineCore(line, false);
+ part.calcPoints.Add(beginPoint);
+ part.calcPoints.Add(endPoint);
}
- ///
- /// Find intersection (xz-plane) from this surface with another surface
- /// or phratic line
- ///
- ///
- ///
- /// Considers all in to
- /// such that they describe a closed loop.
- ///
- public IList ClosedGeometryIntersectionXzPointsWithGeometryPointList(IList list)
+ if (!part.calcPoints[0].LocationEquals(beginPoint))
{
- return IntersectWithPointsListCore(list, true);
+ part.calcPoints.Insert(0, beginPoint);
}
- ///
- /// Finds all intersections in the XZ-plane the given .
- ///
- /// The geometry point string.
- ///
- ///
- public List IntersectionXzPointsWithGeometryString(GeometryPointString externalSurface)
+ if (!part.calcPoints[part.calcPoints.Count - 1].LocationEquals(endPoint))
{
- return IntersectionXzPointsWithGeometryPointList(externalSurface.CalcPoints);
+ part.calcPoints.Add(endPoint);
}
- ///
- /// Sorts the points by x ascending (only to be used for Surface lines).
- ///
- public virtual void SortPointsByXAscending()
- {
- calcPoints.Sort();
- points.Sort();
- }
+ SyncPoints();
+ return part;
+ }
- ///
- /// Removes the non ascending points on surface line.
- ///
- public void RemoveNonAscendingPointsOnSurfaceLine()
+ ///
+ /// Removes all double points at a location, if consecutive
+ ///
+ public void CondensePoints()
+ {
+ for (int i = calcPoints.Count - 1; i > 0; i--)
{
- for (int i = points.Count - 1; i > 0; i--)
+ if (calcPoints[i].LocationEquals(calcPoints[i - 1]))
{
- if (Math.Abs(points[i].X - points[i - 1].X) < GeometryConstants.Accuracy)
- {
- if (Math.Abs(points[i].Z - points[i - 1].Z) > GeometryConstants.Accuracy)
- {
- points.Remove(points[i]);
- }
- }
+ calcPoints.RemoveAt(i);
}
}
+ }
- ///
- /// Gets a part of the geometry point string defined by a begin and end point
- ///
- ///
- ///
- ///
- public GeometryPointString GetPart(double begin, double end)
- {
- var part = new GeometryPointString();
- var filling = false;
- var filled = false;
+ ///
+ /// Removes all points which don't influence the shape of the line
+ ///
+ public void RemoveUnnecessaryPoints()
+ {
+ const double slopeTolerance = 1E-10;
- for (var i = 0; i < calcPoints.Count; i++)
- {
- if (!filling && !filled)
- {
- filling = calcPoints[i].X >= begin - epsilon;
- }
- else
- {
- filled = calcPoints[i].X >= end - epsilon;
- if (filled)
- {
- filling = false;
- }
- }
+ CondensePoints();
- if (filling)
- {
- part.calcPoints.Add(calcPoints[i]);
- }
- }
+ for (int i = calcPoints.Count - 2; i > 1; i--)
+ {
+ // if the slope of the line before the point is equal to the slope after the point, the point can be removed
+ double slopeBefore = (calcPoints[i].Z - calcPoints[i - 1].Z) / (calcPoints[i].X - calcPoints[i - 1].X);
+ double slopeAfter = (calcPoints[i + 1].Z - calcPoints[i].Z) / (calcPoints[i + 1].X - calcPoints[i].X);
- var beginPoint = new Point2D(begin, GetZatX(begin));
- var endPoint = new Point2D(end, GetZatX(end));
-
- if (part.calcPoints.Count == 0)
+ if (Routines2D.AreEqual(slopeBefore, slopeAfter, slopeTolerance))
{
- part.calcPoints.Add(beginPoint);
- part.calcPoints.Add(endPoint);
+ calcPoints.RemoveAt(i);
}
+ }
+ }
- if (!part.calcPoints[0].LocationEquals(beginPoint))
+ ///
+ /// Synchronizes the calculation points.
+ ///
+ public void SyncCalcPoints()
+ {
+ calcPoints.Clear();
+ foreach (GeometryPoint geometryPoint in Points)
+ {
+ var p2D = new Point2D
{
- part.calcPoints.Insert(0, beginPoint);
- }
+ X = geometryPoint.X,
+ Z = geometryPoint.Z
+ };
+ calcPoints.Add(p2D);
+ }
+ }
- if (!part.calcPoints[part.calcPoints.Count - 1].LocationEquals(endPoint))
+ ///
+ /// Synchronizes the points.
+ ///
+ public void SyncPoints()
+ {
+ points.Clear();
+ foreach (Point2D p2D in calcPoints)
+ {
+ var geometryPoint = new GeometryPoint
{
- part.calcPoints.Add(endPoint);
- }
-
- SyncPoints();
- return part;
+ X = p2D.X,
+ Z = p2D.Z
+ };
+ points.Add(geometryPoint);
}
+ }
- ///
- /// Removes all double points at a location, if consecutive
- ///
- public void CondensePoints()
+ ///
+ /// Gets the surrounding rectangle around the geometry point string
+ ///
+ ///
+ public override GeometryBounds GetGeometryBounds()
+ {
+ if (!Points.Any())
{
- for (int i = calcPoints.Count - 1; i > 0; i--)
+ // Sync with calcPoints
+ SyncPoints();
+ // if still no points, then return null
+ if (!Points.Any())
{
- if (calcPoints[i].LocationEquals(calcPoints[i - 1]))
- {
- calcPoints.RemoveAt(i);
- }
+ return null;
}
}
- ///
- /// Removes all points which don't influence the shape of the line
- ///
- public void RemoveUnnecessaryPoints()
+ GeometryBounds bounds = Points[0].GetGeometryBounds();
+ for (var i = 1; i < Points.Count; i++)
{
- const double slopeTolerance = 1E-10;
+ GeometryPoint point = Points[i];
- CondensePoints();
+ bounds.Left = Math.Min(bounds.Left, point.X);
+ bounds.Right = Math.Max(bounds.Right, point.X);
+ bounds.Top = Math.Max(bounds.Top, point.Z);
+ bounds.Bottom = Math.Min(bounds.Bottom, point.Z);
+ }
- for (int i = calcPoints.Count - 2; i > 1; i--)
- {
- // if the slope of the line before the point is equal to the slope after the point, the point can be removed
- double slopeBefore = (calcPoints[i].Z - calcPoints[i - 1].Z) / (calcPoints[i].X - calcPoints[i - 1].X);
- double slopeAfter = (calcPoints[i + 1].Z - calcPoints[i].Z) / (calcPoints[i + 1].X - calcPoints[i].X);
+ return bounds;
+ }
- if (Routines2D.AreEqual(slopeBefore, slopeAfter, slopeTolerance))
- {
- calcPoints.RemoveAt(i);
- }
- }
- }
+ private IList IntersectionPointsXzClosedStringWithLineXz(Line line)
+ {
+ IList intersectionPointsWithLine = IntersectionPointsXzWithLineXz(line);
- ///
- /// Synchronizes the calculation points.
- ///
- public void SyncCalcPoints()
+ // close the poly line
+ if (calcPoints.Count > 0)
{
- calcPoints.Clear();
- foreach (GeometryPoint geometryPoint in Points)
- {
- var p2D = new Point2D
- {
- X = geometryPoint.X,
- Z = geometryPoint.Z
- };
- calcPoints.Add(p2D);
- }
+ DoIntersectAndAddToCollection(line, calcPoints[calcPoints.Count - 1], calcPoints[0],
+ intersectionPointsWithLine, false);
}
- ///
- /// 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);
- }
- }
+ return intersectionPointsWithLine;
+ }
- ///
- /// Gets the surrounding rectangle around the geometry point string
- ///
- ///
- public override GeometryBounds GetGeometryBounds()
+ ///
+ /// 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.
+ /// Output param: Extrapolated Z value, or
+ /// when no extrapolation is possible.
+ /// True if extrapolation possible; false otherwise.
+ private bool DoConstantExtrapolationXz(double x, out double z)
+ {
+ if (calcPoints.Count > 0)
{
- if (!Points.Any())
+ Point2D first = calcPoints[0];
+ if (x < first.X || Math.Abs(x - first.X) < epsilon)
{
- // Sync with calcPoints
- SyncPoints();
- // if still no points, then return null
- if (!Points.Any())
- {
- return null;
- }
+ z = first.Z;
+ return true;
}
- GeometryBounds bounds = Points[0].GetGeometryBounds();
- for (var i = 1; i < Points.Count; i++)
+ Point2D last = calcPoints[calcPoints.Count - 1];
+ if (x > last.X)
{
- GeometryPoint point = Points[i];
-
- bounds.Left = Math.Min(bounds.Left, point.X);
- bounds.Right = Math.Max(bounds.Right, point.X);
- bounds.Top = Math.Max(bounds.Top, point.Z);
- bounds.Bottom = Math.Min(bounds.Bottom, point.Z);
+ z = last.Z;
+ return true;
}
-
- return bounds;
}
- private IList IntersectionPointsXzClosedStringWithLineXz(Line line)
- {
- IList intersectionPointsWithLine = IntersectionPointsXzWithLineXz(line);
+ z = double.NaN;
+ return false;
+ }
- // close the poly line
- if (calcPoints.Count > 0)
- {
- DoIntersectAndAddToCollection(line, calcPoints[calcPoints.Count - 1], calcPoints[0],
- intersectionPointsWithLine, false);
- }
+ ///
+ /// Can be used for a Line or for a Surface where a surface is supposed to closed.
+ /// In case of a waternet line it is possible
+ /// to have more z values at a give x coor
+ /// Furthermore a z is not needed at al x values
+ ///
+ ///
+ ///
+ ///
+ private List GetAllZatX(double x, bool asSurface)
+ {
+ var result = new List();
- return intersectionPointsWithLine;
+ if (calcPoints.Count == 1 && Math.Abs(calcPoints[0].X - x) < epsilon)
+ {
+ result.Add(calcPoints[0].Z);
}
- ///
- /// Finds all intersections in the XZ-plane the given list.
- ///
- /// The list.
- ///
- ///
- ///
- private List IntersectionXzPointsWithGeometryPointList(IList list)
+ int pointsCount = calcPoints.Count - 1;
+ if (asSurface)
{
- return IntersectWithPointsListCore(list, false);
+ pointsCount = calcPoints.Count;
}
- ///
- /// Checks if constant extrapolation can be applied, and if so set the Z value.
- ///
- /// The evaluated X coordinate.
- /// Output param: Extrapolated Z value, or
- /// when no extrapolation is possible.
- /// True if extrapolation possible; false otherwise.
- private bool DoConstantExtrapolationXz(double x, out double z)
+ for (var i = 0; i < pointsCount; i++)
{
- if (calcPoints.Count > 0)
+ Point2D current;
+ Point2D next;
+ if (i == calcPoints.Count - 1)
{
- Point2D first = calcPoints[0];
- if (x < first.X || Math.Abs(x - first.X) < epsilon)
- {
- z = first.Z;
- return true;
- }
-
- Point2D last = calcPoints[calcPoints.Count - 1];
- if (x > last.X)
- {
- z = last.Z;
- return true;
- }
+ current = calcPoints[i];
+ next = calcPoints[0];
}
+ else
+ {
+ current = calcPoints[i];
+ next = calcPoints[i + 1];
+ }
- z = double.NaN;
- return false;
- }
+ double leftOffset = x - current.X;
+ double rightOffset = next.X - x;
- ///
- /// Can be used for a Line or for a Surface where a surface is supposed to closed.
- /// In case of a waternet line it is possible
- /// to have more z values at a give x coor
- /// Furthermore a z is not needed at al x values
- ///
- ///
- ///
- ///
- private List GetAllZatX(double x, bool asSurface)
- {
- var result = new List();
-
- if (calcPoints.Count == 1 && Math.Abs(calcPoints[0].X - x) < epsilon)
+ var matchedWithAPoint = false;
+ if (Math.Abs(leftOffset) < epsilon)
{
- result.Add(calcPoints[0].Z);
+ result.Add(current.Z);
+ matchedWithAPoint = true;
}
- int pointsCount = calcPoints.Count - 1;
- if (asSurface)
+ if (Math.Abs(rightOffset) < epsilon)
{
- pointsCount = calcPoints.Count;
+ result.Add(next.Z);
+ matchedWithAPoint = true;
}
- for (var i = 0; i < pointsCount; i++)
+ if (!matchedWithAPoint)
{
- Point2D current;
- Point2D next;
- if (i == calcPoints.Count - 1)
+ if (leftOffset > 0 && rightOffset > 0)
{
- current = calcPoints[i];
- next = calcPoints[0];
- }
- else
- {
- current = calcPoints[i];
- next = calcPoints[i + 1];
- }
+ double fraction = leftOffset / (leftOffset + rightOffset);
- double leftOffset = x - current.X;
- double rightOffset = next.X - x;
-
- var matchedWithAPoint = false;
- if (Math.Abs(leftOffset) < epsilon)
- {
- result.Add(current.Z);
- matchedWithAPoint = true;
+ result.Add((1.0 - fraction) * current.Z + fraction * next.Z);
}
- if (Math.Abs(rightOffset) < epsilon)
+ // if both ofsets are negative the waterline goes back
+ if ((leftOffset < 0) && (rightOffset < 0))
{
- result.Add(next.Z);
- matchedWithAPoint = true;
- }
+ double fraction = rightOffset / (rightOffset + leftOffset);
- if (!matchedWithAPoint)
- {
- if (leftOffset > 0 && rightOffset > 0)
- {
- 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))
- {
- double fraction = rightOffset / (rightOffset + leftOffset);
-
- result.Add((1.0 - fraction) * next.Z + fraction * current.Z);
- }
+ result.Add((1.0 - fraction) * next.Z + fraction * current.Z);
}
}
-
- return result.Distinct().ToList();
}
- private static bool IsSegmentNotCrossingZ(double z, Point2D current, Point2D next)
- {
- if (double.IsNaN(z))
- {
- return true;
- }
+ return result.Distinct().ToList();
+ }
- 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);
- return currentSign == nextSign && currentSign != 0;
+ private static bool IsSegmentNotCrossingZ(double z, Point2D current, Point2D next)
+ {
+ if (double.IsNaN(z))
+ {
+ return true;
}
- private static double GetXIntersectingZ(double z, Point2D current, Point2D next)
- {
- double leftOffset = Math.Abs(current.Z - z);
- if (leftOffset < epsilon)
- {
- return current.X;
- }
+ double leftOffset = Math.Abs(current.Z - z);
+ double rightOffset = Math.Abs(next.Z - z);
- double rightOffset = Math.Abs(next.Z - z);
- if (rightOffset < epsilon)
- {
- return next.X;
- }
+ int currentSign = leftOffset < epsilon ? 0 : Math.Sign(current.Z - z);
+ int nextSign = rightOffset < epsilon ? 0 : Math.Sign(next.Z - z);
+ return currentSign == nextSign && currentSign != 0;
+ }
- double fraction = leftOffset / (leftOffset + rightOffset);
- return GeneralMathRoutines.LinearInterpolate(current.X, next.X, fraction);
+ private static double GetXIntersectingZ(double z, Point2D current, Point2D next)
+ {
+ double leftOffset = Math.Abs(current.Z - z);
+ if (leftOffset < epsilon)
+ {
+ return current.X;
}
- private IList IntersectionPointsWithLineCore(Line line, bool allowDuplicates)
+ double rightOffset = Math.Abs(next.Z - z);
+ if (rightOffset < epsilon)
{
- var intersectionPointsWithLine = new List();
+ return next.X;
+ }
- for (var pointIndex = 0; pointIndex < calcPoints.Count - 1; pointIndex++)
- {
- DoIntersectAndAddToCollection(line, calcPoints[pointIndex], calcPoints[pointIndex + 1],
- intersectionPointsWithLine, allowDuplicates);
- }
+ double fraction = leftOffset / (leftOffset + rightOffset);
+ return GeneralMathRoutines.LinearInterpolate(current.X, next.X, fraction);
+ }
- return intersectionPointsWithLine;
- }
+ private IList IntersectionPointsWithLineCore(Line line, bool allowDuplicates)
+ {
+ var intersectionPointsWithLine = new List();
- private static void DoIntersectAndAddToCollection(Line line, Point2D begin, Point2D end, ICollection intersectionPointsWithLine, bool allowDuplicates)
+ for (var pointIndex = 0; pointIndex < calcPoints.Count - 1; pointIndex++)
{
- var lineInPoly = new Line
- {
- BeginPoint = begin,
- EndPoint = end
- };
- Point2D intersectionPoint = lineInPoly.GetIntersectPointXz(line);
- if (intersectionPoint != null && (allowDuplicates || NoPointSameXzLocation(intersectionPointsWithLine, intersectionPoint)))
- {
- intersectionPointsWithLine.Add(intersectionPoint);
- }
+ DoIntersectAndAddToCollection(line, calcPoints[pointIndex], calcPoints[pointIndex + 1],
+ intersectionPointsWithLine, allowDuplicates);
}
- private static bool NoPointSameXzLocation(IEnumerable collection, Point2D point)
+ return intersectionPointsWithLine;
+ }
+
+ private static void DoIntersectAndAddToCollection(Line line, Point2D begin, Point2D end, ICollection intersectionPointsWithLine, bool allowDuplicates)
+ {
+ var lineInPoly = new Line
{
- return !collection.Any(
- p => Math.Abs(p.X - point.X) < GeometryConstants.Accuracy &&
- Math.Abs(p.Z - point.Z) < GeometryConstants.Accuracy);
+ BeginPoint = begin,
+ EndPoint = end
+ };
+ Point2D intersectionPoint = lineInPoly.GetIntersectPointXz(line);
+ if (intersectionPoint != null && (allowDuplicates || NoPointSameXzLocation(intersectionPointsWithLine, intersectionPoint)))
+ {
+ intersectionPointsWithLine.Add(intersectionPoint);
}
+ }
- private List IntersectWithPointsListCore(IList list, bool closePointString)
+ 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);
+ }
+
+ private List IntersectWithPointsListCore(IList list, bool closePointString)
+ {
+ var result = new List();
+ var line = new Line();
+ for (var externalPointIndex = 0; externalPointIndex < list.Count - 1; externalPointIndex++)
{
- var result = new List();
- var line = new Line();
- for (var externalPointIndex = 0; externalPointIndex < list.Count - 1; externalPointIndex++)
- {
- line.BeginPoint = list[externalPointIndex];
- line.EndPoint = list[externalPointIndex + 1];
+ line.BeginPoint = list[externalPointIndex];
+ line.EndPoint = list[externalPointIndex + 1];
- result.AddRange(!closePointString
- ? IntersectionPointsXzWithLineXzWithAllPoints(line)
- : IntersectionPointsXzClosedStringWithLineXz(line));
- }
-
- return result;
+ result.AddRange(!closePointString
+ ? IntersectionPointsXzWithLineXzWithAllPoints(line)
+ : IntersectionPointsXzClosedStringWithLineXz(line));
}
+
+ return result;
}
}
\ No newline at end of file