Index: Ringtoets/MacroStabilityInwards/src/Ringtoets.MacroStabilityInwards.Service/MacroStabilityInwardsInputValidator.cs =================================================================== diff -u -r28326633ec4e625d2b1a2a7fae7cb617f820eb4b -red8ca34d08ebc0fb4cffdf0bb366ee94b6e6913e --- Ringtoets/MacroStabilityInwards/src/Ringtoets.MacroStabilityInwards.Service/MacroStabilityInwardsInputValidator.cs (.../MacroStabilityInwardsInputValidator.cs) (revision 28326633ec4e625d2b1a2a7fae7cb617f820eb4b) +++ Ringtoets/MacroStabilityInwards/src/Ringtoets.MacroStabilityInwards.Service/MacroStabilityInwardsInputValidator.cs (.../MacroStabilityInwardsInputValidator.cs) (revision ed8ca34d08ebc0fb4cffdf0bb366ee94b6e6913e) @@ -144,11 +144,12 @@ IEnumerable surfaceLineWithInterpolations = GetSurfaceLineWithInterpolations(inputParameters, uniqueXs); - IEnumerable maximumYCoordinates = GetMaximumYCoordinatesFromSoilProfile(soilProfile2D); + IEnumerable topLevelCoordinates = GetTopLevelCoordinatesFromSoilProfile(soilProfile2D); + IEnumerable polygonWithTopLevelCoordinates = Math2D.ConvertPointsToPolygonSegments(topLevelCoordinates) + .ToArray(); foreach (Point2D surfaceLinePoint in surfaceLineWithInterpolations) { - bool isNear = IsPointNearSoilSegments(surfaceLinePoint, - Math2D.ConvertPointsToPolygonSegments(maximumYCoordinates)); + bool isNear = IsPointNearSoilSegments(surfaceLinePoint, polygonWithTopLevelCoordinates); if (!isNear) { return false; @@ -163,7 +164,7 @@ { return surfaceLinePoints.Select(p => p.X) .Concat(GetSoilProfile2DXCoordinates(soilProfile2D)) - .OrderBy(d => d) + .OrderBy(x => x) .Distinct(); } @@ -175,23 +176,23 @@ .Select(outerRingPoint => outerRingPoint.X)); } - private static IEnumerable GetMaximumYCoordinatesFromSoilProfile(MacroStabilityInwardsSoilProfile2D soilProfile2D) + private static IEnumerable GetTopLevelCoordinatesFromSoilProfile(MacroStabilityInwardsSoilProfile2D soilProfile2D) { - IEnumerable xCoordinates = GetSoilProfile2DXCoordinates(soilProfile2D).OrderBy(d => d) + IEnumerable xCoordinates = GetSoilProfile2DXCoordinates(soilProfile2D).OrderBy(x => x) .Distinct(); - var selectedCoordinates = new List(); + IEnumerable> layerPolygons = soilProfile2D.Layers + .Select(l => Math2D.ConvertPointsToPolygonSegments(l.OuterRing.Points)) + .ToArray(); + + var topLevelCoordinates = new List(); foreach (double xCoordinate in xCoordinates) { - double maximumYCoordinate = soilProfile2D.Layers - .SelectMany(l => l.OuterRing - .Points) - .Where(p => p.X.Equals(xCoordinate)) - .Max(p => p.Y); - selectedCoordinates.Add(new Point2D(xCoordinate, maximumYCoordinate)); + IEnumerable intersectingCoordinates = layerPolygons.SelectMany(lp => Math2D.SegmentsIntersectionWithVerticalLine(lp, xCoordinate)); + topLevelCoordinates.Add(new Point2D(xCoordinate, intersectingCoordinates.Select(p => p.Y).Max())); } - return selectedCoordinates; + return topLevelCoordinates; } private static IEnumerable GetSurfaceLineWithInterpolations(MacroStabilityInwardsInput inputParameters, Index: Ringtoets/MacroStabilityInwards/test/Ringtoets.MacroStabilityInwards.Service.Test/MacroStabilityInwardsInputValidatorTest.cs =================================================================== diff -u -r28326633ec4e625d2b1a2a7fae7cb617f820eb4b -red8ca34d08ebc0fb4cffdf0bb366ee94b6e6913e --- Ringtoets/MacroStabilityInwards/test/Ringtoets.MacroStabilityInwards.Service.Test/MacroStabilityInwardsInputValidatorTest.cs (.../MacroStabilityInwardsInputValidatorTest.cs) (revision 28326633ec4e625d2b1a2a7fae7cb617f820eb4b) +++ Ringtoets/MacroStabilityInwards/test/Ringtoets.MacroStabilityInwards.Service.Test/MacroStabilityInwardsInputValidatorTest.cs (.../MacroStabilityInwardsInputValidatorTest.cs) (revision ed8ca34d08ebc0fb4cffdf0bb366ee94b6e6913e) @@ -302,7 +302,133 @@ CollectionAssert.IsEmpty(messages); } + /// + /// The soil profile used in this tests contains two outer layers (outer rings) and a surfaceline): + /// + /// Soil layer one (1) is defined on top of the surfaceline on the X coordinates + /// Soil layer two (2) is defined as shown below: + /// + /// + /// + /// 20 1 + /// + /// + /// 15 2 2 + /// / \ / \ + /// / \ / \ + /// 10 1,2 2 ---- 2 1,2 + /// 0 5 10 15 20 + /// + /// [Test] + public void Validate_SurfaceLineNear2DProfileWithLayersWithTriangularXCoordinateDefinitions_ReturnsEmpty() + { + // Setup + var surfaceLine = new MacroStabilityInwardsSurfaceLine("Test"); + surfaceLine.SetGeometry(new[] + { + new Point3D(0, 0.0, 10), + new Point3D(10, 0.0, 20), + new Point3D(20, 0.0, 10) + }); + + var soilProfile = new MacroStabilityInwardsSoilProfile2D( + "profile", + new[] + { + new MacroStabilityInwardsSoilLayer2D(new Ring(new[] + { + new Point2D(0, 10), + new Point2D(10, 20), + new Point2D(20, 10) + })), + new MacroStabilityInwardsSoilLayer2D(new Ring(new[] + { + new Point2D(0, 10), + new Point2D(5, 15), + new Point2D(7.5, 0), + new Point2D(12.5, 0), + new Point2D(15, 15), + new Point2D(20, 10) + })) + }, new MacroStabilityInwardsPreconsolidationStress[0]); + + input.StochasticSoilProfile = new MacroStabilityInwardsStochasticSoilProfile(0.0, + soilProfile); + input.SurfaceLine = surfaceLine; + + // Call + IEnumerable messages = MacroStabilityInwardsInputValidator.Validate(input).ToArray(); + + // Assert + CollectionAssert.IsEmpty(messages); + } + + /// + /// The soil profile used in this tests contains two outer layers (outer rings) and a surfaceline): + /// + /// Soil layer one (1) is defined on directly vertically below the X coordinates of the surface line + /// Soil layer two (2) is defined as shown below: + /// + /// + /// + /// 20 1 --------------------- 1 + /// | | + /// | | + /// 15 1,2 ------------------- 1,2 + /// | | + /// | | + /// 10 2 2 + /// \ / + /// \ / + /// 5 2 + /// 0 5 10 15 20 + /// + /// + [Test] + public void Validate_SurfaceLineNear2DProfileWithLayersWithSquareXCoordinateDefinitions_ReturnsEmpty() + { + // Setup + var surfaceLine = new MacroStabilityInwardsSurfaceLine("Test"); + surfaceLine.SetGeometry(new[] + { + new Point3D(0, 0.0, 20), + new Point3D(20, 0.0, 20) + }); + + var soilProfile = new MacroStabilityInwardsSoilProfile2D( + "profile", + new[] + { + new MacroStabilityInwardsSoilLayer2D(new Ring(new[] + { + new Point2D(0, 20), + new Point2D(20, 20), + new Point2D(20, 15), + new Point2D(0, 15) + })), + new MacroStabilityInwardsSoilLayer2D(new Ring(new[] + { + new Point2D(0, 15), + new Point2D(20, 15), + new Point2D(20, 10), + new Point2D(10, 5), + new Point2D(0, 10) + })) + }, new MacroStabilityInwardsPreconsolidationStress[0]); + + input.StochasticSoilProfile = new MacroStabilityInwardsStochasticSoilProfile(0.0, + soilProfile); + input.SurfaceLine = surfaceLine; + + // Call + IEnumerable messages = MacroStabilityInwardsInputValidator.Validate(input).ToArray(); + + // Assert + CollectionAssert.IsEmpty(messages); + } + + [Test] public void Validate_ZoneBoundaryRightSmallerThanZoneBoundaryLeft_ReturnsError() { // Setup @@ -522,17 +648,16 @@ })) }, new MacroStabilityInwardsPreconsolidationStress[0])) .SetName("Second segment is vertical and exceeds surfaceLine"); - + yield return new TestCaseData(new MacroStabilityInwardsSoilProfile2D( "profile", new[] { new MacroStabilityInwardsSoilLayer2D(new Ring(new[] { - new Point2D(0, 10), new Point2D(0, 10.06), - new Point2D(1, 20), - new Point2D(2, 10) + new Point2D(1, 20.06), + new Point2D(2, 10.06) })), new MacroStabilityInwardsSoilLayer2D(new Ring(new[] { @@ -541,7 +666,7 @@ new Point2D(2, 10) })), }, new MacroStabilityInwardsPreconsolidationStress[0])) - .SetName("Top soillayer, one Y coordinate not within limit."); + .SetName("Top soil layer offset above surfaceline above limit."); } private static IEnumerable SurfaceLineOnMacroStabilityInwardsSoilProfile2D() @@ -650,6 +775,46 @@ })) }, new MacroStabilityInwardsPreconsolidationStress[0])) .SetName("SoilLayer X start and end point on left side of surfaceline"); + + yield return new TestCaseData( + new MacroStabilityInwardsSoilProfile2D( + "profile", + new[] + { + new MacroStabilityInwardsSoilLayer2D(new Ring(new[] + { + new Point2D(0.0, 10.05), + new Point2D(0.1, 20.05), + new Point2D(0.2, 10.05) + })), + new MacroStabilityInwardsSoilLayer2D(new Ring(new[] + { + new Point2D(0.0, 10), + new Point2D(0.1, 20), + new Point2D(0.2, 10) + })) + }, new MacroStabilityInwardsPreconsolidationStress[0])) + .SetName("Top SoilLayer offset above surfaceline within limit"); + + yield return new TestCaseData( + new MacroStabilityInwardsSoilProfile2D( + "profile", + new[] + { + new MacroStabilityInwardsSoilLayer2D(new Ring(new[] + { + new Point2D(0.0, 9), + new Point2D(0.1, 19), + new Point2D(0.2, 9) + })), + new MacroStabilityInwardsSoilLayer2D(new Ring(new[] + { + new Point2D(0.0, 10), + new Point2D(0.1, 20), + new Point2D(0.2, 10) + })) + }, new MacroStabilityInwardsPreconsolidationStress[0])) + .SetName("Top SoilLayer offset below surfaceline within limit"); } } } \ No newline at end of file