Index: Core/Common/src/Core.Common.Geometry/AdvancedMath2D.cs =================================================================== diff -u -r67284323e2785c651633d9c52049ba12a9c70e6a -r58bcdff0e0effb884294342067cc723e06961379 --- Core/Common/src/Core.Common.Geometry/AdvancedMath2D.cs (.../AdvancedMath2D.cs) (revision 67284323e2785c651633d9c52049ba12a9c70e6a) +++ Core/Common/src/Core.Common.Geometry/AdvancedMath2D.cs (.../AdvancedMath2D.cs) (revision 58bcdff0e0effb884294342067cc723e06961379) @@ -59,6 +59,38 @@ } /// + /// Completes a line shape so that it becomes a polygon by adding two bottom points to the shape. + /// The location of the bottom points are determined by the 's first and + /// last points' x-coordinate and by for the y-coordinate. + /// + /// The line to complete. + /// The level at which to place the points completing the polygon. + /// A new collection of , with the line's point and + /// the two new bottom points. + /// Thrown when is null. + /// + /// Thrown when contains + /// less than 2 points. + public static IEnumerable CompleteLineToPolygon(IEnumerable line, double completingPointsLevel) + { + if (line == null) + { + throw new ArgumentNullException(nameof(line)); + } + if (line.Count() < 2) + { + throw new ArgumentException(@"The line needs to have at least two points to be able to create a complete polygon.", nameof(line)); + } + + foreach (Point2D point in line) + { + yield return point; + } + yield return new Point2D(line.Last().X, completingPointsLevel); + yield return new Point2D(line.First().X, completingPointsLevel); + } + + /// /// Transforms X coordinates in a 2D X, Y plane using: /// - A reference point as starting point of the line. /// - An offset at which the reference coincides with the X axis. Index: Core/Common/test/Core.Common.Geometry.Test/AdvancedMath2DTest.cs =================================================================== diff -u -r67284323e2785c651633d9c52049ba12a9c70e6a -r58bcdff0e0effb884294342067cc723e06961379 --- Core/Common/test/Core.Common.Geometry.Test/AdvancedMath2DTest.cs (.../AdvancedMath2DTest.cs) (revision 67284323e2785c651633d9c52049ba12a9c70e6a) +++ Core/Common/test/Core.Common.Geometry.Test/AdvancedMath2DTest.cs (.../AdvancedMath2DTest.cs) (revision 58bcdff0e0effb884294342067cc723e06961379) @@ -376,6 +376,59 @@ }, points); } + [Test] + public void CompleteLineToPolygon_WithoutLine_ThrowsArgumentNullException() + { + // Call + TestDelegate test = () => AdvancedMath2D.CompleteLineToPolygon(null, double.NaN).ToArray(); + + // Assert + var exception = Assert.Throws(test); + Assert.AreEqual("line", exception.ParamName); + } + + [Test] + public void CompleteLineToPolygon_LineWithLessThanTwoPoints_ThrowsArgumentNullException([Range(0,1)] int pointCount) + { + // Setup + IEnumerable points = Enumerable.Repeat(new Point2D(3, 2), pointCount); + + // Call + TestDelegate test = () => AdvancedMath2D.CompleteLineToPolygon(points, double.NaN).ToArray(); + + // Assert + const string message = "The line needs to have at least two points to be able to create a complete polygon."; + var exception = TestHelper.AssertThrowsArgumentExceptionAndTestMessage(test, message); + Assert.AreEqual("line", exception.ParamName); + } + + + [Test] + [TestCase(3)] + [TestCase(0)] + [TestCase(-9)] + [TestCase(double.NaN)] + public void CompleteLineToPolygon_LineWithTwoPoints_TwoPointsAtBottomLevelAdded(double completingPointsLevel) + { + // Setup + var random = new Random(21); + int firstPointX = random.Next(); + int lastPointX = random.Next(); + var points = new [] + { + new Point2D(firstPointX, random.Next()), + new Point2D(random.Next(), random.Next()), + new Point2D(lastPointX, random.Next()), + }; + + // Call + Point2D[] pointsOfPolygon = AdvancedMath2D.CompleteLineToPolygon(points, completingPointsLevel).ToArray(); + + // Assert + Assert.AreEqual(new Point2D(lastPointX, completingPointsLevel), pointsOfPolygon.ElementAt(3)); + Assert.AreEqual(new Point2D(firstPointX, completingPointsLevel), pointsOfPolygon.ElementAt(4)); + } + private static double[] ThreeRandomXCoordinates() { var random = new Random(21); Index: Ringtoets/MacroStabilityInwards/src/Ringtoets.MacroStabilityInwards.Data/SoilProfileUnderSurfaceLineFactory.cs =================================================================== diff -u -r677ec9937ae7eff73a09bf937804ad22e0dc5a4b -r58bcdff0e0effb884294342067cc723e06961379 --- Ringtoets/MacroStabilityInwards/src/Ringtoets.MacroStabilityInwards.Data/SoilProfileUnderSurfaceLineFactory.cs (.../SoilProfileUnderSurfaceLineFactory.cs) (revision 677ec9937ae7eff73a09bf937804ad22e0dc5a4b) +++ Ringtoets/MacroStabilityInwards/src/Ringtoets.MacroStabilityInwards.Data/SoilProfileUnderSurfaceLineFactory.cs (.../SoilProfileUnderSurfaceLineFactory.cs) (revision 58bcdff0e0effb884294342067cc723e06961379) @@ -54,10 +54,11 @@ } Point2D[] localizedSurfaceLine = surfaceLine.LocalGeometry.ToArray(); - IEnumerable surfaceLineGeometry = CreateSurfaceLineAreaToDepth(localizedSurfaceLine, soilProfile.Bottom); + double geometryBottom = Math.Min(soilProfile.Bottom, localizedSurfaceLine.Min(p => p.Y)) - 1; + IEnumerable surfaceLineGeometry = AdvancedMath2D.CompleteLineToPolygon(localizedSurfaceLine, geometryBottom); IEnumerable layerGeometries = soilProfile.Layers.Select( layer => As2DGeometry( - layer, + layer, soilProfile, localizedSurfaceLine.First().X, localizedSurfaceLine.Last().X)); @@ -81,8 +82,8 @@ IEnumerable layersUnderSurfaceLine = soilProfile.Layers.Select( layer => new SoilLayerUnderSurfaceLine( - RingToPoints(layer.OuterRing), - layer.Holes.Select(RingToPoints), + RingToPoints(layer.OuterRing), + layer.Holes.Select(RingToPoints), layer.Properties)); return new SoilProfileUnderSurfaceLine(layersUnderSurfaceLine); @@ -101,7 +102,7 @@ foreach (TempSoilLayerGeometry layer in layerGeometries) { - foreach (Point2D[] soilLayerArea in CreateSoilLayerAreas(surfaceLineGeometryArray, layer.OuterLoop)) + foreach (Point2D[] soilLayerArea in GetSoilLayerWithSurfaceLineIntersection(surfaceLineGeometryArray, layer.OuterLoop)) { collection.Add(new SoilLayerUnderSurfaceLine(soilLayerArea, layer.Properties)); } @@ -124,22 +125,6 @@ }, layer.Properties); } - private static IEnumerable CreateSurfaceLineAreaToDepth(Point2D[] localizedSurfaceLine, double soilProfileBottom) - { - foreach (Point2D point in localizedSurfaceLine) - { - yield return point; - } - double geometryBottom = Math.Min(soilProfileBottom, localizedSurfaceLine.Min(p => p.Y)) - 1; - yield return new Point2D(localizedSurfaceLine.Last().X, geometryBottom); - yield return new Point2D(localizedSurfaceLine.First().X, geometryBottom); - } - - private static IEnumerable CreateSoilLayerAreas(IEnumerable surfaceLineGeometry, IEnumerable soilLayerGeometry) - { - return GetSoilLayerWithSurfaceLineIntersection(surfaceLineGeometry, soilLayerGeometry); - } - private static IEnumerable GetSoilLayerWithSurfaceLineIntersection(IEnumerable surfaceLineGeometry, IEnumerable soilLayerGeometry) { return AdvancedMath2D.PolygonIntersectionWithPolygon(surfaceLineGeometry, soilLayerGeometry).Where(arr => arr.Length > 2); Index: Ringtoets/Piping/src/Ringtoets.Piping.Forms/Factories/PipingChartDataPointsFactory.cs =================================================================== diff -u -rd6fe8399e8398224cf1bda9259052232d85b85a4 -r58bcdff0e0effb884294342067cc723e06961379 --- Ringtoets/Piping/src/Ringtoets.Piping.Forms/Factories/PipingChartDataPointsFactory.cs (.../PipingChartDataPointsFactory.cs) (revision d6fe8399e8398224cf1bda9259052232d85b85a4) +++ Ringtoets/Piping/src/Ringtoets.Piping.Forms/Factories/PipingChartDataPointsFactory.cs (.../PipingChartDataPointsFactory.cs) (revision 58bcdff0e0effb884294342067cc723e06961379) @@ -277,14 +277,10 @@ double topLevel = soilLayer.Top; double bottomLevel = topLevel - soilProfile.GetLayerThickness(soilLayer); - double surfaceLineLowestPointY = surfaceLineAsPolygon.Select(p => p.Y).Min(); - double closingSurfaceLineToPolygonBottomLevel = Math.Min(surfaceLineLowestPointY, bottomLevel) - 1; + double closingSurfaceLineToPolygonBottomLevel = Math.Min(surfaceLineAsPolygon.Select(p => p.Y).Min(), bottomLevel) - 1; - surfaceLineAsPolygon.Add(new Point2D(surfaceLineAsPolygon.Last().X, closingSurfaceLineToPolygonBottomLevel)); - surfaceLineAsPolygon.Add(new Point2D(surfaceLineAsPolygon.First().X, closingSurfaceLineToPolygonBottomLevel)); - - return surfaceLineAsPolygon.ToArray(); + return AdvancedMath2D.CompleteLineToPolygon(surfaceLineLocalGeometry, closingSurfaceLineToPolygonBottomLevel).ToArray(); } private static Point2D[] CreateSurfaceLineWideSoilLayer(Point2D[] surfaceLineLocalGeometry, PipingSoilLayer soilLayer, PipingSoilProfile soilProfile)