Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilProfile2D.cs =================================================================== diff -u -r6557 -r7060 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilProfile2D.cs (.../SoilProfile2D.cs) (revision 6557) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilProfile2D.cs (.../SoilProfile2D.cs) (revision 7060) @@ -272,6 +272,12 @@ soilProfile.BottomLevel = detector.LayerList[detector.LayerList.Count - 1].EndPoint.Z; for (var i = 0; i < detector.LayerList.Count; i++) { + bool isHolePresentBeforeLayer = (i > 0) && (Math.Abs(detector.LayerList[i].StartPoint.Z - detector.LayerList[i -1].EndPoint.Z) > 1e-3); + if (isHolePresentBeforeLayer) + { + var emptyLayer = new SoilLayer1D(null, detector.LayerList[i - 1].EndPoint.Z); + soilProfile.Layers.Add(emptyLayer); + } var layer = new SoilLayer1D(detector.LayerList[i].Soil, detector.LayerList[i].StartPoint.Z) { IsAquifer = detector.LayerList[i].IsAquifer, Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/KernelWrappers/MacroStabilityCommon/MacroStabilityCommonHelper.cs =================================================================== diff -u -r6677 -r7060 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/KernelWrappers/MacroStabilityCommon/MacroStabilityCommonHelper.cs (.../MacroStabilityCommonHelper.cs) (revision 6677) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/KernelWrappers/MacroStabilityCommon/MacroStabilityCommonHelper.cs (.../MacroStabilityCommonHelper.cs) (revision 7060) @@ -551,10 +551,11 @@ ValidateForCombineSoilProfile2DWithSurfaceLine(subSoilScenario, surfaceLine2, dikeEmbankmentSoil); subSoilScenario.SoilProfile2D = SoilProfile2DSurfaceLineHelper.CombineSurfaceLineWithSoilProfile2D(surfaceLine2.Geometry, subSoilScenario.SoilProfile2D, dikeEmbankmentSoil); - CorrectSurfacelinePointsForGeometryCoordinates(subSoilScenario.SoilProfile2D.Geometry, surfaceLine2); + CorrectSurfaceLinePointsForGeometryCoordinates(subSoilScenario.SoilProfile2D.Geometry, surfaceLine2); + CheckIfAllLayersWereCorrectlyGenerated(subSoilScenario.SoilProfile2D, surfaceLine2); } - private static void CorrectSurfacelinePointsForGeometryCoordinates(GeometryData geometry, SurfaceLine2 surfaceLine) + private static void CorrectSurfaceLinePointsForGeometryCoordinates(GeometryData geometry, SurfaceLine2 surfaceLine) { foreach (Point2D surfaceLinePoint in surfaceLine.Geometry.Points) { @@ -569,6 +570,25 @@ RemovePointsAtSameXLocation(surfaceLine); } + private static void CheckIfAllLayersWereCorrectlyGenerated(SoilProfile2D soilProfile2D, SurfaceLine2 surfaceLine) + { + for (var i = 0; i < surfaceLine.Geometry.Points.Count; i++) + { + Point2D surfaceLinePoint = surfaceLine.Geometry.Points[i]; + SoilProfile1D geometry1D = soilProfile2D.GetSoilProfile1D(surfaceLinePoint.X); + bool profileContainsHole = geometry1D.Layers.Any(layer => layer.Soil == null); + // Check if the top layer is generated correctly. + // Do not check the first and last points because the 1D profile is not exactly at the X position. + bool topLayerNotGenerated = i > 0 && i < surfaceLine.Geometry.Points.Count - 1 && + Math.Abs(geometry1D.TopLevel - surfaceLinePoint.Z) > 2 * GeometryConstants.Accuracy; + + if (profileContainsHole || topLayerNotGenerated) + { + throw new Exception(Resources.MacroStabilityKernelWrapper_SoilProfile2DHasMissingLayers); + } + } + } + /// /// Removes points with same X coordinates and different Z /// Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/Properties/Resources.resx =================================================================== diff -u -r7002 -r7060 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/Properties/Resources.resx (.../Resources.resx) (revision 7002) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/Properties/Resources.resx (.../Resources.resx) (revision 7060) @@ -256,6 +256,13 @@ Prepare of calculator for Macro Stability did not succeed + + DAM was unable to generate a valid soil profile 2D when combining the surface line given in the CSV file with the soil profile given in the STIX file. + The most plausible underlying cause is that the geometric intersection results in residual soil layers with extremely small thickness (thinner than 1 mm), + which are not supported by the algorithm. + If the surface line provided in the CSV file is intended to coincide exactly with the surface line defined in the STIX file, + ensure that both surface lines contain the same number of points and that their coordinates correspond one‑to‑one. + No soil profiles available for location '{0}' Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/Properties/Resources.Designer.cs =================================================================== diff -u -r6895 -r7060 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/Properties/Resources.Designer.cs (.../Resources.Designer.cs) (revision 6895) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/Properties/Resources.Designer.cs (.../Resources.Designer.cs) (revision 7060) @@ -250,8 +250,17 @@ } /// - /// Looks up a localized string similar to River level ({0}) is below surface level at river side ({1}).. + /// Looks up a localized string similar to The soil profile is not valid. /// + internal static string MacroStabilityKernelWrapper_SoilProfile2DHasMissingLayers { + get { + return ResourceManager.GetString("MacroStabilityKernelWrapper_SoilProfile2DHasMissingLayers", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to River level ({0}) is below surface level at river side ({1}). + /// internal static string MStabXmlDoc_CreateMStabXmlDoc_RiverLevelHighIsBelowSurfaceLevelOutside { get { return ResourceManager.GetString("MStabXmlDoc_CreateMStabXmlDoc_RiverLevelHighIsBelowSurfaceLevelOutside", resourceCulture); Index: DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/IssuesTests.cs =================================================================== diff -u -r7057 -r7060 --- DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/IssuesTests.cs (.../IssuesTests.cs) (revision 7057) +++ DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/IssuesTests.cs (.../IssuesTests.cs) (revision 7060) @@ -19,6 +19,7 @@ // Stichting Deltares and remain full property of Stichting Deltares at all times. // All rights reserved. +using System; using System.IO; using System.Linq; using Deltares.DamEngine.Calculators.KernelWrappers.MacroStabilityCommon; @@ -60,17 +61,18 @@ const string xmlInput = @"TestFiles\InputFileMWDAM-3266.xml"; TestGeometryAndResult(calcDir, xmlInput, location, segment, surfaceCount, curveCount, pointCount, surfaceLinePointCount, safetyFactor); } - - [Test, Category(Categories.WorkInProgress)] - [TestCase("DWP-SC0035+50m_88111_3", "Schermer_sectie_3",24, 248, 227, 177, 999)] - [TestCase("DWP-SC0200+50m_88111_11", "Schermer_sectie_11",15, 191, 177, 84, 0.831)] - [TestCase("DWP_SC0234_88111_13", "Schermer_sectie_13",20, 187, 169, 2, 999)] - [TestCase("DWP_SC0264+50m_88111_14", "Schermer_sectie_14",15, 206, 192, 20, 1.031)] - public void TestGeometryAndResultForIssueMWDAM_3279(string location, string segment, int surfaceCount, int curveCount, int pointCount, int surfaceLinePointCount, double safetyFactor) + + [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) { const string calcDir = "TestGeometryAndResultForIssueMWDAM_3279"; const string xmlInput = @"TestFiles\InputFileMWDAM-3279.xml"; - TestGeometryAndResult(calcDir, xmlInput, location, segment, surfaceCount, curveCount, pointCount, surfaceLinePointCount, safetyFactor); + TestGeometryAndResult(calcDir, xmlInput, location, segment, 0, 0, 0, 0, 0); } private static void TestGeometryAndResult(string calcDirectory, string xmlInput, string location, string segment, int surfaceCount, int curveCount, int pointCount, int surfaceLinePointCount, double safetyFactor) @@ -101,26 +103,44 @@ Soil soil = engineInterface.DamProjectData.Dike.SoilList.GetSoilByName(soilName); // To be able to check the geometry, create it here. SoilGeometryProbability soilProfile2DOriginal = engineInterface.DamProjectData.Segments.First(s => s.Name == segment).SoilProfileProbabilities[0]; - SoilProfile2D soilProfile2D = MacroStabilityCommonHelper.CombineSoilProfileWithSurfaceLine(soilProfile2DOriginal, surfaceLine, soil); - // For debugging purposes - //geometry = soilProfile2D.Geometry; - //GeometryExporter.ExportToFile(geometry, GeometryExporter.VisualizationFolder + location + "GeometryEnd.txt"); - //GeometryExporter.ExportWithSurfaceLineToJsonFile(GeometryExporter.VisualizationFolder + - // GeometryExporter.ExportJasonFile, geometry, surfaceLine.Geometry); - Assert.Multiple(() => + var expectedException = ""; + SoilProfile2D soilProfile2D = null; + try { - Assert.That(soilProfile2D.Geometry.Surfaces, Has.Count.EqualTo(surfaceCount)); - Assert.That(soilProfile2D.Geometry.Curves, Has.Count.EqualTo(curveCount)); - Assert.That(soilProfile2D.Geometry.Points, Has.Count.EqualTo(pointCount)); - Assert.That(soilProfile2D.Geometry.SurfaceLine.Points, Has.Count.EqualTo(surfaceLinePointCount)); - }); - GeneralHelper.RunAfterInputValidation(engineInterface, true, outputName); - int errorCount = GeneralHelper.DetermineNumberOfCalculationErrors(engineInterface.DamProjectData.CalculationMessages); - Assert.Multiple(() => + soilProfile2D = MacroStabilityCommonHelper.CombineSoilProfileWithSurfaceLine(soilProfile2DOriginal, surfaceLine, soil); + // For debugging purposes + //geometry = soilProfile2D.Geometry; + //GeometryExporter.ExportToFile(geometry, GeometryExporter.VisualizationFolder + location + "GeometryEnd.txt"); + //GeometryExporter.ExportWithSurfaceLineToJsonFile(GeometryExporter.VisualizationFolder + + // GeometryExporter.ExportJasonFile, geometry, surfaceLine.Geometry); + } + catch (Exception exception) { - Assert.That(errorCount, Is.EqualTo(0), "There should be no errors during the calculation."); - Assert.That(engineInterface.DamProjectData.DesignCalculations, Has.Count.EqualTo(1), "There should be one design calculation."); - Assert.That(engineInterface.DamProjectData.DesignCalculations[0].SafetyFactor, Is.EqualTo(safetyFactor).Within(0.001), "The safety factor is incorrect."); - }); + expectedException = exception.Message; + } + + if (surfaceCount == 0) + { + Assert.That(expectedException, Does.Contain("DAM kon geen geldig 2D‑grondprofiel genereren bij het " + + "combineren van de hoogtegeometrie uit het CSV‑bestand met het grondprofiel uit het STIX‑bestand.")); + } + else + { + Assert.Multiple(() => + { + Assert.That(soilProfile2D.Geometry.Surfaces, Has.Count.EqualTo(surfaceCount)); + Assert.That(soilProfile2D.Geometry.Curves, Has.Count.EqualTo(curveCount)); + Assert.That(soilProfile2D.Geometry.Points, Has.Count.EqualTo(pointCount)); + Assert.That(soilProfile2D.Geometry.SurfaceLine.Points, Has.Count.EqualTo(surfaceLinePointCount)); + }); + GeneralHelper.RunAfterInputValidation(engineInterface, true, outputName); + int errorCount = GeneralHelper.DetermineNumberOfCalculationErrors(engineInterface.DamProjectData.CalculationMessages); + Assert.Multiple(() => + { + Assert.That(errorCount, Is.EqualTo(0), "There should be no errors during the calculation."); + Assert.That(engineInterface.DamProjectData.DesignCalculations, Has.Count.EqualTo(1), "There should be one design calculation."); + Assert.That(engineInterface.DamProjectData.DesignCalculations[0].SafetyFactor, Is.EqualTo(safetyFactor).Within(0.001), "The safety factor is incorrect."); + }); + } } } \ No newline at end of file Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/Properties/Resources.nl-NL.resx =================================================================== diff -u -r6895 -r7060 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/Properties/Resources.nl-NL.resx (.../Resources.nl-NL.resx) (revision 6895) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/Properties/Resources.nl-NL.resx (.../Resources.nl-NL.resx) (revision 7060) @@ -252,6 +252,13 @@ Voorbereiding van het rekenhart voor Macrostabiliteit is niet geslaagd. + + DAM kon geen geldig 2D‑grondprofiel genereren bij het combineren van de hoogtegeometrie uit het CSV‑bestand met het grondprofiel uit het STIX‑bestand. + De meest waarschijnlijke onderliggende oorzaak is dat de geometrische intersectie leidt tot resterende grondlagen met een zeer geringe dikte (dunner dan 1 mm), + die niet door het algoritme worden ondersteund. + Als de hoogtegeometrie in het CSV‑bestand exact moet samenvallen met de hoogtegeometrie in het STIX‑bestand, + zorg er dan voor dat beide hoogtegeometrieën hetzelfde aantal punten bevatten en dat de coördinaten één‑op‑één overeenkomen. + Geen ondergrond profielen beschikbaar voor locatie '{0}' Index: DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geotechnics/SoilProfile2DTests.cs =================================================================== diff -u -r6404 -r7060 --- DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geotechnics/SoilProfile2DTests.cs (.../SoilProfile2DTests.cs) (revision 6404) +++ DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geotechnics/SoilProfile2DTests.cs (.../SoilProfile2DTests.cs) (revision 7060) @@ -141,8 +141,31 @@ }); } - private static void CompareSoilProfile2D(SoilProfile2D sourceSoilProfile2D, SoilProfile2D targetSoilProfile2D) + [Test] + public void GivenSoilProfile2DWithHole_WhenDetermining1DProfileAlongTheHole_ReturnsHoleAsEmptySoil() { + // Given + SoilProfile2D soilProfile2D = FactoryForSoilProfiles.CreateSoilProfile2DWithHole(); + + // When + SoilProfile1D soilProfile1D = soilProfile2D.GetSoilProfile1D(25); + + // Then + Assert.That(soilProfile1D.Layers, Has.Count.EqualTo(3)); + Assert.Multiple(() => + { + Assert.That(soilProfile1D.Layers[0].TopLevel, Is.EqualTo(10).Within(precison10Decimals)); + Assert.That(soilProfile1D.Layers[0].Soil.Name, Is.EqualTo("Soil 1")); + Assert.That(soilProfile1D.Layers[1].TopLevel, Is.EqualTo(0).Within(precison10Decimals)); + Assert.That(soilProfile1D.Layers[1].Soil, Is.Null); + Assert.That(soilProfile1D.Layers[2].TopLevel, Is.EqualTo(-10).Within(precison10Decimals)); + Assert.That(soilProfile1D.Layers[2].Soil.Name, Is.EqualTo("Soil 3")); + Assert.That(soilProfile1D.BottomLevel, Is.EqualTo(-20).Within(precison10Decimals)); + }); + } + +private static void CompareSoilProfile2D(SoilProfile2D sourceSoilProfile2D, SoilProfile2D targetSoilProfile2D) + { Assert.That(targetSoilProfile2D, Is.Not.SameAs(sourceSoilProfile2D)); var compare = new CompareLogic {