// 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 System.Collections.Generic; 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 SoilSurfaceProfileTests { [Test] public void GivenProfile1DWithOneLayerAndSurfaceLineWhenConverToProfile2DThenCorrectSoilProfile2DIsCreated() { // Given Profile1D with one layer and surface line const string layerName = "Layer"; const string topLayerName = "TopLayer"; SoilLayer1D soilLayer = FactoryForSoilProfiles.CreateSoilLayer(-5, layerName); var profile = new SoilProfile1D { BottomLevel = -10 }; profile.Layers.Add(soilLayer); SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[] { new Point2D(0, 0), new Point2D(5, 10), new Point2D(10, 10) }); // When Convert to Profile2D var soilSurfaceProfile = new SoilSurfaceProfile { SoilProfile = profile, SurfaceLine2 = surfaceLine, DikeEmbankmentMaterial = new Soil { Name = topLayerName } }; SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D(); // Then SoilProfile2D is created Assert.Multiple(() => { Assert.That(soilProfile2D.Geometry.Points.Count, Is.EqualTo(9)); Assert.That(soilProfile2D.Geometry.Curves.Count, Is.EqualTo(10)); Assert.That(soilProfile2D.Geometry.Surfaces.Count, Is.EqualTo(2)); Assert.That(soilProfile2D.Geometry.Surfaces[0].OuterLoop.CurveList.Count, Is.EqualTo(6)); Assert.That(soilProfile2D.Geometry.Surfaces[1].OuterLoop.CurveList.Count, Is.EqualTo(6)); Assert.That(soilProfile2D.Geometry.Surfaces[0].OuterLoop.IsContinuous(), Is.True); Assert.That(soilProfile2D.Geometry.Surfaces[1].OuterLoop.IsContinuous(), Is.True); Assert.That(soilProfile2D.Geometry.Surfaces[0].OuterLoop.IsClockWise(), Is.True); Assert.That(soilProfile2D.Geometry.Surfaces[1].OuterLoop.IsClockWise(), Is.True); }); } [Test] public void ConvertToSoilProfile2D_WithSurfaceLineFullyAboveSoilLayers_ReturnsExpectedSoilProfile2D() { // Setup const string bottomLayerName = "BottomLayer"; const string middleLayerName = "MiddleLayer"; const string topLayerName = "TopLayer"; SoilLayer1D bottomLayer = FactoryForSoilProfiles.CreateSoilLayer(-5, bottomLayerName); SoilLayer1D middleLayer = FactoryForSoilProfiles.CreateSoilLayer(-2, middleLayerName); var profile = new SoilProfile1D { BottomLevel = -10 }; profile.Layers.Add(bottomLayer); profile.Layers.Add(middleLayer); SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[] { new Point2D(0, 0), new Point2D(5, 10), new Point2D(10, 10) }); var soilSurfaceProfile = new SoilSurfaceProfile { SoilProfile = profile, SurfaceLine2 = surfaceLine, DikeEmbankmentMaterial = new Soil { Name = topLayerName } }; // Call SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D(); // Assert IList soilLayer2Ds = soilProfile2D.Surfaces; Assert.That(soilLayer2Ds, Has.Count.EqualTo(3)); SoilLayer2D topSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, topLayerName)); AssertDikeEmbankmentSoilLayerProperties(soilSurfaceProfile, topSoilLayer2D); AssertGeometry(new[] { new GeometryCurve(new Point2D(0, 0), new Point2D(5, 10)), new GeometryCurve(new Point2D(5, 10), new Point2D(10, 10)), new GeometryCurve(new Point2D(10, 10), new Point2D(10, -2)), new GeometryCurve(new Point2D(10, -2), new Point2D(5, -2)), new GeometryCurve(new Point2D(5, -2), new Point2D(0, -2)), new GeometryCurve(new Point2D(0, -2), new Point2D(0, 0)) }, topSoilLayer2D.GeometrySurface.OuterLoop.CurveList); SoilLayer2D middleSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, middleLayerName)); AssertSoilLayerProperties(middleLayer, middleSoilLayer2D); AssertGeometry(new[] { new GeometryCurve(new Point2D(0, -2), new Point2D(5, -2)), new GeometryCurve(new Point2D(5, -2), new Point2D(10, -2)), new GeometryCurve(new Point2D(10, -2), new Point2D(10, -5)), new GeometryCurve(new Point2D(10, -5), new Point2D(5, -5)), new GeometryCurve(new Point2D(5, -5), new Point2D(0, -5)), new GeometryCurve(new Point2D(0, -5), new Point2D(0, -2)) }, middleSoilLayer2D.GeometrySurface.OuterLoop.CurveList); SoilLayer2D bottomSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName)); AssertSoilLayerProperties(bottomLayer, bottomSoilLayer2D); AssertGeometry(new[] { new GeometryCurve(new Point2D(0, -5), new Point2D(5, -5)), new GeometryCurve(new Point2D(5, -5), new Point2D(10, -5)), new GeometryCurve(new Point2D(10, -5), new Point2D(10, -10)), new GeometryCurve(new Point2D(10, -10), new Point2D(5, -10)), new GeometryCurve(new Point2D(5, -10), new Point2D(0, -10)), new GeometryCurve(new Point2D(0, -10), new Point2D(0, -5)) }, bottomSoilLayer2D.GeometrySurface.OuterLoop.CurveList); } [Test] public void ConvertToSoilProfile2D_WithLayerFullyAboveSurfaceLine_ReturnsExpectedSoilProfile2D() { // Setup const string bottomLayerName = "BottomLayer"; const string middleLayerName = "MiddleLayer"; const string topLayerName = "TopLayer"; SoilLayer1D irrelevantLayer = FactoryForSoilProfiles.CreateSoilLayer(0, "Does not matter"); SoilLayer1D bottomLayer = FactoryForSoilProfiles.CreateSoilLayer(-5, bottomLayerName); SoilLayer1D middleLayer = FactoryForSoilProfiles.CreateSoilLayer(-2, middleLayerName); var profile = new SoilProfile1D { BottomLevel = -10 }; profile.Layers.Add(bottomLayer); profile.Layers.Add(middleLayer); profile.Layers.Add(irrelevantLayer); SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[] { new Point2D(0, -5), new Point2D(5, -3), new Point2D(10, -5) }); var soilSurfaceProfile = new SoilSurfaceProfile { SoilProfile = profile, SurfaceLine2 = surfaceLine, DikeEmbankmentMaterial = new Soil { Name = topLayerName } }; // Call SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D(); // Assert IList soilLayer2Ds = soilProfile2D.Surfaces; Assert.That(soilLayer2Ds, Has.Count.EqualTo(2)); SoilLayer2D middleSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, middleLayerName)); AssertSoilLayerProperties(middleLayer, middleSoilLayer2D); AssertGeometry(new[] { new GeometryCurve(new Point2D(0, -5), new Point2D(5, -3)), new GeometryCurve(new Point2D(5, -3), new Point2D(10, -5)), new GeometryCurve(new Point2D(10, -5), new Point2D(5, -5)), new GeometryCurve(new Point2D(5, -5), new Point2D(0, -5)) }, middleSoilLayer2D.GeometrySurface.OuterLoop.CurveList); SoilLayer2D bottomSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName)); AssertSoilLayerProperties(bottomLayer, bottomSoilLayer2D); AssertGeometry(new[] { new GeometryCurve(new Point2D(0, -5), new Point2D(5, -5)), new GeometryCurve(new Point2D(5, -5), new Point2D(10, -5)), new GeometryCurve(new Point2D(10, -5), new Point2D(10, -10)), new GeometryCurve(new Point2D(10, -10), new Point2D(5, -10)), new GeometryCurve(new Point2D(5, -10), new Point2D(0, -10)), new GeometryCurve(new Point2D(0, -10), new Point2D(0, -5)) }, bottomSoilLayer2D.GeometrySurface.OuterLoop.CurveList); } [Test] public void ConvertToSoilProfile2D_WithSurfaceLineFullyEnvelopedByTopSoilLayer_ReturnsExpectedSoilProfile2D() { // Setup const string bottomLayerName = "BottomLayer"; const string middleLayerName = "MiddleLayer"; const string topLayerName = "TopLayer"; 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 = FactoryForSoilProfiles.CreateSurfaceLine(new[] { new Point2D(0, -4), new Point2D(5, -2.5), new Point2D(10, -2.5) }); var soilSurfaceProfile = new SoilSurfaceProfile { SoilProfile = profile, SurfaceLine2 = surfaceLine, DikeEmbankmentMaterial = new Soil { Name = topLayerName } }; // Call SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D(); // Assert IList soilLayer2Ds = soilProfile2D.Surfaces; Assert.That(soilLayer2Ds, Has.Count.EqualTo(2)); SoilLayer2D middleLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, middleLayerName)); AssertSoilLayerProperties(middleLayer, middleLayer2D); AssertGeometry(new[] { new GeometryCurve(new Point2D(0, -4), new Point2D(5, -2.5)), new GeometryCurve(new Point2D(5, -2.5), new Point2D(10, -2.5)), new GeometryCurve(new Point2D(10, -2.5), new Point2D(10, -5)), new GeometryCurve(new Point2D(10, -5), new Point2D(5, -5)), new GeometryCurve(new Point2D(5, -5), new Point2D(0, -5)), new GeometryCurve(new Point2D(0, -5), new Point2D(0, -4)) }, middleLayer2D.GeometrySurface.OuterLoop.CurveList); SoilLayer2D bottomLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName)); AssertSoilLayerProperties(bottomLayer, bottomLayer2D); AssertGeometry(new[] { new GeometryCurve(new Point2D(0, -5), new Point2D(5, -5)), new GeometryCurve(new Point2D(5, -5), new Point2D(10, -5)), new GeometryCurve(new Point2D(10, -5), new Point2D(10, -10)), new GeometryCurve(new Point2D(10, -10), new Point2D(5, -10)), new GeometryCurve(new Point2D(5, -10), new Point2D(0, -10)), new GeometryCurve(new Point2D(0, -10), new Point2D(0, -5)) }, bottomLayer2D.GeometrySurface.OuterLoop.CurveList); } [Test] public void ConvertToSoilProfile2D_WithSurfaceLinePartiallyEnvelopedByTopSoilLayer_ReturnsExpectedSoilProfile2D() { // Setup const string bottomLayerName = "BottomLayer"; const string middleLayerName = "MiddleLayer"; const string topLayerName = "TopLayer"; 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 = FactoryForSoilProfiles.CreateSurfaceLine(new[] { new Point2D(0, -2.5), new Point2D(5, 2.5), new Point2D(10, -2.5) }); var soilSurfaceProfile = new SoilSurfaceProfile { SoilProfile = profile, SurfaceLine2 = surfaceLine, DikeEmbankmentMaterial = new Soil { Name = topLayerName } }; // Call SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D(); // Assert IList soilLayer2Ds = soilProfile2D.Surfaces; Assert.That(soilLayer2Ds, Has.Count.EqualTo(3)); SoilLayer2D topSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, topLayerName)); AssertDikeEmbankmentSoilLayerProperties(soilSurfaceProfile, topSoilLayer2D); AssertGeometry(new[] { new GeometryCurve(new Point2D(2.5, 0), new Point2D(5, 2.5)), new GeometryCurve(new Point2D(5, 2.5), new Point2D(7.5, 0)), new GeometryCurve(new Point2D(7.5, 0), new Point2D(5, 0)), new GeometryCurve(new Point2D(5, 0), new Point2D(2.5, 0)) }, topSoilLayer2D.GeometrySurface.OuterLoop.CurveList); SoilLayer2D middleSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, middleLayerName)); AssertSoilLayerProperties(middleLayer, middleSoilLayer2D); AssertGeometry(new[] { new GeometryCurve(new Point2D(0, -2.5), new Point2D(2.5, 0)), new GeometryCurve(new Point2D(2.5, 0), new Point2D(5, 0)), new GeometryCurve(new Point2D(5, 0), new Point2D(7.5, 0)), new GeometryCurve(new Point2D(7.5, 0), new Point2D(10, -2.5)), new GeometryCurve(new Point2D(10, -2.5), new Point2D(10, -5)), new GeometryCurve(new Point2D(10, -5), new Point2D(7.5, -5)), new GeometryCurve(new Point2D(7.5, -5), new Point2D(5, -5)), new GeometryCurve(new Point2D(5, -5), new Point2D(2.5, -5)), new GeometryCurve(new Point2D(2.5, -5), new Point2D(0, -5)), new GeometryCurve(new Point2D(0, -5), new Point2D(0, -2.5)) }, middleSoilLayer2D.GeometrySurface.OuterLoop.CurveList); SoilLayer2D bottomSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName)); AssertSoilLayerProperties(bottomLayer, bottomSoilLayer2D); AssertGeometry(new[] { new GeometryCurve(new Point2D(0, -5), new Point2D(2.5, -5)), new GeometryCurve(new Point2D(2.5, -5), new Point2D(5, -5)), new GeometryCurve(new Point2D(5, -5), new Point2D(7.5, -5)), new GeometryCurve(new Point2D(7.5, -5), new Point2D(10, -5)), new GeometryCurve(new Point2D(10, -5), new Point2D(10, -10)), new GeometryCurve(new Point2D(10, -10), new Point2D(7.5, -10)), new GeometryCurve(new Point2D(7.5, -10), new Point2D(5, -10)), new GeometryCurve(new Point2D(5, -10), new Point2D(2.5, -10)), new GeometryCurve(new Point2D(2.5, -10), new Point2D(0, -10)), new GeometryCurve(new Point2D(0, -10), new Point2D(0, -5)) }, bottomSoilLayer2D.GeometrySurface.OuterLoop.CurveList); } [Test] public void ConvertToSoilProfile2D_WithSurfaceLineIntersectingSoilLayers_ReturnsExpectedSoilProfile() { // Setup const string bottomLayerName = "BottomLayer"; const string middleLayerName = "MiddleLayer"; const string topLayerName = "TopLayer"; 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 = FactoryForSoilProfiles.CreateSurfaceLine(new[] { new Point2D(0, 2.5), new Point2D(5, -2.5), new Point2D(10, 2.5) }); var soilSurfaceProfile = new SoilSurfaceProfile { SoilProfile = profile, SurfaceLine2 = surfaceLine, DikeEmbankmentMaterial = new Soil { Name = topLayerName } }; // Call SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D(); // Assert IList soilLayer2Ds = soilProfile2D.Surfaces; Assert.That(soilLayer2Ds, Has.Count.EqualTo(5)); SoilLayer2D[] topSoilLayerSurfaces = soilLayer2Ds.Where(l => string.Equals(l.Name, topLayerName)).ToArray(); Assert.That(topSoilLayerSurfaces.Length, Is.EqualTo(2)); foreach (SoilLayer2D surface in topSoilLayerSurfaces) { AssertDikeEmbankmentSoilLayerProperties(soilSurfaceProfile, surface); } AssertGeometry(new[] { new GeometryCurve(new Point2D(0, 2.5), new Point2D(2.5, 0)), new GeometryCurve(new Point2D(2.5, 0), new Point2D(0, 0)), new GeometryCurve(new Point2D(0, 0), new Point2D(0, 2.5)) }, topSoilLayerSurfaces[0].GeometrySurface.OuterLoop.CurveList); AssertGeometry(new[] { new GeometryCurve(new Point2D(7.5, 0), new Point2D(10, 2.5)), new GeometryCurve(new Point2D(10, 2.5), new Point2D(10, 0)), new GeometryCurve(new Point2D(10, 0), new Point2D(7.5, 0)) }, topSoilLayerSurfaces[1].GeometrySurface.OuterLoop.CurveList); SoilLayer2D[] middleLayerSurfaces = soilLayer2Ds.Where(l => string.Equals(l.Name, middleLayerName)).ToArray(); Assert.That(middleLayerSurfaces.Length, Is.EqualTo(2)); foreach (SoilLayer2D surface in middleLayerSurfaces) { AssertSoilLayerProperties(middleLayer, surface); } AssertGeometry(new[] { new GeometryCurve(new Point2D(0, 0), new Point2D(2.5, 0)), new GeometryCurve(new Point2D(2.5, 0), new Point2D(3.75, -1.25)), new GeometryCurve(new Point2D(3.75, -1.25), new Point2D(2.5, -1.25)), new GeometryCurve(new Point2D(2.5, -1.25), new Point2D(0, -1.25)), new GeometryCurve(new Point2D(0, -1.25), new Point2D(0, 0)) }, middleLayerSurfaces[0].GeometrySurface.OuterLoop.CurveList); AssertGeometry(new[] { new GeometryCurve(new Point2D(7.5, 0), new Point2D(10, 0)), new GeometryCurve(new Point2D(10, 0), new Point2D(10, -1.25)), new GeometryCurve(new Point2D(10, -1.25), new Point2D(7.5, -1.25)), new GeometryCurve(new Point2D(7.5, -1.25), new Point2D(6.25, -1.25)), new GeometryCurve(new Point2D(6.25, -1.25), new Point2D(7.5, 0)) }, middleLayerSurfaces[1].GeometrySurface.OuterLoop.CurveList); SoilLayer2D bottomLayerSurface = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName)); AssertSoilLayerProperties(bottomLayer, bottomLayerSurface); AssertGeometry(new[] { new GeometryCurve(new Point2D(0, -1.25), new Point2D(2.5, -1.25)), new GeometryCurve(new Point2D(2.5, -1.25), new Point2D(3.75, -1.25)), new GeometryCurve(new Point2D(3.75, -1.25), new Point2D(5, -2.5)), new GeometryCurve(new Point2D(5, -2.5), new Point2D(6.25, -1.25)), new GeometryCurve(new Point2D(6.25, -1.25), new Point2D(7.5, -1.25)), new GeometryCurve(new Point2D(7.5, -1.25), new Point2D(10, -1.25)), new GeometryCurve(new Point2D(10, -1.25), new Point2D(10, -10)), new GeometryCurve(new Point2D(10, -10), new Point2D(7.5, -10)), new GeometryCurve(new Point2D(7.5, -10), new Point2D(6.25, -10)), new GeometryCurve(new Point2D(6.25, -10), new Point2D(5, -10)), new GeometryCurve(new Point2D(5, -10), new Point2D(3.75, -10)), new GeometryCurve(new Point2D(3.75, -10), new Point2D(2.5, -10)), new GeometryCurve(new Point2D(2.5, -10), new Point2D(0, -10)), new GeometryCurve(new Point2D(0, -10), new Point2D(0, -1.25)) }, bottomLayerSurface.GeometrySurface.OuterLoop.CurveList); } [Test] public void ConvertToSoilProfile2D_WithSurfaceLineIntersectingSoilLayerAndInflectionAtBottomIntersection_ReturnsExpectedSoilProfile() { // Setup const string bottomLayerName = "BottomLayer"; const string middleLayerName = "MiddleLayer"; const string topLayerName = "TopLayer"; 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 = FactoryForSoilProfiles.CreateSurfaceLine(new[] { new Point2D(0, 2.5), new Point2D(5, -2.5), new Point2D(10, 2.5) }); var soilSurfaceProfile = new SoilSurfaceProfile { SoilProfile = profile, SurfaceLine2 = surfaceLine, DikeEmbankmentMaterial = new Soil { Name = topLayerName } }; // Call SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D(); // Assert IList soilLayer2Ds = soilProfile2D.Surfaces; Assert.That(soilLayer2Ds, Has.Count.EqualTo(5)); SoilLayer2D[] topSoilLayerSurfaces = soilLayer2Ds.Where(l => string.Equals(l.Name, topLayerName)).ToArray(); Assert.That(topSoilLayerSurfaces.Length, Is.EqualTo(2)); foreach (SoilLayer2D surface in topSoilLayerSurfaces) { AssertDikeEmbankmentSoilLayerProperties(soilSurfaceProfile, surface); } AssertGeometry(new[] { new GeometryCurve(new Point2D(0, 2.5), new Point2D(2.5, 0)), new GeometryCurve(new Point2D(2.5, 0), new Point2D(0, 0)), new GeometryCurve(new Point2D(0, 0), new Point2D(0, 2.5)) }, topSoilLayerSurfaces[0].GeometrySurface.OuterLoop.CurveList); AssertGeometry(new[] { new GeometryCurve(new Point2D(7.5, 0), new Point2D(10, 2.5)), new GeometryCurve(new Point2D(10, 2.5), new Point2D(10, 0)), new GeometryCurve(new Point2D(10, 0), new Point2D(7.5, 0)) }, topSoilLayerSurfaces[1].GeometrySurface.OuterLoop.CurveList); SoilLayer2D[] middleLayerSurfaces = soilLayer2Ds.Where(l => string.Equals(l.Name, middleLayerName)).ToArray(); Assert.That(middleLayerSurfaces.Length, Is.EqualTo(2)); foreach (SoilLayer2D surface in middleLayerSurfaces) { AssertSoilLayerProperties(middleLayer, surface); } AssertGeometry(new[] { new GeometryCurve(new Point2D(0, 0), new Point2D(2.5, 0)), new GeometryCurve(new Point2D(2.5, 0), new Point2D(5, -2.5)), new GeometryCurve(new Point2D(5, -2.5), new Point2D(2.5, -2.5)), new GeometryCurve(new Point2D(2.5, -2.5), new Point2D(0, -2.5)), new GeometryCurve(new Point2D(0, -2.5), new Point2D(0, 0)) }, middleLayerSurfaces[0].GeometrySurface.OuterLoop.CurveList); AssertGeometry(new[] { new GeometryCurve(new Point2D(7.5, 0), new Point2D(10, 0)), new GeometryCurve(new Point2D(10, 0), new Point2D(10, -2.5)), new GeometryCurve(new Point2D(10, -2.5), new Point2D(7.5, -2.5)), new GeometryCurve(new Point2D(7.5, -2.5), new Point2D(5, -2.5)), new GeometryCurve(new Point2D(5, -2.5), new Point2D(7.5, 0)) }, middleLayerSurfaces[1].GeometrySurface.OuterLoop.CurveList); SoilLayer2D bottomLayerSurface = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName)); AssertSoilLayerProperties(bottomLayer, bottomLayerSurface); AssertGeometry(new[] { new GeometryCurve(new Point2D(0, -2.5), new Point2D(2.5, -2.5)), new GeometryCurve(new Point2D(2.5, -2.5), new Point2D(5, -2.5)), new GeometryCurve(new Point2D(5, -2.5), new Point2D(7.5, -2.5)), new GeometryCurve(new Point2D(7.5, -2.5), new Point2D(10, -2.5)), new GeometryCurve(new Point2D(10, -2.5), new Point2D(10, -10)), new GeometryCurve(new Point2D(10, -10), new Point2D(7.5, -10)), new GeometryCurve(new Point2D(7.5, -10), new Point2D(5, -10)), new GeometryCurve(new Point2D(5, -10), new Point2D(2.5, -10)), new GeometryCurve(new Point2D(2.5, -10), new Point2D(0, -10)), new GeometryCurve(new Point2D(0, -10), new Point2D(0, -2.5)) }, bottomLayerSurface.GeometrySurface.OuterLoop.CurveList); } [Test] public void ConvertToSoilProfile2D_WithSurfaceLineIntersectingSoilLayerAndHorizontalLineAtBottomIntersection_ReturnsExpectedSoilProfile() { // Setup const string bottomLayerName = "BottomLayer"; const string middleLayerName = "MiddleLayer"; const string topLayerName = "TopLayer"; 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 = FactoryForSoilProfiles.CreateSurfaceLine(new[] { new Point2D(0, 2.5), new Point2D(5, -2.5), new Point2D(10, -2.5), new Point2D(15, 2.5) }); var soilSurfaceProfile = new SoilSurfaceProfile { SoilProfile = profile, SurfaceLine2 = surfaceLine, DikeEmbankmentMaterial = new Soil { Name = topLayerName } }; // Call SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D(); // Assert IList soilLayer2Ds = soilProfile2D.Surfaces; Assert.That(soilLayer2Ds, Has.Count.EqualTo(5)); SoilLayer2D[] topSoilLayerSurfaces = soilLayer2Ds.Where(l => string.Equals(l.Name, topLayerName)).ToArray(); Assert.That(topSoilLayerSurfaces.Length, Is.EqualTo(2)); foreach (SoilLayer2D surface in topSoilLayerSurfaces) { AssertDikeEmbankmentSoilLayerProperties(soilSurfaceProfile, surface); } AssertGeometry(new[] { new GeometryCurve(new Point2D(0, 2.5), new Point2D(2.5, 0)), new GeometryCurve(new Point2D(2.5, 0), new Point2D(0, 0)), new GeometryCurve(new Point2D(0, 0), new Point2D(0, 2.5)) }, topSoilLayerSurfaces[0].GeometrySurface.OuterLoop.CurveList); AssertGeometry(new[] { new GeometryCurve(new Point2D(12.5, 0), new Point2D(15, 2.5)), new GeometryCurve(new Point2D(15, 2.5), new Point2D(15, 0)), new GeometryCurve(new Point2D(15, 0), new Point2D(12.5, 0)) }, topSoilLayerSurfaces[1].GeometrySurface.OuterLoop.CurveList); SoilLayer2D[] middleLayerSurfaces = soilLayer2Ds.Where(l => string.Equals(l.Name, middleLayerName)).ToArray(); Assert.That(middleLayerSurfaces.Length, Is.EqualTo(2)); foreach (SoilLayer2D surface in middleLayerSurfaces) { AssertSoilLayerProperties(middleLayer, surface); } AssertGeometry(new[] { new GeometryCurve(new Point2D(0, 0), new Point2D(2.5, 0)), new GeometryCurve(new Point2D(2.5, 0), new Point2D(5, -2.5)), new GeometryCurve(new Point2D(5, -2.5), new Point2D(2.5, -2.5)), new GeometryCurve(new Point2D(2.5, -2.5), new Point2D(0, -2.5)), new GeometryCurve(new Point2D(0, -2.5), new Point2D(0, 0)) }, middleLayerSurfaces[0].GeometrySurface.OuterLoop.CurveList); AssertGeometry(new[] { new GeometryCurve(new Point2D(12.5, 0), new Point2D(15, 0)), new GeometryCurve(new Point2D(15, 0), new Point2D(15, -2.5)), new GeometryCurve(new Point2D(15, -2.5), new Point2D(12.5, -2.5)), new GeometryCurve(new Point2D(12.5, -2.5), new Point2D(10, -2.5)), new GeometryCurve(new Point2D(10, -2.5), new Point2D(12.5, 0)) }, middleLayerSurfaces[1].GeometrySurface.OuterLoop.CurveList); SoilLayer2D bottomLayerSurface = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName)); AssertSoilLayerProperties(bottomLayer, bottomLayerSurface); AssertGeometry(new[] { new GeometryCurve(new Point2D(0, -2.5), new Point2D(2.5, -2.5)), new GeometryCurve(new Point2D(2.5, -2.5), new Point2D(5, -2.5)), new GeometryCurve(new Point2D(5, -2.5), new Point2D(10, -2.5)), new GeometryCurve(new Point2D(10, -2.5), new Point2D(12.5, -2.5)), new GeometryCurve(new Point2D(12.5, -2.5), new Point2D(15, -2.5)), new GeometryCurve(new Point2D(15, -2.5), new Point2D(15, -10)), new GeometryCurve(new Point2D(15, -10), new Point2D(12.5, -10)), new GeometryCurve(new Point2D(12.5, -10), new Point2D(10, -10)), new GeometryCurve(new Point2D(10, -10), new Point2D(5, -10)), new GeometryCurve(new Point2D(5, -10), new Point2D(2.5, -10)), new GeometryCurve(new Point2D(2.5, -10), new Point2D(0, -10)), new GeometryCurve(new Point2D(0, -10), new Point2D(0, -2.5)) }, bottomLayerSurface.GeometrySurface.OuterLoop.CurveList); } [Test] public void ConvertToSoilProfile2D_WithSurfaceLineStartingHorizontallyAtBottomLayer_ReturnsExpectedSoilProfile() { // Setup const string bottomLayerName = "BottomLayer"; const string middleLayerName = "MiddleLayer"; const string topLayerName = "TopLayer"; 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 = FactoryForSoilProfiles.CreateSurfaceLine(new[] { new Point2D(0, -2.5), new Point2D(5, -2.5), new Point2D(10, 2.5), new Point2D(15, -2.5), new Point2D(20, -2.5) }); var soilSurfaceProfile = new SoilSurfaceProfile { SoilProfile = profile, SurfaceLine2 = surfaceLine, DikeEmbankmentMaterial = new Soil { Name = topLayerName } }; // Call SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D(); // Assert IList soilLayer2Ds = soilProfile2D.Surfaces; SoilLayer2D topSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, topLayerName)); AssertDikeEmbankmentSoilLayerProperties(soilSurfaceProfile, topSoilLayer2D); AssertGeometry(new[] { new GeometryCurve(new Point2D(7.5, 0), new Point2D(10, 2.5)), new GeometryCurve(new Point2D(10, 2.5), new Point2D(12.5, 0)), new GeometryCurve(new Point2D(12.5, 0), new Point2D(10, 0)), new GeometryCurve(new Point2D(10, 0), new Point2D(7.5, 0)) }, topSoilLayer2D.GeometrySurface.OuterLoop.CurveList); SoilLayer2D middleSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, middleLayerName)); AssertSoilLayerProperties(middleLayer, middleSoilLayer2D); AssertGeometry(new[] { new GeometryCurve(new Point2D(5, -2.5), new Point2D(7.5, 0)), new GeometryCurve(new Point2D(7.5, 0), new Point2D(10, 0)), new GeometryCurve(new Point2D(10, 0), new Point2D(12.5, 0)), new GeometryCurve(new Point2D(12.5, 0), new Point2D(15, -2.5)), new GeometryCurve(new Point2D(15, -2.5), new Point2D(12.5, -2.5)), new GeometryCurve(new Point2D(12.5, -2.5), new Point2D(10, -2.5)), new GeometryCurve(new Point2D(10, -2.5), new Point2D(7.5, -2.5)), new GeometryCurve(new Point2D(7.5, -2.5), new Point2D(5, -2.5)) }, middleSoilLayer2D.GeometrySurface.OuterLoop.CurveList); SoilLayer2D bottomSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName)); AssertSoilLayerProperties(bottomLayer, bottomSoilLayer2D); AssertGeometry(new[] { new GeometryCurve(new Point2D(0, -2.5), new Point2D(5, -2.5)), new GeometryCurve(new Point2D(5, -2.5), new Point2D(7.5, -2.5)), new GeometryCurve(new Point2D(7.5, -2.5), new Point2D(10, -2.5)), new GeometryCurve(new Point2D(10, -2.5), new Point2D(12.5, -2.5)), new GeometryCurve(new Point2D(12.5, -2.5), new Point2D(15, -2.5)), new GeometryCurve(new Point2D(15, -2.5), new Point2D(20, -2.5)), new GeometryCurve(new Point2D(20, -2.5), new Point2D(20, -10)), new GeometryCurve(new Point2D(20, -10), new Point2D(15, -10)), new GeometryCurve(new Point2D(15, -10), new Point2D(12.5, -10)), new GeometryCurve(new Point2D(12.5, -10), new Point2D(10, -10)), new GeometryCurve(new Point2D(10, -10), new Point2D(7.5, -10)), new GeometryCurve(new Point2D(7.5, -10), new Point2D(5, -10)), new GeometryCurve(new Point2D(5, -10), new Point2D(0, -10)), new GeometryCurve(new Point2D(0, -10), new Point2D(0, -2.5)) }, bottomSoilLayer2D.GeometrySurface.OuterLoop.CurveList); } /// /// This test reproduces the problem found in MWDAM-2514 where the ditch was incorrectly filled in. /// This is due to the small vertical distance between the surface line point (32.125, -2.451) and the bottom level of /// layer H_MDp_k (-2.45) which led to consider that the point was part of the layer and therefore to create a curve /// closing the ditch. /// Expected is that only 5 layers are created, not 6. /// [Test] public void GivenSurfaceLineWithDitch_WhenConvertingToSoilProfile2D_ReturnsExpectedSoilProfile() { // Setup const string layer1Name = "H_MDp_k"; const string layer2Name = "H_MDg_zf"; const string layer3Name = "H_Vhv_vo"; SoilLayer1D layer1 = FactoryForSoilProfiles.CreateSoilLayer(-1.78, layer1Name); SoilLayer1D layer2 = FactoryForSoilProfiles.CreateSoilLayer(-2.45, layer2Name); SoilLayer1D layer3 = FactoryForSoilProfiles.CreateSoilLayer(-2.95, layer3Name); var profile = new SoilProfile1D(); profile.Layers.Add(layer1); profile.Layers.Add(layer2); profile.Layers.Add(layer3); profile.BottomLevel = -4.3; SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[] { new Point2D(0, -1.78), new Point2D(26, -1.78), new Point2D(31.775, -2.443), new Point2D(32.125, -2.451), new Point2D(34.575, -2.544), new Point2D(35, -3.130), new Point2D(37, -3.130), new Point2D(38.775, -2.479), new Point2D(39.125, -2.445), new Point2D(48.575, -2.156) }); var soilSurfaceProfile = new SoilSurfaceProfile { SoilProfile = profile, SurfaceLine2 = surfaceLine, DikeEmbankmentMaterial = new Soil() }; // Call SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D(); // Assert IList soilLayer2Ds = soilProfile2D.Surfaces; Assert.That(soilLayer2Ds, Has.Count.EqualTo(5)); Assert.Multiple(() => { Assert.That(soilLayer2Ds[0].SoilName, Is.EqualTo(layer1Name)); Assert.That(soilLayer2Ds[1].SoilName, Is.EqualTo(layer2Name)); Assert.That(soilLayer2Ds[2].SoilName, Is.EqualTo(layer1Name)); Assert.That(soilLayer2Ds[3].SoilName, Is.EqualTo(layer2Name)); Assert.That(soilLayer2Ds[4].SoilName, Is.EqualTo(layer3Name)); }); } private static void AssertGeometry(IEnumerable expectedCurves, IEnumerable actualCurves) { int nrOfExpectedCurves = expectedCurves.Count(); Assert.That(actualCurves.Count(), Is.EqualTo(nrOfExpectedCurves)); IEnumerable actualCurveString = actualCurves.Select(c => $"Coordinate ({c.HeadPoint.X}, {c.HeadPoint.Z}) --> ({c.EndPoint.X}, {c.EndPoint.Z})"); foreach (GeometryCurve expectedCurve in expectedCurves) { Assert.That(actualCurves.Any(c => c.LocationEquals(expectedCurve)), Is.True, $"Expected curve ({expectedCurve.HeadPoint.X}, {expectedCurve.HeadPoint.Z}) --> ({expectedCurve.EndPoint.X}, {expectedCurve.EndPoint.Z}) not found. " + $"Actual curves {string.Join(", ", actualCurveString)}"); } } private static void AssertSoilLayerProperties(SoilLayer1D expectedLayer, SoilLayer2D actualSoilLayer) { Assert.That(actualSoilLayer.IsAquifer, Is.EqualTo(expectedLayer.IsAquifer)); Assert.That(actualSoilLayer.WaterpressureInterpolationModel, Is.EqualTo(expectedLayer.WaterpressureInterpolationModel)); Assert.That(actualSoilLayer.Soil, Is.SameAs(expectedLayer.Soil)); } private static void AssertDikeEmbankmentSoilLayerProperties(SoilSurfaceProfile expectedProfile, SoilLayer2D actualSoilLayer) { Assert.That(actualSoilLayer.IsAquifer, Is.False); Assert.That(actualSoilLayer.WaterpressureInterpolationModel, Is.EqualTo(WaterpressureInterpolationModel.Hydrostatic)); Assert.That(actualSoilLayer.Soil, Is.SameAs(expectedProfile.DikeEmbankmentMaterial)); } }