Index: DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/MultiCoreMacroStabilityInwardsTests.cs =================================================================== diff -u -r6531 -r6557 --- DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/MultiCoreMacroStabilityInwardsTests.cs (.../MultiCoreMacroStabilityInwardsTests.cs) (revision 6531) +++ DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/MultiCoreMacroStabilityInwardsTests.cs (.../MultiCoreMacroStabilityInwardsTests.cs) (revision 6557) @@ -42,14 +42,14 @@ private const string tutorialStability2D = @"TestFiles\InputTutorialStability2D.xml"; [Test, Category(Categories.MultiCore)] - [TestCase(4, InputStabilityModelType.Bishop, "SlopeAdaptionBeforeShoulderAdaption", 21, 6)] - [TestCase(8, InputStabilityModelType.Bishop, "SlopeAdaptionBeforeShoulderAdaption", 21, 6)] - [TestCase(4, InputStabilityModelType.UpliftVan, "SlopeAdaptionBeforeShoulderAdaption", 9, 17)] - [TestCase(8, InputStabilityModelType.UpliftVan, "SlopeAdaptionBeforeShoulderAdaption", 9, 17)] + [TestCase(4, InputStabilityModelType.Bishop, "SlopeAdaptionBeforeShoulderAdaption", 18, 9)] + [TestCase(8, InputStabilityModelType.Bishop, "SlopeAdaptionBeforeShoulderAdaption", 18, 9)] + [TestCase(4, InputStabilityModelType.UpliftVan, "SlopeAdaptionBeforeShoulderAdaption", 8, 18)] + [TestCase(8, InputStabilityModelType.UpliftVan, "SlopeAdaptionBeforeShoulderAdaption", 8, 18)] [TestCase(4, InputStabilityModelType.Bishop, "OptimizedSlopeAndShoulderAdaption", 9, 18)] [TestCase(8, InputStabilityModelType.Bishop, "OptimizedSlopeAndShoulderAdaption", 9, 18)] - [TestCase(4, InputStabilityModelType.UpliftVan, "OptimizedSlopeAndShoulderAdaption", 7, 19)] - [TestCase(8, InputStabilityModelType.UpliftVan, "OptimizedSlopeAndShoulderAdaption", 7, 19)] + [TestCase(4, InputStabilityModelType.UpliftVan, "OptimizedSlopeAndShoulderAdaption", 6, 20)] + [TestCase(8, InputStabilityModelType.UpliftVan, "OptimizedSlopeAndShoulderAdaption", 6, 20)] public void GivenTutorialDesign_WhenCalculateAllWithGeometryAdaption_ThenGivesExpectedResults(int maxCores, InputStabilityModelType stabilityModelType, string designMethod, int expectedSucceeded = 21, int expectedFailed = 6) { Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilProfile2D.cs =================================================================== diff -u -r6404 -r6557 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilProfile2D.cs (.../SoilProfile2D.cs) (revision 6404) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilProfile2D.cs (.../SoilProfile2D.cs) (revision 6557) @@ -34,7 +34,6 @@ /// public class SoilProfile2D : SoilProfile { - private const double deviation = 1E-05; private const double toleranceAlmostEqual = 1e-07; private readonly List surfaces = new List(); @@ -163,33 +162,35 @@ public static SoilLayer2D DetermineOriginalLayerFromOldSurfaces(GeometrySurface geometrySurface, IEnumerable oldSurfaces) { - var point = new Point2D(0.0, 0.0); - var isPointInOuterLoopAndOldSurface = false; - point = IsPointInOuterLoopAndOldSurface(geometrySurface, oldSurfaces, point, ref isPointInOuterLoopAndOldSurface); - - if (!isPointInOuterLoopAndOldSurface) + Point2D point = geometrySurface.DetermineValidTestPointBasedOnNewSurface(); + // If the test point is beyond the x-limits of the old surfaces, there cannot be an old layer. + if (IsSurfaceLeftOrRightOfOldSurfaces(point, oldSurfaces)) { - isPointInOuterLoopAndOldSurface = IsPointInOldSurfaceJustBelowTopOfNewGeometryWithinItsLimits(geometrySurface, - oldSurfaces, point, - isPointInOuterLoopAndOldSurface); + return null; } + + return DetermineOldSurfaceFromTestPoint(oldSurfaces, point); + } - if (isPointInOuterLoopAndOldSurface) + /// + /// Determines whether the given point is left or right of the old surfaces. + /// + /// + /// + /// true when the given point is left or right of the old surfaces else false. + public static bool IsSurfaceLeftOrRightOfOldSurfaces(Point2D point, IEnumerable oldSurfaces) + { + // If the test point is beyound the x-limits of the old surfaces, there can not be an old layer + double xminFromSurfaces = DetermineXminFromSurfaces(oldSurfaces); + double xmaxFromSurfaces = DetermineXmaxFromSurfaces(oldSurfaces); + if (point.X > xmaxFromSurfaces || point.X < xminFromSurfaces) { - if (IsPointInPreviousOuterLoopOfOldSurface(oldSurfaces, point, out SoilLayer2D soilLayer2D)) - { - return soilLayer2D; - } - - if (IsPointInOuterLoopOfOldSurface(oldSurfaces, point, out SoilLayer2D originalLayerFromOldSurfaces1)) - { - return originalLayerFromOldSurfaces1; - } + return true; } - return null; + return false; } - + /// /// Returns a that represents this instance. /// @@ -201,17 +202,22 @@ return Name; } - private static bool IsPointInOuterLoopOfOldSurface(IEnumerable oldSurfaces, Point2D point, - out SoilLayer2D originalLayerFromOldSurfaces1) + /// + /// Determine the old surface from the test point. + /// + /// + /// + /// The found old surface/layer else null. + public static SoilLayer2D DetermineOldSurfaceFromTestPoint(IEnumerable oldSurfaces, Point2D point) { - originalLayerFromOldSurfaces1 = null; foreach (SoilLayer2D oldSurface in oldSurfaces) { GeometryLoop outerLoop = oldSurface.GeometrySurface.OuterLoop; - if (outerLoop != null && outerLoop.CurveList.Count > 2 && Routines2D.CheckIfPointIsInPolygon(outerLoop, point.X, - point.Z) == PointInPolygon.InsidePolygon) + if (outerLoop != null && outerLoop.CurveList.Count > 2 && + Routines2D.CheckIfPointIsInPolygon(outerLoop, point.X, point.Z) == PointInPolygon.InsidePolygon) { var isPointInOuterLoopOfOldSurface = true; + // Make sure point is NOT in (one of) the inner loop(s). foreach (GeometryLoop innerLoop in oldSurface.GeometrySurface.InnerLoops) { if (Routines2D.CheckIfPointIsInPolygon(innerLoop, point.X, point.Z) == PointInPolygon.InsidePolygon) @@ -222,117 +228,13 @@ if (isPointInOuterLoopOfOldSurface) { - originalLayerFromOldSurfaces1 = oldSurface; - return true; + return oldSurface; } } } - - return false; + return null; } - - private static bool IsPointInPreviousOuterLoopOfOldSurface(IEnumerable oldSurfaces, Point2D point, - out SoilLayer2D soilLayer2D) - { - soilLayer2D = null; - foreach (SoilLayer2D oldSurface in oldSurfaces) - { - GeometryLoop previousOuterLoop = oldSurface.GeometrySurface.PreviousOuterLoop; - if (previousOuterLoop != null && previousOuterLoop.CurveList.Count > 2 && - Routines2D.CheckIfPointIsInPolygon(previousOuterLoop, point.X, point.Z) == PointInPolygon.InsidePolygon) - { - var isPointInPreviousOuterLoopOfOldSurface = true; - foreach (GeometryLoop previousInnerLoop in oldSurface.GeometrySurface.PreviousInnerLoops) - { - if (Routines2D.CheckIfPointIsInPolygon(previousInnerLoop, point.X, point.Z) == PointInPolygon.InsidePolygon) - { - isPointInPreviousOuterLoopOfOldSurface = false; - } - } - - if (isPointInPreviousOuterLoopOfOldSurface) - { - soilLayer2D = oldSurface; - return true; - } - } - } - - return false; - } - - private static bool IsPointInOldSurfaceJustBelowTopOfNewGeometryWithinItsLimits(GeometrySurface geometrySurface, - IEnumerable oldSurfaces, Point2D point, bool isPointInOuterLoopAndOldSurface) - { - GeometryPointString topGeometrySurface = geometrySurface.DetermineTopGeometrySurface(); - topGeometrySurface.SortPointsByXAscending(); - Point2D geometryPoint1 = topGeometrySurface[0]; - geometryPoint1.X -= deviation; - geometryPoint1.Z -= deviation; - Point2D geometryPoint2 = topGeometrySurface[checked(topGeometrySurface.Count - 1)]; - geometryPoint2.X += deviation; - geometryPoint2.Z -= deviation; - bool isPoint1WithinOldSurfaces = IsPointWithinOldSurfaces(geometryPoint1, oldSurfaces, -deviation); - bool isPoint2WithinOldSurfaces = IsPointWithinOldSurfaces(geometryPoint2, oldSurfaces, -deviation); - double d = double.NaN; - if (isPoint1WithinOldSurfaces && !isPoint2WithinOldSurfaces) - { - point.X = geometryPoint1.X; - point.Z = geometryPoint1.Z; - isPointInOuterLoopAndOldSurface = true; - d = geometryPoint1.X + deviation; - } - - if (!isPoint1WithinOldSurfaces && isPoint2WithinOldSurfaces) - { - point.X = geometryPoint2.X; - point.Z = geometryPoint2.Z; - isPointInOuterLoopAndOldSurface = true; - d = geometryPoint2.X - deviation; - } - - if (!double.IsNaN(d)) - { - double xminFromSurfaces = DetermineXminFromSurfaces(oldSurfaces); - double xmaxFromSurfaces = DetermineXmaxFromSurfaces(oldSurfaces); - if (d <= xmaxFromSurfaces && d >= xminFromSurfaces) - { - isPointInOuterLoopAndOldSurface = false; - } - } - - return isPointInOuterLoopAndOldSurface; - } - - private static Point2D IsPointInOuterLoopAndOldSurface(GeometrySurface geometrySurface, IEnumerable oldSurfaces, Point2D point, ref bool isPointInOuterLoopAndOldSurface) - { - foreach (GeometryCurve curve in geometrySurface.OuterLoop.CurveList) - { - point = new Point2D((curve.HeadPoint.X + curve.EndPoint.X) / 2.0, (curve.HeadPoint.Z + curve.EndPoint.Z) / 2.0); - if (IsPointWithinOldSurfaces(point, oldSurfaces, deviation) || IsPointWithinOldSurfaces(point, oldSurfaces, - -deviation)) - { - point.Z += deviation; - if (Routines2D.CheckIfPointIsInPolygon(geometrySurface.OuterLoop, point.X, point.Z) == - PointInPolygon.InsidePolygon) - { - isPointInOuterLoopAndOldSurface = true; - break; - } - - point.Z -= 2 * deviation; - if (Routines2D.CheckIfPointIsInPolygon(geometrySurface.OuterLoop, point.X, point.Z) == - PointInPolygon.InsidePolygon) - { - isPointInOuterLoopAndOldSurface = true; - break; - } - } - } - - return point; - } - + private static double DetermineXminFromSurfaces(IEnumerable oldSurfaces) { var xminFromSurfaces = double.MaxValue; @@ -355,51 +257,6 @@ return xmaxFromSurfaces; } - private static bool IsPointWithinOldSurfaces(Point2D point, IEnumerable oldSurfaces, double verticalShift) - { - point.Z += verticalShift; - var shiftedPoint = new Point2D(point.X, point.Z); - foreach (SoilLayer2D oldSurface in oldSurfaces) - { - GeometryLoop outerLoop = oldSurface.GeometrySurface.OuterLoop; - List innerLoops = oldSurface.GeometrySurface.InnerLoops; - bool isPointInSurface = IsPointInGivenOuterLoopOfOldSurface(shiftedPoint, outerLoop, innerLoops); - if (!isPointInSurface) - { - GeometryLoop previousOuterLoop = oldSurface.GeometrySurface.PreviousOuterLoop; - List previousInnerLoops = oldSurface.GeometrySurface.PreviousInnerLoops; - isPointInSurface = IsPointInGivenOuterLoopOfOldSurface(shiftedPoint, previousOuterLoop, previousInnerLoops); - } - - if (isPointInSurface) - { - return true; - } - } - - return false; - } - - private static bool IsPointInGivenOuterLoopOfOldSurface(Point2D point, GeometryLoop outerLoop, - List innerLoops) - { - var isPointInSurface = false; - if (outerLoop != null && Routines2D.CheckIfPointIsInPolygon(outerLoop, point.X, point.Z) == PointInPolygon.InsidePolygon) - { - isPointInSurface = true; - // Make sure the point is in the outer loop, not in the inner loop(s). - foreach (GeometryLoop innerLoop in innerLoops) - { - if (Routines2D.CheckIfPointIsInPolygon(innerLoop, point.X, point.Z) == PointInPolygon.InsidePolygon) - { - return false; - } - } - } - - return isPointInSurface; - } - private SoilProfile1D DetermineSoilProfile1DAtX(double x) { var soilProfile = new SoilProfile1D Index: DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geometry/GeometryDataTests.cs =================================================================== diff -u -r6404 -r6557 --- DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geometry/GeometryDataTests.cs (.../GeometryDataTests.cs) (revision 6404) +++ DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geometry/GeometryDataTests.cs (.../GeometryDataTests.cs) (revision 6557) @@ -389,74 +389,6 @@ return geometryModel; } - private GeometryData CreateDonutGeometry() - { - var geometryModel = new GeometryData - { - Left = -10, - Bottom = -10, - Right = 20 - }; - - /* The following model looks as follows - * - * |----------| - * | ------ | - * | | | | - * | | | | - * | ------ | - * |----------| - * - */ - - var point1 = new Point2D(0, 0); - var point2 = new Point2D(0, 10); - var point3 = new Point2D(10, 10); - var point4 = new Point2D(10, 0); - var point5 = new Point2D(3, 3); - var point6 = new Point2D(3, 7); - var point7 = new Point2D(7, 7); - var point8 = new Point2D(7, 3); - - var curve1 = new GeometryCurve(point1, point2); - var curve2 = new GeometryCurve(point2, point3); - var curve3 = new GeometryCurve(point3, point4); - var curve4 = new GeometryCurve(point4, point1); - var curve5 = new GeometryCurve(point5, point6); - var curve6 = new GeometryCurve(point6, point7); - var curve7 = new GeometryCurve(point7, point8); - var curve8 = new GeometryCurve(point8, point5); - - geometryModel.Points.AddRange(new[] - { - point1, - point2, - point3, - point4, - point5, - point6, - point7, - point8 - }); - geometryModel.Curves.AddRange(new[] - { - curve1, - curve2, - curve3, - curve4, - curve5, - curve5, - curve6, - curve7, - curve8 - }); - - geometryModel.NewlyEffectedPoints.AddRange(geometryModel.Points); - geometryModel.NewlyEffectedCurves.AddRange(geometryModel.Curves); - geometryModel.RegenerateGeometry(); - return geometryModel; - } - public class GivenGeometryData { private static readonly GeometryData originalGeometryData = CreateGeometryData(); Index: DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/MacroStabilityInwardsTests.cs =================================================================== diff -u -r6548 -r6557 --- DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/MacroStabilityInwardsTests.cs (.../MacroStabilityInwardsTests.cs) (revision 6548) +++ DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/MacroStabilityInwardsTests.cs (.../MacroStabilityInwardsTests.cs) (revision 6557) @@ -71,7 +71,7 @@ Assert.Multiple(() => { - Assert.That(output.Results.CalculationResults[0].StabilityDesignResults.SafetyFactor, Is.EqualTo(1.165).Within(tolerance)); + Assert.That(output.Results.CalculationResults[0].StabilityDesignResults.SafetyFactor, Is.EqualTo(1.161).Within(tolerance)); // NumberOfIterations=0 Assert.That(output.Results.CalculationResults[0].StabilityDesignResults.NumberOfIterations, Is.EqualTo(0)); @@ -131,7 +131,7 @@ DesignResult result = output.Results.CalculationResults[0]; Assert.Multiple(() => { - Assert.That(result.StabilityDesignResults.SafetyFactor, Is.EqualTo(1.248).Within(tolerance)); + Assert.That(result.StabilityDesignResults.SafetyFactor, Is.EqualTo(1.245).Within(tolerance)); Assert.That(result.StabilityDesignResults.UpliftSituation, Is.Not.Null); }); Assert.Multiple(() => @@ -144,7 +144,7 @@ result = output.Results.CalculationResults[1]; Assert.Multiple(() => { - Assert.That(result.StabilityDesignResults.SafetyFactor, Is.EqualTo(1.165).Within(tolerance)); + Assert.That(result.StabilityDesignResults.SafetyFactor, Is.EqualTo(1.161).Within(tolerance)); Assert.That(result.StabilityDesignResults.UpliftSituation, Is.Not.Null); Assert.That(result.StabilityDesignResults.StabilityModelType, Is.EqualTo(DesignResultStabilityDesignResultsStabilityModelType.UpliftVan)); Assert.That(result.BaseFileName, Is.EqualTo("Loc(DWP_1)_Sce(1)_Pro(DWP_1_stix)")); @@ -153,7 +153,7 @@ result = output.Results.CalculationResults[2]; Assert.Multiple(() => { - Assert.That(result.StabilityDesignResults.SafetyFactor, Is.EqualTo(1.165).Within(tolerance)); + Assert.That(result.StabilityDesignResults.SafetyFactor, Is.EqualTo(1.161).Within(tolerance)); Assert.That(result.StabilityDesignResults.UpliftSituation, Is.Not.Null); Assert.That(result.StabilityDesignResults.StabilityModelType, Is.EqualTo(DesignResultStabilityDesignResultsStabilityModelType.BishopUpliftVan)); Assert.That(result.BaseFileName, Is.EqualTo("Loc(DWP_1)_Sce(1)_Pro(DWP_1_stix)")); @@ -317,7 +317,7 @@ Assert.Multiple(() => { // No Zone - Assert.That(result.StabilityDesignResults.SafetyFactor, Is.EqualTo(1.318).Within(tolerance)); + Assert.That(result.StabilityDesignResults.SafetyFactor, Is.EqualTo(1.359).Within(tolerance)); Assert.That(result.LocationName, Is.EqualTo("DWP_10_1")); Assert.That(result.ProfileName, Is.EqualTo("DWP_10.stix")); Assert.That(ConversionHelper.ConvertToCalculationResult(result.CalculationResult), Is.EqualTo(CalculationResult.Succeeded)); @@ -327,7 +327,7 @@ Assert.Multiple(() => { // Forbidden Zone, factor = 0.2 - Assert.That(result.StabilityDesignResults.SafetyFactor, Is.EqualTo(1.835).Within(tolerance)); + Assert.That(result.StabilityDesignResults.SafetyFactor, Is.EqualTo(1.789).Within(tolerance)); Assert.That(result.LocationName, Is.EqualTo("DWP_10_4")); Assert.That(result.ProfileName, Is.EqualTo("DWP_10.stix")); Assert.That(ConversionHelper.ConvertToCalculationResult(result.CalculationResult), Is.EqualTo(CalculationResult.Succeeded)); @@ -344,10 +344,10 @@ // Set UseNewMinDistanceDikeToeStartDitch(Use new allowed distance toe-ditch) = true (to force value to be written to XML) // // Parameters: CalcDir - StabilityModel - DesignStrategy - CalculationResult - FoS - EntryPointX - ExitPointX - DikeLength - ShoulderHeight - Iterations - ResultMessage - [TestCase("TestStabInwardsBishopDesignSequential", "Bishop", "SlopeAdaptionBeforeShoulderAdaption", CalculationResult.Succeeded, 1.467, 45.385, 2.799, 5, "")] + [TestCase("TestStabInwardsBishopDesignSequential", "Bishop", "SlopeAdaptionBeforeShoulderAdaption", CalculationResult.Succeeded, 1.496, 45.385, 2.799, 5, "")] [TestCase("TestStabInwardsBishopDesignOptimized", "Bishop", "OptimizedSlopeAndShoulderAdaption", CalculationResult.Succeeded, 1.483, 43.760, 3.889, 4, "")] - [TestCase("TestStabInwardsUpliftVanDesignSequential", "UpliftVan", "SlopeAdaptionBeforeShoulderAdaption", CalculationResult.Succeeded, 1.427, 47.735, 3.132, 6, "")] - [TestCase("TestStabInwardsUpliftVanDesignOptimized", "UpliftVan", "OptimizedSlopeAndShoulderAdaption", CalculationResult.RunFailed, 1.342, 80.417, 4.545, 20, "After height adaption ditch does not fit inside surfaceline anymore.")] + [TestCase("TestStabInwardsUpliftVanDesignSequential", "UpliftVan", "SlopeAdaptionBeforeShoulderAdaption", CalculationResult.Succeeded, 1.480, 47.735, 3.132, 6, "")] + [TestCase("TestStabInwardsUpliftVanDesignOptimized", "UpliftVan", "OptimizedSlopeAndShoulderAdaption", CalculationResult.Succeeded, 1.403, 80.417, 4.545, 20, "")] public void CanPerformStabilityInwardsDesignTutorialDesignWithAdaption_OneLocation( string calcDir, string stabilityModel, string designStrategy, CalculationResult calculationResult, double expectedSafetyFactor, @@ -430,7 +430,7 @@ Output output = GetOutputStringForProject(analysisType, true); Assert.That(output.Results.CalculationResults, Is.Not.Null, "No results available"); - Assert.That(output.Results.CalculationResults[0].StabilityDesignResults.SafetyFactor, Is.EqualTo(1.259).Within(0.0005)); + Assert.That(output.Results.CalculationResults[0].StabilityDesignResults.SafetyFactor, Is.EqualTo(1.356).Within(0.0005)); } [Test] @@ -785,10 +785,10 @@ /// /// [Test] - [TestCase(double.NaN, 1.248)] // DoC is unchanged - [TestCase(0, 1.248)] - [TestCase(50, 1.276)] - [TestCase(100, 1.305)] + [TestCase(double.NaN, 1.245)] // DoC is unchanged + [TestCase(0, 1.245)] + [TestCase(50, 1.273)] + [TestCase(100, 1.301)] public void GivenStabilityDesignTutorial_WhenCalculatingWithDifferentDegreeOfConsolidation_ThenReturnsADifferentSafetyFactor(double trafficLoadDegreeOfConsolidation, double expectedSafetyFactor) { const string calcDir = "TestEffectOfTrafficLoadDegreeOfConsolidation"; @@ -852,7 +852,7 @@ Assert.Multiple(() => { - Assert.That(output.Results.CalculationResults[0].StabilityDesignResults.SafetyFactor, Is.EqualTo(1.248).Within(tolerance)); + Assert.That(output.Results.CalculationResults[0].StabilityDesignResults.SafetyFactor, Is.EqualTo(1.245).Within(tolerance)); // NumberOfIterations=0 Assert.That(output.Results.CalculationResults[0].StabilityDesignResults.NumberOfIterations, Is.EqualTo(0)); @@ -885,14 +885,14 @@ } [Test, Category(Categories.Slow)] - [TestCase("DWP_1", InputStabilityModelType.Bishop, "SlopeAdaptionBeforeShoulderAdaption", CalculationResult.Succeeded, 1.4, 1.492, 5)] - [TestCase("DWP_1", InputStabilityModelType.Bishop, "OptimizedSlopeAndShoulderAdaption", CalculationResult.Succeeded, 1.4, 1.545, 4)] - [TestCase("DWP_2", InputStabilityModelType.Bishop, "SlopeAdaptionBeforeShoulderAdaption", CalculationResult.Succeeded, 1.5, 1.546, 9)] - [TestCase("DWP_2", InputStabilityModelType.Bishop, "OptimizedSlopeAndShoulderAdaption", CalculationResult.RunFailed, 1.5, 1.176, 17, "Location 'DWP_2', subsoil scenario 'DWP_2.stix', design scenario '1': The calculation failed with error message 'The design was not successful. After height adaption ditch does not fit inside surfaceline anymore.'")] - [TestCase("DWP_13", InputStabilityModelType.Bishop, "OptimizedSlopeAndShoulderAdaption", CalculationResult.RunFailed, 1.5, 0.936, 23, "The characteristic points of the surfaceline are not ascending in X-direction.")] - [TestCase("DWP_10", InputStabilityModelType.Bishop, "OptimizedSlopeAndShoulderAdaption", CalculationResult.RunFailed, 1.5, 1.308, 16, "Location 'DWP_10', subsoil scenario 'DWP_10.stix', design scenario '3': The calculation failed with error message 'The design was not successful. After height adaption ditch does not fit inside surfaceline anymore.'")] - [TestCase("DWP_1", InputStabilityModelType.BishopUpliftVan, "SlopeAdaptionBeforeShoulderAdaption", CalculationResult.Succeeded, 1.4, 1.405, 6)] - [TestCase("DWP_1", InputStabilityModelType.BishopUpliftVan, "OptimizedSlopeAndShoulderAdaption", CalculationResult.RunFailed, 1.5, 1.367, 19)] + [TestCase("DWP_1", InputStabilityModelType.Bishop, "SlopeAdaptionBeforeShoulderAdaption", CalculationResult.Succeeded, 1.4, 1.456, 5)] + [TestCase("DWP_1", InputStabilityModelType.Bishop, "OptimizedSlopeAndShoulderAdaption", CalculationResult.Succeeded, 1.4, 1.520, 4)] + [TestCase("DWP_2", InputStabilityModelType.Bishop, "SlopeAdaptionBeforeShoulderAdaption", CalculationResult.RunFailed, 1.5, 1.348, 14)] + [TestCase("DWP_2", InputStabilityModelType.Bishop, "OptimizedSlopeAndShoulderAdaption", CalculationResult.RunFailed, 1.5, 1.072, 17, "Location 'DWP_2', subsoil scenario 'DWP_2.stix', design scenario '1': The calculation failed with error message 'The design was not successful. After height adaption ditch does not fit inside surfaceline anymore.'")] + [TestCase("DWP_13", InputStabilityModelType.Bishop, "OptimizedSlopeAndShoulderAdaption", CalculationResult.RunFailed, 1.5, 0.943, 23, "The characteristic points of the surfaceline are not ascending in X-direction.")] + [TestCase("DWP_10", InputStabilityModelType.Bishop, "OptimizedSlopeAndShoulderAdaption", CalculationResult.RunFailed, 1.5, 1.385, 16, "Location 'DWP_10', subsoil scenario 'DWP_10.stix', design scenario '3': The calculation failed with error message 'The design was not successful. After height adaption ditch does not fit inside surfaceline anymore.'")] + [TestCase("DWP_1", InputStabilityModelType.BishopUpliftVan, "SlopeAdaptionBeforeShoulderAdaption", CalculationResult.Succeeded, 1.4, 1.504, 7)] + [TestCase("DWP_1", InputStabilityModelType.BishopUpliftVan, "OptimizedSlopeAndShoulderAdaption", CalculationResult.RunFailed, 1.5, 1.424, 19)] public void GivenTutorialDesign_WhenSpecifiedLocationRunWithGeometryAdaption_ThenGivesExpectedResults(string locationId, InputStabilityModelType stabilityModelType, string designMethod, CalculationResult calculationResult, double requiredSafetyFactor, double actualSafetyFactor, int iterationCount, string errorMessage = "", string firstStabilityMessage = "") { Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilProfile2DSurfaceLineHelper.cs =================================================================== diff -u -r6524 -r6557 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilProfile2DSurfaceLineHelper.cs (.../SoilProfile2DSurfaceLineHelper.cs) (revision 6524) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilProfile2DSurfaceLineHelper.cs (.../SoilProfile2DSurfaceLineHelper.cs) (revision 6557) @@ -23,6 +23,7 @@ using System.Collections.Generic; using System.Linq; using Deltares.DamEngine.Data.Geometry; +//using Deltares.DamEngine.Data.GeometryExport; for Debugging purposes only. using Deltares.DamEngine.Data.Standard; namespace Deltares.DamEngine.Data.Geotechnics; @@ -97,13 +98,16 @@ var oldSurfaces = new List(); oldSurfaces.AddRange(soilProfile2D.Surfaces); - +//GeometryExporter.ExportToFile(soilProfile2D.Geometry, GeometryExporter.VisualizationFolder + "_oldSurf_" +"GeometryStart.txt"); +//GeometryExporter.ExportWithSurfaceLineToJsonFile(GeometryExporter.VisualizationFolder + GeometryExporter.ExportJasonFile, clonedProfile.Geometry, surfaceLine); var result = new SoilProfile2D(); result.Name = soilProfile2D.Name; - result.Geometry = CreateNewGeometryForSoilProfile2DByCombiningItsGeometryWithSurfaceLine(clonedSurfaceLine, clonedProfile.Geometry); - - RemoveGeometryDataOfSoilProfileAboveSurfaceLine(clonedSurfaceLine, ref result); + result.Geometry = CreateNewGeometryForSoilProfile2DByCombiningItsGeometryWithSurfaceLine(clonedSurfaceLine, clonedProfile.Geometry); +//GeometryExporter.ExportWithSurfaceLineToJsonFile(GeometryExporter.VisualizationFolder + GeometryExporter.ExportJasonFile, result.Geometry, surfaceLine); + RemoveGeometryDataOfSoilProfileAboveSurfaceLine(clonedSurfaceLine, ref result); +//GeometryExporter.ExportWithSurfaceLineToJsonFile(GeometryExporter.VisualizationFolder + GeometryExporter.ExportJasonFile, result.Geometry, surfaceLine); ReconstructSurfaces(ref result, clonedSurfaceLine, oldSurfaces, defaultSoil); +//GeometryExporter.ExportWithSurfaceLineToJsonFile(GeometryExporter.VisualizationFolder + GeometryExporter.ExportJasonFile, result.Geometry, surfaceLine); ReconstructPreConsolidations(ref result, clonedProfile); result.Geometry.Rebox(); result.Geometry.UpdateSurfaceLine(); @@ -343,47 +347,40 @@ result.Surfaces.Clear(); foreach (GeometrySurface surface in result.Geometry.Surfaces) { - var soilLayer2D1 = new SoilLayer2D + var soilLayer2D = new SoilLayer2D { GeometrySurface = surface, Soil = defaultSoil }; - SoilLayer2D soilLayer2D2 = soilLayer2D1; + SoilLayer2D layerFromOldSurfaces = SoilProfile2D.DetermineOriginalLayerFromOldSurfaces(surface, oldSurfaces); if (layerFromOldSurfaces != null && layerFromOldSurfaces.Soil != null) { - soilLayer2D2.Soil = layerFromOldSurfaces.Soil; - soilLayer2D2.IsAquifer = layerFromOldSurfaces.IsAquifer; - soilLayer2D2.WaterpressureInterpolationModel = layerFromOldSurfaces.WaterpressureInterpolationModel; + soilLayer2D.Soil = layerFromOldSurfaces.Soil; + soilLayer2D.IsAquifer = layerFromOldSurfaces.IsAquifer; + soilLayer2D.WaterpressureInterpolationModel = layerFromOldSurfaces.WaterpressureInterpolationModel; } if (layerFromOldSurfaces == null) { - SoilLayer2D oldLayer = null; - bool isDefaultLayer = IsLayerAboveOriginalSurfaceLine(soilLayer2D2, surfaceLine); - if (!isDefaultLayer) + SoilLayer2D oldLayer = DetermineLayerIfSurfaceIsLeftOrRightOfOldSurfaces(surface, oldSurfaces); + + if (oldLayer != null) { - oldLayer = DetermineLayerIfSurfaceIsLeftOrRightOfOldSurfaces(surface, oldSurfaces); - isDefaultLayer = oldLayer == null; + soilLayer2D.IsAquifer = oldLayer.IsAquifer; + soilLayer2D.WaterpressureInterpolationModel = oldLayer.WaterpressureInterpolationModel; + soilLayer2D.SoilName = oldLayer.SoilName; + soilLayer2D.Soil = oldLayer.Soil; } - - if (!isDefaultLayer) - { - soilLayer2D2.IsAquifer = oldLayer.IsAquifer; - soilLayer2D2.WaterpressureInterpolationModel = oldLayer.WaterpressureInterpolationModel; - soilLayer2D2.SoilName = oldLayer.SoilName; - soilLayer2D2.Soil = oldLayer.Soil; - } else { - soilLayer2D2.IsAquifer = false; - soilLayer2D2.WaterpressureInterpolationModel = WaterpressureInterpolationModel.Automatic; - soilLayer2D2.SoilName = defaultSoil.Name; - soilLayer2D2.Soil = defaultSoil; + soilLayer2D.IsAquifer = false; + soilLayer2D.WaterpressureInterpolationModel = WaterpressureInterpolationModel.Automatic; + soilLayer2D.SoilName = defaultSoil.Name; + soilLayer2D.Soil = defaultSoil; } } - - result.Surfaces.Add(soilLayer2D2); + result.Surfaces.Add(soilLayer2D); } } @@ -395,8 +392,15 @@ } } - private static SoilLayer2D DetermineLayerIfSurfaceIsLeftOrRightOfOldSurfaces(GeometrySurface surface, List oldSurfaces) + private static SoilLayer2D DetermineLayerIfSurfaceIsLeftOrRightOfOldSurfaces(GeometrySurface surface, + List oldSurfaces) { + Point2D point = surface.DetermineValidTestPointBasedOnNewSurface(); + if (!SoilProfile2D.IsSurfaceLeftOrRightOfOldSurfaces(point, oldSurfaces)) + { + return null; + } + double[] xMin = surface.OuterLoop.Points.Select(p => p.X).OrderBy(x => x).Distinct().ToArray(); double[] zMin = surface.OuterLoop.Points.Select(p => p.Z).OrderBy(z => z).Distinct().ToArray(); var leftPoint = new Point2D @@ -405,7 +409,7 @@ Z = zMin[0] + 0.1 }; - SoilLayer2D soilLayer = FindLayerFromPointInOldSurfaces(oldSurfaces, leftPoint); + SoilLayer2D soilLayer = SoilProfile2D.DetermineOldSurfaceFromTestPoint(oldSurfaces, leftPoint); if (soilLayer != null) { return soilLayer; @@ -417,21 +421,8 @@ Z = zMin[0] + 0.1 }; - soilLayer = FindLayerFromPointInOldSurfaces(oldSurfaces, rightPoint); + soilLayer = SoilProfile2D.DetermineOldSurfaceFromTestPoint(oldSurfaces, rightPoint); return soilLayer; } - - private static SoilLayer2D FindLayerFromPointInOldSurfaces(List oldSurfaces, Point2D searchPoint) - { - for (var i = 0; i < oldSurfaces.Count; i++) - { - bool find = oldSurfaces[i].GeometrySurface.OuterLoop.IsPointInLoopArea(searchPoint); - if (find) - { - return oldSurfaces[i]; - } - } - - return null; - } + } \ No newline at end of file Index: DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/IssuesTests.cs =================================================================== diff -u -r6404 -r6557 --- DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/IssuesTests.cs (.../IssuesTests.cs) (revision 6404) +++ DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/IssuesTests.cs (.../IssuesTests.cs) (revision 6557) @@ -36,11 +36,11 @@ private const string tutorialStability2D = @"TestFiles\InputTutorialStability2D.xml"; [Test] - [TestCase("DWP_1", 19, 81, 63, 35, 1.248)] + [TestCase("DWP_1", 19, 81, 63, 35, 1.245)] [TestCase("DWP_2", 12, 72, 61, 38, 1.398)] [TestCase("DWP_6", 15, 79, 65, 45, 1.503)] [TestCase("DWP_7", 9, 65, 57, 37, 1.264)] - [TestCase("DWP_8", 27, 117, 91, 46, 0.989)] + [TestCase("DWP_8", 27, 117, 91, 46, 1.020)] [TestCase("DWP_16", 26, 99, 74, 39, 0.713)] [TestCase("DWP_17", 19, 82, 64, 32, 1.256)] [TestCase("DWP_20", 24, 102, 79, 46, 1.523)] Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometrySurface.cs =================================================================== diff -u -r6404 -r6557 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometrySurface.cs (.../GeometrySurface.cs) (revision 6404) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometrySurface.cs (.../GeometrySurface.cs) (revision 6557) @@ -32,7 +32,7 @@ [Serializable] public class GeometrySurface : GeometryObject { - private GeometryLoop outerLoop = new GeometryLoop(); + private GeometryLoop outerLoop = new(); /// /// Empty constructor @@ -166,7 +166,71 @@ { return OuterLoop.GetGeometryBounds(); } - + + /// + /// Determines a point within the outer loop of the new surface and that is not in an inner loop of that surface + /// so it can be used to determine the old surface. + /// + /// + /// The point or null when no valid point is found. + public Point2D DetermineValidTestPointBasedOnNewSurface() + { + const double offset = 0.002; + var point = new Point2D(); + var geometryPointString = DetermineTopGeometrySurface(); + geometryPointString.SortPointsByXAscending(); + for (int i = 0; i < geometryPointString.Count - 1; i++) + { + // look if point just below the top line is in the outer loop and if so, is not in a inner loop + // If both are true, then a valid test point is found, else keep looking + point.X = (geometryPointString[i].X + geometryPointString[i + 1].X) * 0.5; + point.Z = (geometryPointString[i].Z + geometryPointString[i + 1].Z) * 0.5 - offset; + if (Routines2D.CheckIfPointIsInPolygon(OuterLoop, point.X, point.Z) == PointInPolygon.InsidePolygon) + { + var isInInnerLoop = false; + foreach (GeometryLoop innerLoop in InnerLoops) + { + if (Routines2D.CheckIfPointIsInPolygon(innerLoop, point.X, point.Z) == PointInPolygon.InsidePolygon) + { + isInInnerLoop = true; + } + } + if (!isInInnerLoop) + { + break; + } + } + if (i == geometryPointString.Count - 2) + { + // if no valid point is found, then the shape is very awkward or the surface is terribly small. + // In that case, return center point. + point = DetermineCenterPoint(); + } + } + return point; + } + + /// + /// Determine the center point of the surface + /// + /// Center point + private Point2D DetermineCenterPoint() + { + double summedX = 0; + double summedZ = 0; + foreach (Point2D outerLoopPoint in OuterLoop.Points) + { + summedX += outerLoopPoint.X; + summedZ += outerLoopPoint.Z; + } + var point = new Point2D + { + X = summedX / OuterLoop.Points.Count, + Z = summedZ / OuterLoop.Points.Count + }; + return point; + } + private bool HasIdenticalInnerLoop(GeometryLoop loop) { return InnerLoops.Any(innerLoop => innerLoop.HasSameCurves(loop)); Index: DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geometry/GeometrySurfaceTests.cs =================================================================== diff -u --- DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geometry/GeometrySurfaceTests.cs (revision 0) +++ DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geometry/GeometrySurfaceTests.cs (revision 6557) @@ -0,0 +1,169 @@ +// Copyright (C) Stichting Deltares 2025. All rights reserved. +// +// This file is part of the Dam Engine. +// +// The Dam Engine is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU Affero General Public License for more details. +// +// You should have received a copy of the GNU Affero General Public License +// along with this program. If not, see . +// +// All names, logos, and references to "Deltares" are registered trademarks of +// Stichting Deltares and remain full property of Stichting Deltares at all times. +// All rights reserved. + +using Deltares.DamEngine.Data.Geometry; +using NUnit.Framework; + +namespace Deltares.DamEngine.Data.Tests.Geometry; + +[TestFixture] +public class GeometrySurfaceTests +{ + private const double cTolerance = 1e-5; + [Test] + public void TestDetermineValidTestPointBasedOnNewSurfaceWithDonutGeometry() + { + GeometryData geometry = CreateDonutGeometry(); + Point2D testPoint = geometry.Surfaces[0].DetermineValidTestPointBasedOnNewSurface(); + Assert.Multiple(() => + { + Assert.That(testPoint.X, Is.EqualTo(5).Within(cTolerance)); + Assert.That(testPoint.Z, Is.EqualTo(9.998).Within(cTolerance)); + }); + testPoint = geometry.Surfaces[1].DetermineValidTestPointBasedOnNewSurface(); + Assert.Multiple(() => + { + Assert.That(testPoint.X, Is.EqualTo(5).Within(cTolerance)); + Assert.That(testPoint.Z, Is.EqualTo(6.998).Within(cTolerance)); + }); + } + + [Test] + public void TestDetermineValidTestPointBasedOnNewSurfaceWithPointedGeomertyForCenterPoint() + { + GeometryData geometry = CreatePointedGeometry(); + Point2D testPoint = geometry.Surfaces[0].DetermineValidTestPointBasedOnNewSurface(); + Assert.Multiple(() => + { + Assert.That(testPoint.X, Is.EqualTo(9.66666).Within(cTolerance)); + Assert.That(testPoint.Z, Is.EqualTo(9.999666).Within(cTolerance)); + }); + } + + private GeometryData CreateDonutGeometry() + { + var geometryModel = new GeometryData + { + Left = -10, + Bottom = -10, + Right = 20 + }; + + /* The following model looks as follows + * + * |----------| + * | ------ | + * | | | | + * | | | | + * | ------ | + * |----------| + * + */ + + var point1 = new Point2D(0, 0); + var point2 = new Point2D(0, 10); + var point3 = new Point2D(10, 10); + var point4 = new Point2D(10, 0); + var point5 = new Point2D(3, 3); + var point6 = new Point2D(3, 7); + var point7 = new Point2D(7, 7); + var point8 = new Point2D(7, 3); + + var curve1 = new GeometryCurve(point1, point2); + var curve2 = new GeometryCurve(point2, point3); + var curve3 = new GeometryCurve(point3, point4); + var curve4 = new GeometryCurve(point4, point1); + var curve5 = new GeometryCurve(point5, point6); + var curve6 = new GeometryCurve(point6, point7); + var curve7 = new GeometryCurve(point7, point8); + var curve8 = new GeometryCurve(point8, point5); + + geometryModel.Points.AddRange(new[] + { + point1, + point2, + point3, + point4, + point5, + point6, + point7, + point8 + }); + geometryModel.Curves.AddRange(new[] + { + curve1, + curve2, + curve3, + curve4, + curve5, + curve6, + curve7, + curve8 + }); + + geometryModel.NewlyEffectedPoints.AddRange(geometryModel.Points); + geometryModel.NewlyEffectedCurves.AddRange(geometryModel.Curves); + geometryModel.RegenerateGeometry(); + return geometryModel; + } + + private GeometryData CreatePointedGeometry() + { + var geometryModel = new GeometryData + { + Left = -10, + Bottom = -10, + Right = 20 + }; + + /* The following model looks as follows + * + * |----------------------------------------------------------------------------------------------------------| + * -----------------------------| + */ + + var point1 = new Point2D(-8, 10); + var point2 = new Point2D(19, 10); + var point3 = new Point2D(18, 9.999); + + var curve1 = new GeometryCurve(point1, point2); + var curve2 = new GeometryCurve(point2, point3); + var curve3 = new GeometryCurve(point3, point1); + + geometryModel.Points.AddRange(new[] + { + point1, + point2, + point3 + }); + geometryModel.Curves.AddRange(new[] + { + curve1, + curve2, + curve3 + }); + + geometryModel.NewlyEffectedPoints.AddRange(geometryModel.Points); + geometryModel.NewlyEffectedCurves.AddRange(geometryModel.Curves); + geometryModel.RegenerateGeometry(); + return geometryModel; + } +} \ No newline at end of file