Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryPointString.cs =================================================================== diff -u -r6747 -r7071 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryPointString.cs (.../GeometryPointString.cs) (revision 6747) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryPointString.cs (.../GeometryPointString.cs) (revision 7071) @@ -78,7 +78,7 @@ /// /// 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.Tolerance; /// /// The calculate points as protected field (to be able to prevent recursive calls to Points) @@ -382,9 +382,8 @@ /// public Point2D DeterminePointAt(double x, double z) { - return points.FirstOrDefault( - point => point.X.AlmostEquals(x, GeometryPoint.Precision) && - point.Z.AlmostEquals(z, GeometryPoint.Precision)); + return points.FirstOrDefault(point => point.X.AlmostEquals(x, GeometryPoint.Precision) && + point.Z.AlmostEquals(z, GeometryPoint.Precision)); } /// @@ -493,6 +492,12 @@ return RelativeXzPosition.OnGeometricLine; } + public RelativeXzPosition PositionXzOfPointRelatedToExtrapolatedLine(Point2D point, + ExtraPolationMode extraPolationMode = ExtraPolationMode.Beyond) + { + return IsPointConsideredBeyondLine(point, extraPolationMode) ? RelativeXzPosition.BeyondGeometricLine : DeterminePositionWithRespectToExtrapolatedLine(point, extraPolationMode); + } + /// /// Gets the surrounding rectangle around the geometry point string /// @@ -552,12 +557,6 @@ return intersectionPointsWithLine; } - public RelativeXzPosition PositionXzOfPointRelatedToExtrapolatedLine(Point2D point, - ExtraPolationMode extraPolationMode = ExtraPolationMode.Beyond) - { - return IsPointConsideredBeyondLine(point, extraPolationMode) ? RelativeXzPosition.BeyondGeometricLine : DeterminePositionWithRespectToExtrapolatedLine(point, extraPolationMode); - } - private bool IsPointConsideredBeyondLine(Point2D point, ExtraPolationMode extraPolationMode) { if (Points.Count == 0) @@ -578,11 +577,18 @@ { double xToEvaluate = DetermineXToEvaluate(point, extraPolationMode); double zAtX = GetZatX(xToEvaluate); - if (Math.Abs(point.Z - zAtX) < 0.001) + if (Math.Abs(point.Z - zAtX) < GeometryConstants.Accuracy) { return RelativeXzPosition.OnGeometricLine; } + // Look also at the horizontal distance between the point and the line in case of steep line + double xAtZ = GetXatZ(point.Z, point.X - 2 * GeometryConstants.Accuracy); + if (Math.Abs(point.X - xAtZ) < GeometryConstants.Accuracy) + { + return RelativeXzPosition.OnGeometricLine; + } + return point.Z <= zAtX ? RelativeXzPosition.BelowGeometricLine : RelativeXzPosition.AboveGeometricLine; } @@ -733,7 +739,7 @@ result.Add((1.0 - fraction) * current.Z + fraction * next.Z); } - // if both ofsets are negative the waterline goes back + // if both offsets are negative, the waterline goes back if ((leftOffset < 0) && (rightOffset < 0)) { double fraction = rightOffset / (rightOffset + leftOffset); @@ -808,9 +814,8 @@ 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); + 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) Index: DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geotechnics/SoilProfile2DSurfaceLineHelperTests.cs =================================================================== diff -u -r7057 -r7071 --- DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geotechnics/SoilProfile2DSurfaceLineHelperTests.cs (.../SoilProfile2DSurfaceLineHelperTests.cs) (revision 7057) +++ DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geotechnics/SoilProfile2DSurfaceLineHelperTests.cs (.../SoilProfile2DSurfaceLineHelperTests.cs) (revision 7071) @@ -521,15 +521,15 @@ /// /// This test reflects the problem found in MWDAM-3279 when creating a new soil profile with a surface line very close to the - /// original surface line from the soil profile. + /// original surface line from the soil profile. If both surface lines are too close, the original surface line is used. /// [Test] - [TestCase(1, 2, 2)] - [TestCase(0.1, 0.2, 2)] - [TestCase(0.01, 0.02, 2)] - [TestCase(0.007, 0.008, 1)] - [TestCase(0.001, 0.002, 1)] - public void GivenSoilProfile2DWithSteepOrShallowSlopeInTwoPartsAndSurfaceLineCrossingTheSlope_WhenCombiningWithSurfaceLine_ThenExpectedNewSoilProfile2DCreated(double widthLowestSlope, double widthHighestSlope,int expectedLayerCount) + [TestCase(1, 2, false)] + [TestCase(0.1, 0.2, false)] + [TestCase(0.01, 0.02, false)] + [TestCase(0.007, 0.008, true)] + [TestCase(0.001, 0.002, true)] + public void GivenSoilProfile2DWithSteepOrShallowSlopeInTwoPartsAndSurfaceLineCrossingTheSlope_WhenCombiningWithSurfaceLine_ThenExpectedNewSoilProfile2DCreated(double widthLowestSlope, double widthHighestSlope, bool isNewSurfaceLineTooCloseToOriginalSurfaceLine) { // Given SoilProfile2D soilProfile2D = FactoryForSoilProfiles.CreateSoilProfile2DWithSteepOrShallowSlopeInTwoParts(widthLowestSlope, widthHighestSlope); @@ -547,27 +547,26 @@ // Then Assert.That(newSoilProfile2D, Is.Not.Null); - Assert.That(newSoilProfile2D.Surfaces, Has.Count.EqualTo(expectedLayerCount)); - var lineNewSurfaceLine = new Line(surfaceLine.Geometry.Points[1], surfaceLine.Geometry.Points[2]); - var lineSurfaceSeparation = new Line(new Point2D(widthLowestSlope, -4.15), new Point2D(10, -4.15)); - var intersectionPoint = new Point2D(); - Assert.That(LineHelper.DetermineStrictIntersectionPoint(lineNewSurfaceLine, lineSurfaceSeparation, ref intersectionPoint), Is.True); + Assert.That(newSoilProfile2D.Surfaces, Has.Count.EqualTo(2)); - if (expectedLayerCount == 2) + var intersectionPoint = new Point2D(); + if (isNewSurfaceLineTooCloseToOriginalSurfaceLine) { - var soil1 = new Soil("Surface 1"); - var soil2 = new Soil("Surface 2"); - SoilLayer2D expectedSurface1 = FactoryForSoilProfiles.CreatePolygonSoilLayer2D([intersectionPoint, new Point2D(widthLowestSlope + widthHighestSlope, -4.05), new Point2D(10, -4.05), new Point2D(10, -4.15)], soil1, null); - SoilLayer2D expectedSurface2 = FactoryForSoilProfiles.CreatePolygonSoilLayer2D([new Point2D(-10, -4.25), new Point2D(0, -4.25), intersectionPoint, new Point2D(10, -4.15), new Point2D(10, -5), new Point2D(-10, -5)], soil2, null); - CheckSoilProfileContainsSoilLayer(newSoilProfile2D, expectedSurface1); - CheckSoilProfileContainsSoilLayer(newSoilProfile2D, expectedSurface2); + intersectionPoint = originalSurfaceLine.Points[2]; } - - if (expectedLayerCount == 1) + else { - // When the surface line is too close to the original surface line, the top surface is not generated. - CheckSoilProfileContainsSoilLayer(newSoilProfile2D, soilProfile2D.Surfaces[1]); + var lineNewSurfaceLine = new Line(surfaceLine.Geometry.Points[1], surfaceLine.Geometry.Points[2]); + var lineSurfaceSeparation = new Line(new Point2D(widthLowestSlope, -4.15), new Point2D(10, -4.15)); + Assert.That(LineHelper.DetermineStrictIntersectionPoint(lineNewSurfaceLine, lineSurfaceSeparation, ref intersectionPoint), Is.True); } + + var soil1 = new Soil("Surface 1"); + var soil2 = new Soil("Surface 2"); + SoilLayer2D expectedSurface1 = FactoryForSoilProfiles.CreatePolygonSoilLayer2D([intersectionPoint, new Point2D(widthLowestSlope + widthHighestSlope, -4.05), new Point2D(10, -4.05), new Point2D(10, -4.15)], soil1, null); + SoilLayer2D expectedSurface2 = FactoryForSoilProfiles.CreatePolygonSoilLayer2D([new Point2D(-10, -4.25), new Point2D(0, -4.25), intersectionPoint, new Point2D(10, -4.15), new Point2D(10, -5), new Point2D(-10, -5)], soil2, null); + CheckSoilProfileContainsSoilLayer(newSoilProfile2D, expectedSurface1); + CheckSoilProfileContainsSoilLayer(newSoilProfile2D, expectedSurface2); } /// Index: DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/IssuesTests.cs =================================================================== diff -u -r7060 -r7071 --- DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/IssuesTests.cs (.../IssuesTests.cs) (revision 7060) +++ DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/IssuesTests.cs (.../IssuesTests.cs) (revision 7071) @@ -64,15 +64,15 @@ [SetUICulture("nl-NL")] [Test] - [TestCase("DWP-SC0035+50m_88111_3", "Schermer_sectie_3")] - [TestCase("DWP-SC0200+50m_88111_11", "Schermer_sectie_11")] - [TestCase("DWP_SC0234_88111_13", "Schermer_sectie_13")] - [TestCase("DWP_SC0264+50m_88111_14", "Schermer_sectie_14")] - public void TestGeometryAndResultForIssueMWDAM_3279(string location, string segment) + [TestCase("DWP-SC0035+50m_88111_3", "Schermer_sectie_3", 25, 260, 236, 209, 0.740)] + [TestCase("DWP-SC0200+50m_88111_11", "Schermer_sectie_11", 16, 217, 202, 163, 0.839)] + [TestCase("DWP_SC0234_88111_13", "Schermer_sectie_13", 22, 205, 184, 150, 1.444)] + [TestCase("DWP_SC0264+50m_88111_14", "Schermer_sectie_14", 17, 217, 201, 174, 0.880)] + public void TestGeometryAndResultForIssueMWDAM_3279(string location, string segment, int surfaceCount, int curveCount, int pointCount, int surfaceLinePointCount, double safetyFactor) { const string calcDir = "TestGeometryAndResultForIssueMWDAM_3279"; const string xmlInput = @"TestFiles\InputFileMWDAM-3279.xml"; - TestGeometryAndResult(calcDir, xmlInput, location, segment, 0, 0, 0, 0, 0); + TestGeometryAndResult(calcDir, xmlInput, location, segment, surfaceCount, curveCount, pointCount, surfaceLinePointCount, safetyFactor); } private static void TestGeometryAndResult(string calcDirectory, string xmlInput, string location, string segment, int surfaceCount, int curveCount, int pointCount, int surfaceLinePointCount, double safetyFactor)