Index: Ringtoets/Piping/src/Ringtoets.Piping.IO/Builders/SoilLayer2D.cs =================================================================== diff -u -r97c9e382dffcf32dc34d2e05e6a8a475b833ebd4 -r2da86d14cee084c7d6bfa52136d387cdcdb0a025 --- Ringtoets/Piping/src/Ringtoets.Piping.IO/Builders/SoilLayer2D.cs (.../SoilLayer2D.cs) (revision 97c9e382dffcf32dc34d2e05e6a8a475b833ebd4) +++ Ringtoets/Piping/src/Ringtoets.Piping.IO/Builders/SoilLayer2D.cs (.../SoilLayer2D.cs) (revision 2da86d14cee084c7d6bfa52136d387cdcdb0a025) @@ -14,12 +14,15 @@ /// internal class SoilLayer2D { + private readonly Collection> innerLoops; + private List outerLoop; + /// /// Creates a new instance of . /// public SoilLayer2D() { - InnerLoops = new Collection>(); + innerLoops = new Collection>(); } /// @@ -43,16 +46,53 @@ public double? DryUnitWeight { get; set; } /// - /// Gets the outer loop of the as a of . + /// Gets the outer loop of the as a of , + /// for which each of the segments are connected to the next. /// - internal HashSet OuterLoop { get; set; } + /// Thrown when the does not form a loop. + internal List OuterLoop + { + get + { + return outerLoop; + } + set + { + if (value.Count == 1 || !IsLoopConnected(value)) + { + throw new ArgumentException(Resources.SoilLayer2D_Error_Loop_contains_disconnected_segments); + } + outerLoop = value; + } + } /// - /// Gets the of inner loops (as of ) of the . + /// Gets the of inner loops (as of , + /// for which each of the segments are connected to the next) of the . /// - internal Collection> InnerLoops { get; private set; } + internal IEnumerable> InnerLoops + { + get + { + return innerLoops; + } + } /// + /// Adds an inner loop to the geometry. + /// + /// The innerloop to add. + /// Thrown when the does not form a loop. + internal void AddInnerLoop(List innerLoop) + { + if (innerLoop.Count == 1 || !IsLoopConnected(innerLoop)) + { + throw new ArgumentException(Resources.SoilLayer2D_Error_Loop_contains_disconnected_segments); + } + innerLoops.Add(innerLoop); + } + + /// /// Constructs a (1D) based on the and set for the . /// /// The point from which to take a 1D profile. @@ -95,6 +135,25 @@ return result; } + private static bool IsLoopConnected(List segments) + { + int segmentCount = segments.Count; + if (segmentCount == 2) + { + return segments[0].Equals(segments[1]); + } + for (int i = 0; i < segmentCount; i++) + { + var segmentA = segments[i]; + var segmentB = segments[(i + 1)%segmentCount]; + if (!segmentA.IsConnected(segmentB)) + { + return false; + } + } + return true; + } + private double EnsureBottomOutsideInnerLoop(IEnumerable> innerLoopIntersectionHeightPairs, double bottom) { var newBottom = bottom; @@ -155,60 +214,44 @@ /// intersects the vertical line at . /// Thrown when a segment is vertical at and thus /// no deterministic intersection points can be determined. - private Collection GetLoopIntersectionHeights(HashSet loop, double atX) + private Collection GetLoopIntersectionHeights(List loop, double atX) { Collection intersectionPointY = new Collection(); - for (int segmentIndex = 0; segmentIndex < loop.Count; segmentIndex++) + foreach (Segment2D segment in loop) { - var intersectionPoint = GetSegmentIntersectionAtX(loop, segmentIndex, atX); - - if (intersectionPoint.Length > 0) + if (!segment.ContainsX(atX)) { - intersectionPointY.Add(intersectionPoint[1]); + continue; } - else if (IsVerticalAtX(GetSegmentWithStartAtIndex(loop, segmentIndex), atX)) + if (segment.IsVertical()) { throw new SoilLayer2DConversionException(String.Format(Resources.Error_Can_not_determine_1D_profile_with_vertical_segments_at_x, atX)); } + + var intersectionPoint = GetSegmentIntersectionAtX(segment, atX); + + if (intersectionPoint != null) + { + intersectionPointY.Add(intersectionPoint.Y); + } } + return intersectionPointY; } - private bool IsVerticalAtX(Point3D[] segment, double atX) + private Point2D GetSegmentIntersectionAtX(Segment2D segment, double x) { - return Math.Abs(segment[0].X - atX) + Math.Abs(segment[1].X - atX) < Math2D.EpsilonForComparisons; - } - - private static Point3D[] GetSegmentWithStartAtIndex(HashSet loop, int i) - { - var current = loop.ElementAt(i); - var next = loop.ElementAt((i + 1)%loop.Count); - - return new[] + var verticalLineFirstPoint = new Point2D { - current, - next + X = x, Y = 0 }; - } - - private static double[] GetSegmentIntersectionAtX(HashSet loop, int segmentIndex, double atX) - { - Point3D[] segment = GetSegmentWithStartAtIndex(loop, segmentIndex); - - return Math2D.LineSegmentIntersectionWithLine(new[] + var verticalLineSecondPoint = new Point2D { - segment[0].X, - segment[1].X, - atX, - atX - }, new[] - { - segment[0].Z, - segment[1].Z, - 0, - 1 - }); + X = x, Y = 1 + }; + + return Math2D.LineIntersectionWithLine(segment.FirstPoint, segment.SecondPoint, verticalLineFirstPoint, verticalLineSecondPoint); } } } \ No newline at end of file