Index: DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geotechnics/SoilProfile2DSurfaceLineHelperTests.cs =================================================================== diff -u --- DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geotechnics/SoilProfile2DSurfaceLineHelperTests.cs (revision 0) +++ DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geotechnics/SoilProfile2DSurfaceLineHelperTests.cs (revision 4759) @@ -0,0 +1,91 @@ +// Copyright (C) Stichting Deltares 2024. 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 System.Linq; +using Deltares.DamEngine.Data.Geometry; +using Deltares.DamEngine.Data.Geotechnics; +using Deltares.DamEngine.TestHelpers.Factories; +using NUnit.Framework; + +namespace Deltares.DamEngine.Data.Tests.Geotechnics; + +[TestFixture] +public class SoilProfile2DSurfaceLineHelperTests +{ + [Test] + [TestCase(PositionToSoilProfile2D.LeftOfSoilProfile, false)] + [TestCase(PositionToSoilProfile2D.RightOfSoilProfile, false)] + [TestCase(PositionToSoilProfile2D.OnSoilProfile, true)] + [TestCase(PositionToSoilProfile2D.InsideOfSoilProfile, true)] + public void GivenSurfaceLineAndSoilProfile2D_WhenCheckIsSurfaceLineInsideSoilProfile2D_ThenReturnCorrectResult(PositionToSoilProfile2D positionToSoilProfile2D, bool result) + { + // Given + SoilProfile2D soilProfile2D = FactoryForSoilProfiles.CreateSoilProfile2DWithOneLayer(); + SurfaceLine2 surfaceLine = CreateSurfaceLineForSoilProfile2D(soilProfile2D, positionToSoilProfile2D); + + // When-Then + Assert.That(SoilProfile2DSurfaceLineHelper.IsSurfaceLineInsideSoilProfile2D(surfaceLine, soilProfile2D), Is.EqualTo(result)); + } + + public enum PositionToSoilProfile2D + { + LeftOfSoilProfile, + RightOfSoilProfile, + OnSoilProfile, + InsideOfSoilProfile + } + + private static SurfaceLine2 CreateSurfaceLineForSoilProfile2D(SoilProfile2D soilProfile2D, PositionToSoilProfile2D positionToSoilProfile2D) + { + GeometryPoint geometryPoint = soilProfile2D.Geometry.SurfaceLine.Points.First(); + var leftPoint = new GeometryPoint(geometryPoint.X, geometryPoint.Z); + geometryPoint = soilProfile2D.Geometry.SurfaceLine.Points.Last(); + var rightPoint = new GeometryPoint(geometryPoint.X, geometryPoint.Z); + var middlePoint = new GeometryPoint((leftPoint.X + rightPoint.X) / 2, (leftPoint.Z + rightPoint.Z) / 2); + switch (positionToSoilProfile2D) + { + case PositionToSoilProfile2D.LeftOfSoilProfile: + leftPoint.X -= 1; + break; + case PositionToSoilProfile2D.RightOfSoilProfile: + rightPoint.X += 1; + break; + case PositionToSoilProfile2D.OnSoilProfile: + break; + case PositionToSoilProfile2D.InsideOfSoilProfile: + leftPoint.X += 1; + rightPoint.X -= 1; + break; + } + + SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[] + { + leftPoint, + middlePoint, + rightPoint + }); + surfaceLine.CharacteristicPoints.Add(new CharacteristicPoint(surfaceLine.CharacteristicPoints, leftPoint)); + surfaceLine.CharacteristicPoints.Annotate(0, CharacteristicPointType.SurfaceLevelOutside); + surfaceLine.CharacteristicPoints.Add(new CharacteristicPoint(surfaceLine.CharacteristicPoints, rightPoint)); + surfaceLine.CharacteristicPoints.Annotate(1, CharacteristicPointType.SurfaceLevelInside); + return surfaceLine; + } +} \ No newline at end of file Index: DamEngine/trunk/src/Deltares.DamEngine.TestHelpers/Factories/FactoryForSoilProfiles.cs =================================================================== diff -u -r4540 -r4759 --- DamEngine/trunk/src/Deltares.DamEngine.TestHelpers/Factories/FactoryForSoilProfiles.cs (.../FactoryForSoilProfiles.cs) (revision 4540) +++ DamEngine/trunk/src/Deltares.DamEngine.TestHelpers/Factories/FactoryForSoilProfiles.cs (.../FactoryForSoilProfiles.cs) (revision 4759) @@ -19,8 +19,12 @@ // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. +using System; +using System.Collections.Generic; using Deltares.DamEngine.Data.General; +using Deltares.DamEngine.Data.Geometry; using Deltares.DamEngine.Data.Geotechnics; +using Deltares.DamEngine.Data.Standard; namespace Deltares.DamEngine.TestHelpers.Factories; @@ -952,6 +956,80 @@ return soilProfile; } + /// + /// Create a soil layer with the given top level and soil name + /// + /// The toplevel. + /// The soil name + /// + public static SoilLayer1D CreateSoilLayer(double topLevel, string soilName) + { + var random = new Random(soilName.GetHashCode()); + + Array values = Enum.GetValues(typeof(WaterpressureInterpolationModel)); + var model = (WaterpressureInterpolationModel) values.GetValue(random.Next(values.Length)); + + return new SoilLayer1D + { + TopLevel = topLevel, + Soil = new Soil(soilName), + IsAquifer = Convert.ToBoolean(random.Next(0, 2)), + WaterpressureInterpolationModel = model + }; + } + + /// + /// Create a surface line with the given coordinates + /// + /// + /// + public static SurfaceLine2 CreateSurfaceLine(IEnumerable coordinates) + { + var surfaceLine = new SurfaceLine2(); + surfaceLine.Geometry.Points.AddRange(coordinates); + surfaceLine.Geometry.SyncCalcPoints(); + + return surfaceLine; + } + + /// + /// Create a soil profile 2D with one layer + /// + /// + public static SoilProfile2D CreateSoilProfile2DWithOneLayer() + { + const string layerName = "Layer"; + const string topLayerName = "TopLayer"; + + SoilLayer1D soilLayer = CreateSoilLayer(-5, layerName); + + var profile = new SoilProfile1D + { + BottomLevel = -10 + }; + profile.Layers.Add(soilLayer); + + SurfaceLine2 surfaceLine = CreateSurfaceLine(new[] + { + new GeometryPoint(0, 0), + new GeometryPoint(5, 10), + new GeometryPoint(10, 10) + }); + + var soilSurfaceProfile = new SoilSurfaceProfile + { + SoilProfile = profile, + SurfaceLine2 = surfaceLine, + DikeEmbankmentMaterial = new Soil + { + Name = topLayerName + } + }; + + SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D(); + return soilProfile2D; + } + private static string GetNewUniqueLayerId(SoilProfile1D soilProfile1D) { var num = 0; Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilProfile2DSurfaceLineHelper.cs =================================================================== diff -u --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilProfile2DSurfaceLineHelper.cs (revision 0) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilProfile2DSurfaceLineHelper.cs (revision 4759) @@ -0,0 +1,53 @@ +// Copyright (C) Stichting Deltares 2024. 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 System.Linq; + +namespace Deltares.DamEngine.Data.Geotechnics; + +/// +/// Helper class for SoilProfile2D and SurfaceLine2 +/// +public static class SoilProfile2DSurfaceLineHelper +{ + /// + /// Determines if the surface line is inside the soil profile. + /// + /// The surface-line. + /// The soil profile 2D + /// + public static bool IsSurfaceLineInsideSoilProfile2D(SurfaceLine2 surfaceLine, SoilProfile2D soilProfile2D) + { + if (soilProfile2D == null) + { + return false; + } + if (surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelOutside).X < soilProfile2D.Geometry.SurfaceLine.Points.First().X) + { + return false; + } + if (surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelInside).X > soilProfile2D.Geometry.SurfaceLine.Points.Last().X) + { + return false; + } + return true; + } +} \ No newline at end of file Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/KernelWrappers/MacroStabilityInwards/MacroStabilityInwardsKernelWrapper.cs =================================================================== diff -u -r4540 -r4759 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/KernelWrappers/MacroStabilityInwards/MacroStabilityInwardsKernelWrapper.cs (.../MacroStabilityInwardsKernelWrapper.cs) (revision 4540) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/KernelWrappers/MacroStabilityInwards/MacroStabilityInwardsKernelWrapper.cs (.../MacroStabilityInwardsKernelWrapper.cs) (revision 4759) @@ -104,6 +104,16 @@ macroStabilityCommonHelper.EnsureSoilProfile2DIsFilled(damKernelInput.SubSoilScenario, damKernelInput.Location.SurfaceLine, damKernelInput.Location.GetDikeEmbankmentSoil()); + // Check if the surface-line is within the SoilProfile2D boundaries (left/right) + if (!SoilProfile2DSurfaceLineHelper.IsSurfaceLineInsideSoilProfile2D(damKernelInput.Location.SurfaceLine, damKernelInput.SubSoilScenario.SoilProfile2D)) + { + macroStabilityOutput.Message = new LogMessage + { + MessageType = LogMessageType.FatalError, + Message = $"SurfaceLine {damKernelInput.Location.SurfaceLine.Name} does not fit within the boundaries of soil profile {damKernelInput.SubSoilScenario.SoilProfile2D.Name}" + }; + return PrepareResult.Failed; + } const bool useRiverLevelLow = false; // Determine whether there is uplift Index: DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geotechnics/SoilSurfaceProfileTests.cs =================================================================== diff -u -r4540 -r4759 --- DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geotechnics/SoilSurfaceProfileTests.cs (.../SoilSurfaceProfileTests.cs) (revision 4540) +++ DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geotechnics/SoilSurfaceProfileTests.cs (.../SoilSurfaceProfileTests.cs) (revision 4759) @@ -19,12 +19,11 @@ // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. -using System; using System.Collections.Generic; using System.Linq; using Deltares.DamEngine.Data.Geometry; using Deltares.DamEngine.Data.Geotechnics; -using Deltares.DamEngine.Data.Standard; +using Deltares.DamEngine.TestHelpers.Factories; using NUnit.Framework; namespace Deltares.DamEngine.Data.Tests.Geotechnics; @@ -40,8 +39,8 @@ const string middleLayerName = "MiddleLayer"; const string topLayerName = "TopLayer"; - SoilLayer1D bottomLayer = CreateSoilLayer(-5, bottomLayerName); - SoilLayer1D middleLayer = CreateSoilLayer(-2, middleLayerName); + SoilLayer1D bottomLayer = FactoryForSoilProfiles.CreateSoilLayer(-5, bottomLayerName); + SoilLayer1D middleLayer = FactoryForSoilProfiles.CreateSoilLayer(-2, middleLayerName); var profile = new SoilProfile1D { @@ -50,7 +49,7 @@ profile.Layers.Add(bottomLayer); profile.Layers.Add(middleLayer); - SurfaceLine2 surfaceLine = CreateSurfaceLine(new[] + SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[] { new GeometryPoint(0, 0), new GeometryPoint(5, 10), @@ -119,9 +118,9 @@ const string middleLayerName = "MiddleLayer"; const string topLayerName = "TopLayer"; - SoilLayer1D irrelevantLayer = CreateSoilLayer(0, "Does not matter"); - SoilLayer1D bottomLayer = CreateSoilLayer(-5, bottomLayerName); - SoilLayer1D middleLayer = CreateSoilLayer(-2, middleLayerName); + SoilLayer1D irrelevantLayer = FactoryForSoilProfiles.CreateSoilLayer(0, "Does not matter"); + SoilLayer1D bottomLayer = FactoryForSoilProfiles.CreateSoilLayer(-5, bottomLayerName); + SoilLayer1D middleLayer = FactoryForSoilProfiles.CreateSoilLayer(-2, middleLayerName); var profile = new SoilProfile1D { @@ -131,7 +130,7 @@ profile.Layers.Add(middleLayer); profile.Layers.Add(irrelevantLayer); - SurfaceLine2 surfaceLine = CreateSurfaceLine(new[] + SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[] { new GeometryPoint(0, -5), new GeometryPoint(5, -3), @@ -186,15 +185,15 @@ const string middleLayerName = "MiddleLayer"; const string topLayerName = "TopLayer"; - SoilLayer1D bottomLayer = CreateSoilLayer(-5, bottomLayerName); - SoilLayer1D middleLayer = CreateSoilLayer(-2, middleLayerName); + SoilLayer1D bottomLayer = FactoryForSoilProfiles.CreateSoilLayer(-5, bottomLayerName); + SoilLayer1D middleLayer = FactoryForSoilProfiles.CreateSoilLayer(-2, middleLayerName); var profile = new SoilProfile1D(); profile.Layers.Add(bottomLayer); profile.Layers.Add(middleLayer); profile.BottomLevel = -10; - SurfaceLine2 surfaceLine = CreateSurfaceLine(new[] + SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[] { new GeometryPoint(0, -4), new GeometryPoint(5, -2.5), @@ -251,15 +250,15 @@ const string middleLayerName = "MiddleLayer"; const string topLayerName = "TopLayer"; - SoilLayer1D bottomLayer = CreateSoilLayer(-5, bottomLayerName); - SoilLayer1D middleLayer = CreateSoilLayer(0, middleLayerName); + SoilLayer1D bottomLayer = FactoryForSoilProfiles.CreateSoilLayer(-5, bottomLayerName); + SoilLayer1D middleLayer = FactoryForSoilProfiles.CreateSoilLayer(0, middleLayerName); var profile = new SoilProfile1D(); profile.Layers.Add(bottomLayer); profile.Layers.Add(middleLayer); profile.BottomLevel = -10; - SurfaceLine2 surfaceLine = CreateSurfaceLine(new[] + SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[] { new GeometryPoint(0, -2.5), new GeometryPoint(5, 2.5), @@ -334,15 +333,15 @@ const string middleLayerName = "MiddleLayer"; const string topLayerName = "TopLayer"; - SoilLayer1D bottomLayer = CreateSoilLayer(-1.25, bottomLayerName); - SoilLayer1D middleLayer = CreateSoilLayer(0, middleLayerName); + SoilLayer1D bottomLayer = FactoryForSoilProfiles.CreateSoilLayer(-1.25, bottomLayerName); + SoilLayer1D middleLayer = FactoryForSoilProfiles.CreateSoilLayer(0, middleLayerName); var profile = new SoilProfile1D(); profile.Layers.Add(bottomLayer); profile.Layers.Add(middleLayer); profile.BottomLevel = -10; - SurfaceLine2 surfaceLine = CreateSurfaceLine(new[] + SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[] { new GeometryPoint(0, 2.5), new GeometryPoint(5, -2.5), @@ -439,15 +438,15 @@ const string middleLayerName = "MiddleLayer"; const string topLayerName = "TopLayer"; - SoilLayer1D bottomLayer = CreateSoilLayer(-2.5, bottomLayerName); - SoilLayer1D middleLayer = CreateSoilLayer(0, middleLayerName); + SoilLayer1D bottomLayer = FactoryForSoilProfiles.CreateSoilLayer(-2.5, bottomLayerName); + SoilLayer1D middleLayer = FactoryForSoilProfiles.CreateSoilLayer(0, middleLayerName); var profile = new SoilProfile1D(); profile.Layers.Add(bottomLayer); profile.Layers.Add(middleLayer); profile.BottomLevel = -10; - SurfaceLine2 surfaceLine = CreateSurfaceLine(new[] + SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[] { new GeometryPoint(0, 2.5), new GeometryPoint(5, -2.5), @@ -540,15 +539,15 @@ const string middleLayerName = "MiddleLayer"; const string topLayerName = "TopLayer"; - SoilLayer1D bottomLayer = CreateSoilLayer(-2.5, bottomLayerName); - SoilLayer1D middleLayer = CreateSoilLayer(0, middleLayerName); + SoilLayer1D bottomLayer = FactoryForSoilProfiles.CreateSoilLayer(-2.5, bottomLayerName); + SoilLayer1D middleLayer = FactoryForSoilProfiles.CreateSoilLayer(0, middleLayerName); var profile = new SoilProfile1D(); profile.Layers.Add(bottomLayer); profile.Layers.Add(middleLayer); profile.BottomLevel = -10; - SurfaceLine2 surfaceLine = CreateSurfaceLine(new[] + SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[] { new GeometryPoint(0, 2.5), new GeometryPoint(5, -2.5), @@ -644,15 +643,15 @@ const string middleLayerName = "MiddleLayer"; const string topLayerName = "TopLayer"; - SoilLayer1D bottomLayer = CreateSoilLayer(-2.5, bottomLayerName); - SoilLayer1D middleLayer = CreateSoilLayer(0, middleLayerName); + SoilLayer1D bottomLayer = FactoryForSoilProfiles.CreateSoilLayer(-2.5, bottomLayerName); + SoilLayer1D middleLayer = FactoryForSoilProfiles.CreateSoilLayer(0, middleLayerName); var profile = new SoilProfile1D(); profile.Layers.Add(bottomLayer); profile.Layers.Add(middleLayer); profile.BottomLevel = -10; - SurfaceLine2 surfaceLine = CreateSurfaceLine(new[] + SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[] { new GeometryPoint(0, -2.5), new GeometryPoint(5, -2.5), @@ -751,29 +750,4 @@ Assert.That(actualSoilLayer.WaterpressureInterpolationModel, Is.EqualTo(WaterpressureInterpolationModel.Hydrostatic)); Assert.That(actualSoilLayer.Soil, Is.SameAs(expectedProfile.DikeEmbankmentMaterial)); } - - private static SoilLayer1D CreateSoilLayer(double topLevel, string soilName) - { - var random = new Random(soilName.GetHashCode()); - - Array values = Enum.GetValues(typeof(WaterpressureInterpolationModel)); - var model = (WaterpressureInterpolationModel) values.GetValue(random.Next(values.Length)); - - return new SoilLayer1D - { - TopLevel = topLevel, - Soil = new Soil(soilName), - IsAquifer = Convert.ToBoolean(random.Next(0, 2)), - WaterpressureInterpolationModel = model - }; - } - - private static SurfaceLine2 CreateSurfaceLine(IEnumerable coordinates) - { - var surfaceLine = new SurfaceLine2(); - surfaceLine.Geometry.Points.AddRange(coordinates); - surfaceLine.Geometry.SyncCalcPoints(); - - return surfaceLine; - } } \ No newline at end of file Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilProfileHelper.cs =================================================================== diff -u -r4540 -r4759 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilProfileHelper.cs (.../SoilProfileHelper.cs) (revision 4540) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilProfileHelper.cs (.../SoilProfileHelper.cs) (revision 4759) @@ -27,7 +27,7 @@ public class SoilProfileHelper { /// - /// Determines for surface line corrected1 d profile at x. + /// Determines for surface line corrected 1d profile at x. /// /// The original soil profile1 d. /// The surface line. Index: DamEngine/trunk/src/Deltares.DamEngine.TestHelpers/GeneralHelper.cs =================================================================== diff -u -r4627 -r4759 --- DamEngine/trunk/src/Deltares.DamEngine.TestHelpers/GeneralHelper.cs (.../GeneralHelper.cs) (revision 4627) +++ DamEngine/trunk/src/Deltares.DamEngine.TestHelpers/GeneralHelper.cs (.../GeneralHelper.cs) (revision 4759) @@ -79,8 +79,6 @@ File.WriteAllText(outputXml, outputString, Encoding.Unicode); } - CheckDependencyOnStiFiles(output); - // Evaluate results if (!areResultsExpected) { @@ -115,20 +113,6 @@ return output; } - private static void CheckDependencyOnStiFiles(Output output) - { - foreach (Message calcMessage in output.Results.CalculationMessages) - { - if ((calcMessage.MessageType == MessageMessageType.Error) & calcMessage.Message1.Contains("The preparation for this " + - "calculation failed")) - { - string assertMessage = "No results available due to dependency on 2D geometries (sti files) and the old " + - "MacroStability kernel wrapper implementation"; - Assert.That(output.Results.CalculationResults, Is.Not.Null, assertMessage); - } - } - } - private static void CheckConsistencyOfAdaptGeometryResults(EngineInterface engineInterface, OutputResults outputResults) { if (engineInterface.DamProjectData.DamProjectCalculationSpecification.AnalysisTypeForSerializationPurposeOnly == AnalysisType.AdaptGeometry)