Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilSurfaceProfile.cs =================================================================== diff -u -r3079 -r3246 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilSurfaceProfile.cs (.../SoilSurfaceProfile.cs) (revision 3079) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilSurfaceProfile.cs (.../SoilSurfaceProfile.cs) (revision 3246) @@ -353,18 +353,384 @@ } /// + /// Gets the collection of to convert based on the input arguments. + /// + /// The to retrieve the layers for. + /// The surface line. + /// The collection of to convert. + private IEnumerable FilterSoilLayersToConvert(SoilProfile1D profile, SurfaceLine2 surfaceLine) + { + // Make a copy of the soil profile to prevent modifications of the reference argument. + var copiedSoilProfile = (SoilProfile1D)profile.Clone(); + + double maxZCoordinateSurfaceLine = surfaceLine.Geometry.GetMaxZ(); + + // Create an artificial top layer based on the dike embankment material in case the top of the highest soil layer + // lies below the maximum coordinate of the surface line. + var soilLayers = copiedSoilProfile.Layers; + double maxZCoordinateLayers = soilLayers.Select(l => l.TopLevel).Max(); + if (maxZCoordinateLayers < maxZCoordinateSurfaceLine) + { + soilLayers.Insert(0, new SoilLayer1D(DikeEmbankmentMaterial, maxZCoordinateSurfaceLine)); + } + + // TODO: Determine if a layer lies fully above the surface line --> If yes, remove it from the layers to convert + + copiedSoilProfile.EnsureLastLayerHasHeight(); + return copiedSoilProfile.Layers; + } + + private static IEnumerable CreateLayerData(IEnumerable soilLayers, + SurfaceLine2 surfaceLine, IEnumerable xCoordinates) + { + var layerData = new List(); + foreach (SoilLayer1D soilLayer in soilLayers) + { + if (IsLayerBelowSurfaceLine(soilLayer, surfaceLine)) + { + layerData.Add(CreateSurfaceLineWideSoilLayer(soilLayer, xCoordinates)); + } + else + { + layerData.AddRange(CreateSoilLayerWithSurfaceLineIntersection(soilLayer, surfaceLine, xCoordinates)); + } + } + + return layerData; + } + + private static bool IsLayerBelowSurfaceLine(SoilLayer1D soilLayer, SurfaceLine2 surfaceLine) + { + return surfaceLine.Geometry.GetMinZ() > soilLayer.TopLevel; + } + + private static LayerData CreateSurfaceLineWideSoilLayer(SoilLayer1D soilLayer, IEnumerable xCoordinates) + { + // A single square definition does not suffice for the area definition. The + // curves need to overlap each other or the geometry generator fails to recognize + // a surface + double layerTopLevel = soilLayer.TopLevel; + double layerBottomLevel = soilLayer.BottomLevel; + var pointsToConvert = xCoordinates.Select(xCoordinate => new Point2D(xCoordinate, layerTopLevel)).ToList(); + pointsToConvert.AddRange(xCoordinates.Reverse().Select(xCoordinate => new Point2D(xCoordinate, layerBottomLevel)).ToArray()); + + Point2D startPoint = pointsToConvert[0]; + var curves = new List(); + for (int i = 1; i < pointsToConvert.Count; i++) + { + Point2D endPoint = pointsToConvert[i]; + curves.Add(new GeometryCurve(startPoint, endPoint)); + startPoint = endPoint; + } + + // Close the geometry by connecting the first and last points with each other. + // The loop is now closed in a clock wise fashion + curves.Add(new GeometryCurve(pointsToConvert.Last(), pointsToConvert.First())); + + return new LayerData(pointsToConvert, curves, soilLayer.Soil, soilLayer.IsAquifer, soilLayer.WaterpressureInterpolationModel); + } + + private static IEnumerable CreateSoilLayerWithSurfaceLineIntersection(SoilLayer1D soilLayer, + SurfaceLine2 surfaceLine, IEnumerable xCoordinates) + { + double layerTopLevel = soilLayer.TopLevel; + double layerBottomLevel = soilLayer.BottomLevel; + + // Determine the points that are part of the geometry + var currentArea = new EnclosedArea(); + var enclosedAreas = new List(); + double previousZCoordinate = double.NegativeInfinity; + foreach (double xCoordinate in xCoordinates) + { + double zCoordinateSurfaceLine = surfaceLine.Geometry.GetZatX(xCoordinate); + double currentZCoordinate = zCoordinateSurfaceLine; + if (zCoordinateSurfaceLine > layerTopLevel) + { + currentZCoordinate = layerTopLevel; + currentArea.AddCoordinate(new Point2D(xCoordinate, layerTopLevel)); + } + else if (zCoordinateSurfaceLine >= layerBottomLevel && zCoordinateSurfaceLine <= layerTopLevel) + { + currentArea.AddCoordinate(new Point2D(xCoordinate, zCoordinateSurfaceLine)); + } + + // Determine if a new area should be started. This should only happen when: + if (previousZCoordinate > layerBottomLevel // The surface line already starts above the soil layer bottom + && currentZCoordinate < previousZCoordinate // The surface line has a decreasing trend + && currentZCoordinate < layerBottomLevel) // The surface line crossed the bottom of the layer + { + enclosedAreas.Add(currentArea); + currentArea = new EnclosedArea(); + } + + previousZCoordinate = currentZCoordinate; + } + + // The last area needs to be added manually + enclosedAreas.Add(currentArea); + return enclosedAreas.Select(a => CreateLayerData(a, soilLayer)).ToArray(); + } + + private static LayerData CreateLayerData(EnclosedArea area, SoilLayer1D soilLayer) + { + double layerBottomLevel = soilLayer.BottomLevel; + var pointsToConvert = new List(area.Coordinates); + + // Determine the additional points need to be added to close the area + // The area ends at the top right point. Go clockwise to close the area if necessary by adding + // points corresponding to the layer bottom level. + var pointsToTraverse = area.Coordinates.Reverse(); + foreach (Point2D point in pointsToTraverse) + { + var bottomPoint = new Point2D(point.X, layerBottomLevel); + if (!point.LocationEquals(bottomPoint)) + { + pointsToConvert.Add(bottomPoint); + } + } + + Point2D startPoint = pointsToConvert[0]; + var curves = new List(); + for (int i = 1; i < pointsToConvert.Count; i++) + { + Point2D endPoint = pointsToConvert[i]; + curves.Add(new GeometryCurve(startPoint, endPoint)); + startPoint = endPoint; + } + + // Close the geometry by connecting the first and last points with each other + // This closes the outerloop in a clockwise definition. + curves.Add(new GeometryCurve(pointsToConvert.Last(), pointsToConvert.First())); + + return new LayerData(pointsToConvert, curves, soilLayer.Soil, soilLayer.IsAquifer, soilLayer.WaterpressureInterpolationModel); + } + + /// + /// Class to hold the geometry data of a layer. + /// + private class LayerData + { + /// + /// Creates a new instance of . + /// + /// The collection of . + /// The collection of . + /// The belonging to this layer. + /// Indicator whether the layer is an aquifer or not. + /// The of this layer. + public LayerData(IEnumerable points, + IEnumerable curves, + Soil soil, + bool isAquifer, + WaterpressureInterpolationModel waterpressureInterpolationModel) + { + Points = points; + Curves = curves; + Soil = soil; + IsAquifer = isAquifer; + WaterpressureInterpolationModel = waterpressureInterpolationModel; + } + + /// + /// Gets the collection of that define this layer. + /// + public IEnumerable Points { get; } + + /// + /// Gets the collection of that define this layer. + /// + public IEnumerable Curves { get; } + + /// + /// Gets the soil of this layer. + /// + public Soil Soil { get; } + + /// + /// Gets the indicator whether this layer is an aquifer. + /// + public bool IsAquifer { get; } + + /// + /// Gets the belonging to this layer. + /// + public WaterpressureInterpolationModel WaterpressureInterpolationModel { get; } + + /// + /// Function to determine whether the z coordinate lies between the top and + /// bottom coordinate of this layer. + /// + /// The z coordinate to determine the whether it is located inside this layer. + /// true if z lies between the top and bottom coordinate of this layer, false otherwise + public bool IsZLocatedInLayer(double z) + { + double maxZCoordinate = Points.Select(p => p.Z).Max(); + double minZCoordinate = Points.Select(p => p.Z).Min(); + + return z >= minZCoordinate && z <= maxZCoordinate; + } + } + + /// + /// Class to hold the information about the area between a surface line and a soil layer. + /// + private class EnclosedArea + { + private readonly List coordinates; + + /// + /// Creates a new instance of . + /// + public EnclosedArea() + { + coordinates = new List(); + } + + /// + /// Gets the coordinates of the enclosed area. + /// + public IEnumerable Coordinates { get{ return coordinates; }} + + /// + /// Adds a coordinate to the area. + /// + /// The coordinate to add. + /// Thrown when + /// is null. + public void AddCoordinate(Point2D coordinate) + { + if (coordinate == null) + { + throw new ArgumentNullException(nameof(coordinate)); + } + coordinates.Add(coordinate); + } + } + + /// /// Updates the layers. /// private void Create2DGeometryBasedOn1DProfileAndSurfaceLine() { - if (originalSoilProfile1D != null) + var filteredSoilLayers = FilterSoilLayersToConvert(originalSoilProfile1D, surfaceLine2); + + var xCoordinatesToTraverse = GetXCoordinates(filteredSoilLayers, surfaceLine2).ToArray(); + var layerData = CreateLayerData(filteredSoilLayers, surfaceLine2, xCoordinatesToTraverse); + + + // Build geometry + BuildGeometryModel(Geometry, layerData, originalSoilProfile1D, surfaceLine2); + BuildSoilLayer2D(Surfaces, layerData, Geometry); + +// // Assign soil materials to the surfaces +// +// if (originalSoilProfile1D != null) +// { +// soilProfile = (SoilProfile1D)originalSoilProfile1D.Clone(); +// +// EnsureAvailabilityOfMaterialForNew2DGeometry(); +// BuildGeometryModel(); +// RebuildSurfaces(Geometry); +// } + } + + + /// + /// Gets the X coordinates to determine the coordinates for through each layer. + /// + /// The collection of . + /// The . + /// + /// This function is necessary, because the algorithm in recognizing + /// surfaces requires that curves are overlapping. Curves cannot be a subset (e.g, there is one + /// curve definition that span two other curves, because the algorithm will not + /// be able to determine a surface from it. + private IEnumerable GetXCoordinates(IEnumerable soilLayers, SurfaceLine2 surfaceLine) + { + var xCoordinates = new List(surfaceLine.Geometry.CalcPoints.Select(p => p.X)); + + foreach (SoilLayer1D layer in soilLayers) { - soilProfile = (SoilProfile1D)originalSoilProfile1D.Clone(); + xCoordinates.AddRange(GetUniqueXCoordinatesWithIntersections(surfaceLine, layer.TopLevel, layer.BottomLevel)); + } - EnsureAvailabilityOfMaterialForNew2DGeometry(); - BuildGeometryModel(); - RebuildSurfaces(Geometry); - } + return xCoordinates.OrderBy(x => x).Distinct(); } + + private static IEnumerable GetUniqueXCoordinatesWithIntersections(SurfaceLine2 surfaceLine, double layerTopLevel, double layerBottomLevel) + { + GeometryPointString surfaceLineGeometry = surfaceLine.Geometry; + double minXCoordinate = surfaceLineGeometry.GetMinX(); + double maxXCoordinate = surfaceLineGeometry.GetMaxX(); + + // Create lines to determine intersections + var topLeft = new Point2D(minXCoordinate, layerTopLevel); + var topRight = new Point2D(maxXCoordinate, layerTopLevel); + var topLine = new Line(topLeft, topRight); + + var bottomLeft = new Point2D(minXCoordinate, layerBottomLevel); + var bottomRight = new Point2D(maxXCoordinate, layerBottomLevel); + var bottomLine = new Line(bottomLeft, bottomRight); + + var xCoordinates = surfaceLineGeometry.IntersectionPointsXzWithLineXz(topLine).Select(p => p.X).ToList(); + xCoordinates.AddRange(surfaceLineGeometry.IntersectionPointsXzWithLineXz(bottomLine).Select(p => p.X)); + + return xCoordinates.OrderBy(x => x).Distinct(); + } + + private void BuildGeometryModel(GeometryData geometryData, + IEnumerable layers, + SoilProfile1D profile, + SurfaceLine2 surfaceLine) + { + if (surfaceLine.Geometry == null + || profile == null + || profile.Layers.Count == 0 + || surfaceLine.Geometry.GetMaxZ() < profile.BottomLevel + || surfaceLine.Geometry.Points.Count < 2) + { + return; + } + + GeometryBounds bounds = surfaceLine.Geometry.GetGeometryBounds(); + double minX = bounds.Left; + double maxX = bounds.Right; + + geometryData.Clear(); + geometryData.Left = minX; + geometryData.Right = maxX; + geometryData.Bottom = Math.Min(profile.BottomLevel, surfaceLine2.Geometry.GetMinZ() - 1); + + var pointsToBeAdded = layers.SelectMany(l => l.Points); + var curvesToBeAdded = layers.SelectMany(l => l.Curves); + geometryData.NewlyEffectedPoints.AddRange(pointsToBeAdded); + geometryData.NewlyEffectedCurves.AddRange(curvesToBeAdded); + geometryData.RegenerateGeometry(); + } + + private void BuildSoilLayer2D(ICollection soilLayer2Ds, + IEnumerable layers, + GeometryData geometryData) + { + soilLayer2Ds.Clear(); + + foreach (GeometrySurface surface in geometryData.Surfaces) + { + GeometryBounds bounds = surface.GetGeometryBounds(); + double z = (bounds.Top + bounds.Bottom) * 0.5; + + LayerData layerData = layers.FirstOrDefault(l => l.IsZLocatedInLayer(z)); + if (layerData != null) + { + Surfaces.Add(new SoilLayer2D + { + GeometrySurface = surface, + IsAquifer = layerData.IsAquifer, + WaterpressureInterpolationModel = layerData.WaterpressureInterpolationModel, + Soil = layerData.Soil + }); + } + } + } } } \ No newline at end of file Index: DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geotechnics/SoilSurfaceProfileTests.cs =================================================================== diff -u -r3244 -r3246 --- DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geotechnics/SoilSurfaceProfileTests.cs (.../SoilSurfaceProfileTests.cs) (revision 3244) +++ DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geotechnics/SoilSurfaceProfileTests.cs (.../SoilSurfaceProfileTests.cs) (revision 3246) @@ -25,53 +25,30 @@ using Deltares.DamEngine.Data.Geotechnics; using Deltares.DamEngine.Data.Standard; using Deltares.DamEngine.TestHelpers; -using Deltares.DamEngine.TestHelpers.Factories; using NUnit.Framework; namespace Deltares.DamEngine.Data.Tests.Geotechnics { [TestFixture] public class SoilSurfaceProfileTests { - [Test] - public void TestCreate2DProfileWithSimpleSurfaceLineAboveProfile() - { - // Create a 1D profiles with toplayer at -2 - var prof1D = CreateTwoLayerProfile(-2); - // surfaceLine has 7 points, varies in height from -1 to 5 m - var surfaceLine = FactoryForSurfaceLines.CreateSimpleSurfaceLineForExitPointTest(); - - // Create profile - var soilSurfaceProfile = new SoilSurfaceProfile - { - SoilProfile = prof1D, - SurfaceLine2 = surfaceLine, - DikeEmbankmentMaterial = new Soil - { - Name = "Dike material" - } - }; - var profile2D = soilSurfaceProfile.ConvertToSoilProfile2D(); - Assert.AreEqual(13, profile2D.Geometry.Points.Count); - Assert.AreEqual(15, profile2D.Geometry.Curves.Count); - Assert.AreEqual(3, profile2D.Surfaces.Count); - } - - [Test] public void ConvertToSoilProfile2D_WithSurfaceLineFullyAboveSoilLayers_SetsCorrectSurfacesAndGeometry() { // Setup const string bottomLayerName = "BottomLayer"; const string middleLayerName = "MiddleLayer"; const string topLayerName = "TopLayer"; + SoilLayer1D bottomLayer = CreateSoilLayer(-5, bottomLayerName); + SoilLayer1D middleLayer = CreateSoilLayer(-2, middleLayerName); + var profile = new SoilProfile1D { BottomLevel = -10 }; - profile.Layers.Add(CreateSoilLayer(-5, bottomLayerName)); - profile.Layers.Add(CreateSoilLayer(-2, middleLayerName)); + profile.Layers.Add(bottomLayer); + profile.Layers.Add(middleLayer); SurfaceLine2 surfaceLine = CreateSurfaceLine(new[] { @@ -91,39 +68,47 @@ }; // Call - soilSurfaceProfile.ConvertToSoilProfile2D(); + SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D(); // Assert - var soilLayer2Ds = soilSurfaceProfile.Surfaces; + var soilLayer2Ds = soilProfile2D.Surfaces; Assert.That(soilLayer2Ds, Has.Count.EqualTo(3)); - GeometryLoop topSurface = soilLayer2Ds.Single(l => string.Equals(l.Name, topLayerName)).GeometrySurface.OuterLoop; + SoilLayer2D topSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, topLayerName)); + Assert.That(topSoilLayer2D.Soil, Is.SameAs(soilSurfaceProfile.DikeEmbankmentMaterial)); AssertGeometry(new [] { - new GeometryCurve(new Point2D(10, -2), new Point2D(0, -2)), - new GeometryCurve(new Point2D(0, -2), new Point2D(0, 0)), 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)) - }, topSurface.CurveList); + 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); - GeometryLoop middleSurface = soilLayer2Ds.Single(l => string.Equals(l.Name, middleLayerName)).GeometrySurface.OuterLoop; + SoilLayer2D middleSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, middleLayerName)); + Assert.That(middleSoilLayer2D.Soil, Is.SameAs(middleLayer.Soil)); AssertGeometry(new[] { - new GeometryCurve(new Point2D(0, -2), new Point2D(10, -2)), + 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(0, -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)) - }, middleSurface.CurveList); + }, middleSoilLayer2D.GeometrySurface.OuterLoop.CurveList); - GeometryLoop bottomSurface = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName)).GeometrySurface.OuterLoop; + SoilLayer2D bottomSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName)); + Assert.That(bottomSoilLayer2D.Soil, Is.SameAs(bottomLayer.Soil)); AssertGeometry(new[] { - new GeometryCurve(new Point2D(0, -5), new Point2D(10, -5)), + 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(0, -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)) - }, bottomSurface.CurveList); + }, bottomSoilLayer2D.GeometrySurface.OuterLoop.CurveList); } [Test] //Todo #Bka This succeeds locally in the NoExternals version! So Maybe there failuremechanism or C#wrapper is out of date. Update 1 by 1 to find out @@ -135,9 +120,12 @@ const string middleLayerName = "MiddleLayer"; const string topLayerName = "TopLayer"; + SoilLayer1D bottomLayer = CreateSoilLayer(-5, bottomLayerName); + SoilLayer1D middleLayer = CreateSoilLayer(-2, middleLayerName); + var profile = new SoilProfile1D(); - profile.Layers.Add(CreateSoilLayer(-5, bottomLayerName)); - profile.Layers.Add(CreateSoilLayer(-2, middleLayerName)); + profile.Layers.Add(bottomLayer); + profile.Layers.Add(middleLayer); profile.BottomLevel = -10; SurfaceLine2 surfaceLine = CreateSurfaceLine(new[] @@ -158,48 +146,54 @@ }; // Call - soilSurfaceProfile.ConvertToSoilProfile2D(); + SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D(); // Assert - var soilLayer2Ds = soilSurfaceProfile.Surfaces; + var soilLayer2Ds = soilProfile2D.Surfaces; Assert.That(soilLayer2Ds, Has.Count.EqualTo(2)); - GeometryLoop middleSurface = soilLayer2Ds.Single(l => string.Equals(l.Name, middleLayerName)).GeometrySurface.OuterLoop; + SoilLayer2D middleLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, middleLayerName)); + Assert.That(middleLayer2D.Soil, Is.SameAs(middleLayer.Soil)); AssertGeometry(new[] { - new GeometryCurve(new Point2D(0, -5), new Point2D(10, -5)), - new GeometryCurve(new Point2D(0, -5), new Point2D(0, -4)), 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)) - }, middleSurface.CurveList); + 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); - GeometryLoop bottomSurface = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName)).GeometrySurface.OuterLoop; + SoilLayer2D bottomLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName)); + Assert.That(bottomLayer2D.Soil, Is.SameAs(bottomLayer.Soil)); AssertGeometry(new[] { - new GeometryCurve(new Point2D(0, -5), new Point2D(10, -5)), + 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(0, -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)) - }, bottomSurface.CurveList); + }, bottomLayer2D.GeometrySurface.OuterLoop.CurveList); } [Test] [Category(Categories.WorkInProgress)] - public void ConvertToSoilProfile2D_WithSurfaceLinePartiallyEnvelopedByTopSoilLayer_SetsCorrectSurfacesAndGeometry() + public void ConvertToSoilProfile2D_WithSurfaceLinePartiallyEnvelopedByTopSoilLayer_SetsCorrectSurfacesAndGeometry() { // Setup const string bottomLayerName = "BottomLayer"; const string middleLayerName = "MiddleLayer"; const string topLayerName = "TopLayer"; - var profile = new SoilProfile1D - { - BottomLevel = -10 - }; - profile.Layers.Add(CreateSoilLayer(-5, bottomLayerName)); - profile.Layers.Add(CreateSoilLayer(0, middleLayerName)); + SoilLayer1D bottomLayer = CreateSoilLayer(-5, bottomLayerName); + SoilLayer1D middleLayer = CreateSoilLayer(0, middleLayerName); + var profile = new SoilProfile1D(); + profile.Layers.Add(bottomLayer); + profile.Layers.Add(middleLayer); + profile.BottomLevel = -10; + SurfaceLine2 surfaceLine = CreateSurfaceLine(new[] { new GeometryPoint(0, -2.5), @@ -218,40 +212,53 @@ }; // Call - soilSurfaceProfile.ConvertToSoilProfile2D(); + SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D(); // Assert - var soilLayer2Ds = soilSurfaceProfile.Surfaces; + var soilLayer2Ds = soilProfile2D.Surfaces; Assert.That(soilLayer2Ds, Has.Count.EqualTo(3)); - GeometryLoop topSurface = soilLayer2Ds.Single(l => string.Equals(l.Name, topLayerName)).GeometrySurface.OuterLoop; + SoilLayer2D topSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, topLayerName)); + Assert.That(topSoilLayer2D.Soil, Is.SameAs(soilSurfaceProfile.DikeEmbankmentMaterial)); 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(2.5, 0)) - }, topSurface.CurveList); + 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); - GeometryLoop middleSurface = soilLayer2Ds.Single(l => string.Equals(l.Name, middleLayerName)).GeometrySurface.OuterLoop; + SoilLayer2D middleSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, middleLayerName)); + Assert.That(middleSoilLayer2D.Soil, Is.SameAs(middleLayer.Soil)); AssertGeometry(new[] { - new GeometryCurve(new Point2D(0, -5), new Point2D(0, -2.5)), new GeometryCurve(new Point2D(0, -2.5), new Point2D(2.5, 0)), - new GeometryCurve(new Point2D(2.5, 0), new Point2D(7.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(0, -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)) - }, middleSurface.CurveList); + }, middleSoilLayer2D.GeometrySurface.OuterLoop.CurveList); - GeometryLoop bottomSurface = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName)).GeometrySurface.OuterLoop; + SoilLayer2D bottomSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName)); + Assert.That(bottomSoilLayer2D.Soil, Is.SameAs(bottomLayer.Soil)); AssertGeometry(new[] { - new GeometryCurve(new Point2D(0, -5), new Point2D(10, -5)), + 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(0, -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)) - }, bottomSurface.CurveList); + }, bottomSoilLayer2D.GeometrySurface.OuterLoop.CurveList); } private static void AssertGeometry(IEnumerable expectedCurves, IEnumerable actualCurves) @@ -282,35 +289,9 @@ { var surfaceLine = new SurfaceLine2(); surfaceLine.Geometry.Points.AddRange(coordinates); - surfaceLine.Geometry.SyncCalcPoints(); return surfaceLine; } - - private static SoilProfile1D CreateTwoLayerProfile(double offset = 0) - { - var soilProfile = new SoilProfile1D(); - - var layer = new SoilLayer1D(); - layer.TopLevel = 0.0 + offset; - layer.Soil = new Soil("HW-OBO", 12.0, 10.0); - layer.Soil.DryUnitWeight = 0.01; - layer.IsAquifer = false; - layer.WaterpressureInterpolationModel = WaterpressureInterpolationModel.Automatic; - soilProfile.Layers.Add(layer); - - layer = new SoilLayer1D(); - layer.TopLevel = -5.0 + offset; - layer.Soil = new Soil("Alg-zand (0-30)", 22.0, 20.0); - layer.Soil.DryUnitWeight = 0.01; - layer.IsAquifer = true; - layer.WaterpressureInterpolationModel = WaterpressureInterpolationModel.Hydrostatic; - soilProfile.Layers.Add(layer); - - soilProfile.BottomLevel = -10.0 + offset; - - return soilProfile; - } } }