Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/KernelWrappers/Common/SoilProfile2DHelperTests.cs
===================================================================
diff -u
--- DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/KernelWrappers/Common/SoilProfile2DHelperTests.cs (revision 0)
+++ DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/KernelWrappers/Common/SoilProfile2DHelperTests.cs (revision 5382)
@@ -0,0 +1,1002 @@
+// 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;
+using System.Collections.Generic;
+using System.Linq;
+using Deltares.DamEngine.Calculators.KernelWrappers.Common;
+using Deltares.DamEngine.Data.Geometry;
+using Deltares.DamEngine.Data.Geotechnics;
+using Deltares.DamEngine.TestHelpers.Factories;
+using NUnit.Framework;
+
+namespace Deltares.DamEngine.Calculators.Tests.KernelWrappers.Common;
+
+public class SoilProfile2DHelperTests
+{
+ private const double precision5Decimals = 0.0000051;
+
+ private static readonly Random random = new(21);
+ private static readonly double leftCoordinate = random.NextDouble();
+ private static readonly double rightCoordinate = leftCoordinate + 1;
+ private static readonly double middleXCoordinate = 0.5 * (leftCoordinate + rightCoordinate);
+
+ ///
+ /// Different soil profiles 2D are tested, see the pictures in method GetSoilProfilesWithContinuousBottomAquiferLayer,
+ /// with a top clay layer and bottom aquifer layers always forming a continuous bottom layer.
+ /// As there is only one aquifer, then the BottomAquifer is also the HighestAquifer.
+ ///
+ ///
+ ///
+ [Test]
+ [TestCaseSource(nameof(GetSoilProfilesWithContinuousBottomAquiferLayer))]
+ public void Given2DSoilProfileWithContinuousBottomAquifer_WhenDeterminingLayerBoundaryPointsOfBottomAquifer_ThenExpectedCoordinatesReturned(
+ SoilProfile2D soilProfile, IEnumerable expectedBottomAquiferCoordinates)
+ {
+ // Call
+ SoilProfile2DHelper.DetermineAquiferLayerBoundaryPoints(SoilProfile2DHelper.LayerType.BottomAquiferCluster, soilProfile, out Point2D[] bottomAquifer, out _);
+ SoilProfile2DHelper.DetermineAquiferLayerBoundaryPoints(SoilProfile2DHelper.LayerType.HighestAquiferCluster, soilProfile, out Point2D[] highestAquifer, out _);
+
+ // Assert
+ AssertGeometry(bottomAquifer, expectedBottomAquiferCoordinates);
+ AssertGeometry(highestAquifer, expectedBottomAquiferCoordinates);
+ }
+
+ ///
+ /// |-------------------------------------------------------------| Level 0 m
+ /// | Aquitard 1 |
+ /// |-------------------------------------------------------------| Level -10 m
+ /// | Aquitard 2 B /------------------------\ C | Level -12 m
+ /// | / Aquifer 1 \ |
+ /// | / point X \ |
+ /// |---------------/--------------*---------------\--------------| Level -20 m
+ /// | A Aquifer 2 D |
+ /// |------------------------------*------------------------------| Level -30 m
+ /// point Y
+ ///
+ [Test]
+ [TestCase(-20,-30)]
+ [TestCase(-20.1,-30)]
+ [TestCase(-19.9,-30)]
+ [TestCase(-20,-30.1)]
+ [TestCase(-20,-29.9)]
+ public void Given2DSoilProfileWithNotContinuousAquiferConnectedToContinuousAquifer_WhenDeterminingLayerBoundaryPointsOfAquifer_ThenExpectedCoordinatesReturned(double zPointX, double zPointY)
+ {
+ var pointA = new Point2D(leftCoordinate + (rightCoordinate - leftCoordinate) / 3, -20);
+ var pointB = new Point2D(pointA.X + 0.01, -12);
+ var pointC = new Point2D(leftCoordinate + 2 * (rightCoordinate - leftCoordinate) / 3, -12);
+ var pointD = new Point2D(pointC.X + 0.01, -20);
+ var pointX = new Point2D(middleXCoordinate, zPointX);
+ var pointY = new Point2D(middleXCoordinate, zPointY);
+
+ SoilLayer2D soilUpperLayer = CreateRectangularSoilLayer2D(0, -10, leftCoordinate, rightCoordinate, false);
+ SoilLayer2D soilLayerAquitard2 = FactoryForSoilProfiles.CreatePolygoneSoilLayer2D([
+ ..new[]
+ {
+ new Point2D(leftCoordinate, -10),
+ new Point2D(rightCoordinate, -10),
+ new Point2D(rightCoordinate, -20),
+ pointD,
+ pointC,
+ pointB,
+ pointA,
+ new Point2D(leftCoordinate, -20)
+ }
+ ], null);
+ SoilLayer2D soilLayerAquifer1 = FactoryForSoilProfiles.CreatePentagonSoilLayer2D(pointA, pointB, pointC, pointD, pointX, null, null, true);
+ SoilLayer2D soilLayerAquifer2 = FactoryForSoilProfiles.CreatePolygoneSoilLayer2D([
+ ..new[]
+ {
+ new Point2D(leftCoordinate, -20),
+ pointA,
+ pointX,
+ pointD,
+ new Point2D(rightCoordinate, -20),
+ new Point2D(rightCoordinate, -30),
+ pointY,
+ new Point2D(leftCoordinate, -30)
+ }
+ ], null, true);
+
+ var soilProfile = new SoilProfile2D
+ {
+ Geometry = new GeometryData
+ {
+ Left = leftCoordinate,
+ Right = rightCoordinate,
+ Bottom = -30
+ }
+ };
+ soilProfile.Surfaces.Add(soilUpperLayer);
+ soilProfile.Surfaces.Add(soilLayerAquitard2);
+ soilProfile.Surfaces.Add(soilLayerAquifer1);
+ soilProfile.Surfaces.Add(soilLayerAquifer2);
+ soilProfile.Geometry.Surfaces.Add(new GeometrySurface());
+
+ // Call
+ SoilProfile2DHelper.DetermineAquiferLayerBoundaryPoints(SoilProfile2DHelper.LayerType.BottomAquiferCluster, soilProfile, out Point2D[] bottomAquifer, out _);
+ SoilProfile2DHelper.DetermineAquiferLayerBoundaryPoints(SoilProfile2DHelper.LayerType.HighestAquiferCluster, soilProfile, out Point2D[] highestAquifer, out _);
+
+ // Assert
+ var expectedBottomAquiferCoordinates = new[]
+ {
+ new GeometryPoint(leftCoordinate, -20),
+ new GeometryPoint(pointA.X, pointA.Z),
+ new GeometryPoint(pointB.X, pointB.Z),
+ new GeometryPoint(middleXCoordinate, -12),
+ new GeometryPoint(pointC.X, pointC.Z),
+ new GeometryPoint(pointD.X, pointD.Z),
+ new GeometryPoint(rightCoordinate, -20)
+ };
+ AssertGeometry(bottomAquifer, expectedBottomAquiferCoordinates);
+ AssertGeometry(highestAquifer, expectedBottomAquiferCoordinates);
+ }
+
+ ///
+ /// --------------------------------------------------------------- Level 0 m
+ /// top layer
+ /// --------------------------------------------------------------- Level -10 m
+ /// in-between aquifer layer left | in-between aquifer layer right
+ /// --------------------------------------------------------------- Level -20 m
+ /// in-between layer
+ /// --------------------------------------------------------------- Level -25 m
+ /// bottom aquifer layer
+ /// --------------------------------------------------------------- Level -30 m
+ ///
+ [Test]
+ public void Given2DSoilProfileWithContinuousInBetweenAquiferLayerConsistingOfTwoParts_WhenDeterminingLayerBoundaryPointsOfInBetweenAquifer_ThenExpectedCoordinatesReturned()
+ {
+ // Setup
+ SoilLayer2D soilLayer = CreateRectangularSoilLayer2D(0, -10, leftCoordinate, rightCoordinate, false);
+ SoilLayer2D soilLayerAquiferInBetweenLeft = CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, true);
+ SoilLayer2D soilLayerAquiferInBetweenRight = CreateRectangularSoilLayer2D(-10, -20, middleXCoordinate, rightCoordinate, true);
+ SoilLayer2D soilLayerInBetween = CreateRectangularSoilLayer2D(-20, -25, leftCoordinate, rightCoordinate, false);
+ SoilLayer2D soilLayerAquiferBottom = CreateRectangularSoilLayer2D(-25, -30, leftCoordinate, rightCoordinate, true);
+
+ var soilProfile = new SoilProfile2D
+ {
+ Geometry = new GeometryData
+ {
+ Left = leftCoordinate,
+ Right = rightCoordinate,
+ Bottom = -30
+ }
+ };
+ soilProfile.Surfaces.Add(soilLayer);
+ soilProfile.Surfaces.Add(soilLayerAquiferInBetweenLeft);
+ soilProfile.Surfaces.Add(soilLayerAquiferInBetweenRight);
+ soilProfile.Surfaces.Add(soilLayerInBetween);
+ soilProfile.Surfaces.Add(soilLayerAquiferBottom);
+ soilProfile.Geometry.Surfaces.Add(new GeometrySurface());
+
+ // Call
+ bool isInBetweenLayerPresent = SoilProfile2DHelper.AreInBetweenAquiferClustersPresent(soilProfile, out int count);
+ SoilProfile2DHelper.DetermineAquiferLayerBoundaryPoints(SoilProfile2DHelper.LayerType.InBetweenAquiferCluster, soilProfile, out Point2D[] topLevelInBetweenAquifer, out Point2D[] bottomLevelInBetweenAquifer, 0);
+
+ // Assert
+ Assert.Multiple(() =>
+ {
+ Assert.That(isInBetweenLayerPresent, Is.True);
+ Assert.That(count, Is.EqualTo(1));
+ });
+ GeometryPoint[] expectedTop =
+ [
+ new(leftCoordinate, -10),
+ new(middleXCoordinate, -10),
+ new(rightCoordinate, -10)
+ ];
+ GeometryPoint[] expectedBottom =
+ [
+ new(leftCoordinate, -20),
+ new(middleXCoordinate, -20),
+ new(rightCoordinate, -20)
+ ];
+ AssertGeometry(topLevelInBetweenAquifer, expectedTop);
+ AssertGeometry(bottomLevelInBetweenAquifer, expectedBottom);
+ }
+
+ ///
+ /// --------------------------------------------------- Level 0 m
+ /// top layer
+ /// --------------------------------------------------- Level -10 m
+ /// in-between aquifer layer
+ /// --------------------------------------------------- Level -20 m
+ /// in-between layer
+ /// --------------------------------------------------- Level -25 m
+ /// bottom aquifer layer
+ /// --------------------------------------------------- Level -30 m
+ ///
+ [Test]
+ public void Given2DSoilProfileWithContinuousInBetweenAquiferLayerConsistingOfOnePart_WhenDeterminingLayerBoundaryPointsOfInBetweenAquifer_ThenExpectedCoordinatesReturned()
+ {
+ // Setup
+ SoilLayer2D soilLayer = CreateRectangularSoilLayer2D(0, -10, leftCoordinate, rightCoordinate, false);
+ SoilLayer2D soilLayerAquiferInBetween = CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, rightCoordinate, true);
+ SoilLayer2D soilLayerInBetween = CreateRectangularSoilLayer2D(-20, -25, leftCoordinate, rightCoordinate, false);
+ SoilLayer2D soilLayerAquiferBottom = CreateRectangularSoilLayer2D(-25, -30, leftCoordinate, rightCoordinate, true);
+
+ var soilProfile = new SoilProfile2D
+ {
+ Geometry = new GeometryData
+ {
+ Left = leftCoordinate,
+ Right = rightCoordinate,
+ Bottom = -30
+ }
+ };
+ soilProfile.Surfaces.Add(soilLayer);
+ soilProfile.Surfaces.Add(soilLayerAquiferInBetween);
+ soilProfile.Surfaces.Add(soilLayerInBetween);
+ soilProfile.Surfaces.Add(soilLayerAquiferBottom);
+ soilProfile.Geometry.Surfaces.Add(new GeometrySurface());
+
+ // Call
+ bool isInBetweenLayerPresent = SoilProfile2DHelper.AreInBetweenAquiferClustersPresent(soilProfile, out int count);
+ SoilProfile2DHelper.DetermineAquiferLayerBoundaryPoints(SoilProfile2DHelper.LayerType.InBetweenAquiferCluster, soilProfile, out Point2D[] topLevelInBetweenAquifer, out Point2D[] bottomLevelInBetweenAquifer, 0);
+
+ // Assert
+ Assert.Multiple(() =>
+ {
+ Assert.That(isInBetweenLayerPresent, Is.True);
+ Assert.That(count, Is.EqualTo(1));
+ });
+ GeometryPoint[] expectedTop =
+ [
+ new(leftCoordinate, -10),
+ new(rightCoordinate, -10)
+ ];
+ GeometryPoint[] expectedBottom =
+ [
+ new(leftCoordinate, -20),
+ new(rightCoordinate, -20)
+ ];
+ AssertGeometry(topLevelInBetweenAquifer, expectedTop);
+ AssertGeometry(bottomLevelInBetweenAquifer, expectedBottom);
+ }
+
+ ///
+ /// ------------------------------------------------------------- Level 0 m
+ /// top layer
+ /// ------------------------------------------------------------- Level -10 m
+ /// | Gap layer
+ /// in-between aquifer |------------------------------- Level -15 m
+ /// layer left |
+ /// | in-between aquifer
+ /// -----------------------------| layer right Level -20 m
+ /// in-between layer |
+ /// |------------------------------- Level -21 m
+ ///
+ /// ------------------------------------------------------------- Level -25 m
+ /// bottom aquifer layer
+ /// ------------------------------------------------------------- Level -30 m
+ ///
+ [Test]
+ public void Given2DSoilProfileWithContinuousInBetweenAquiferConsistingOfTwoLayersWithRightLayerTopLevelInRangeLeftLayer_WhenDeterminingLayerBoundaryPointsOfInBetweenAquifer_ThenExpectedCoordinatesReturned()
+ {
+ // Setup
+ SoilLayer2D soilLayer = CreateRectangularSoilLayer2D(0, -10, leftCoordinate, rightCoordinate, false);
+ SoilLayer2D soilLayerAquiferInBetweenLeft = CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, true);
+ // Add a layer to fill the gap between the right aquifer layer and the upper layer
+ SoilLayer2D soilLayerGap = CreateRectangularSoilLayer2D(-10, -15, middleXCoordinate, rightCoordinate, false);
+ SoilLayer2D soilLayerAquiferInBetweenRight = CreateRectangularSoilLayer2D(-15, -21, middleXCoordinate, rightCoordinate, true);
+ // Add continuous in-between layer
+ var bottomLeftInBetweenAquiferLayerLeft = new Point2D(leftCoordinate, -20);
+ var bottomRightInBetweenAquiferLayerLeft = new Point2D(middleXCoordinate, -20);
+ var bottomLeftInBetweenAquiferLayerRight = new Point2D(middleXCoordinate, -21);
+ var bottomRightInBetweenAquiferLayerRight = new Point2D(rightCoordinate, -21);
+ var bottomRightInBetweenLayer = new Point2D(rightCoordinate, -25);
+ var bottomLeftInBetweenLayer = new Point2D(leftCoordinate, -25);
+ var soilLayerInBetween = new SoilLayer2D
+ {
+ GeometrySurface = new GeometrySurface
+ {
+ OuterLoop = new GeometryLoop
+ {
+ CurveList =
+ {
+ new GeometryCurve(bottomLeftInBetweenAquiferLayerLeft, bottomRightInBetweenAquiferLayerLeft),
+ new GeometryCurve(bottomRightInBetweenAquiferLayerLeft, bottomLeftInBetweenAquiferLayerRight),
+ new GeometryCurve(bottomLeftInBetweenAquiferLayerRight, bottomRightInBetweenAquiferLayerRight),
+ new GeometryCurve(bottomRightInBetweenAquiferLayerRight, bottomRightInBetweenLayer),
+ new GeometryCurve(bottomRightInBetweenLayer, bottomLeftInBetweenLayer)
+ }
+ }
+ }
+ };
+ SoilLayer2D soilLayerAquiferBottom = CreateRectangularSoilLayer2D(-25, -30, leftCoordinate, rightCoordinate, true);
+
+ var soilProfile = new SoilProfile2D
+ {
+ Geometry = new GeometryData
+ {
+ Left = leftCoordinate,
+ Right = rightCoordinate,
+ Bottom = -30
+ }
+ };
+ soilProfile.Surfaces.Add(soilLayer);
+ soilProfile.Surfaces.Add(soilLayerAquiferInBetweenLeft);
+ soilProfile.Surfaces.Add(soilLayerGap);
+ soilProfile.Surfaces.Add(soilLayerAquiferInBetweenRight);
+ soilProfile.Surfaces.Add(soilLayerInBetween);
+ soilProfile.Surfaces.Add(soilLayerAquiferBottom);
+ soilProfile.Geometry.Surfaces.Add(new GeometrySurface());
+
+ // Call
+ bool isInBetweenLayerPresent = SoilProfile2DHelper.AreInBetweenAquiferClustersPresent(soilProfile, out int count);
+ SoilProfile2DHelper.DetermineAquiferLayerBoundaryPoints(SoilProfile2DHelper.LayerType.InBetweenAquiferCluster, soilProfile, out Point2D[] topLevelInBetweenAquifer, out Point2D[] bottomLevelInBetweenAquifer, 0);
+
+ // Assert
+ Assert.Multiple(() =>
+ {
+ Assert.That(isInBetweenLayerPresent, Is.True);
+ Assert.That(count, Is.EqualTo(1));
+ });
+ GeometryPoint[] expectedTop =
+ [
+ new(leftCoordinate, -10),
+ new(middleXCoordinate, -10),
+ new(middleXCoordinate, -15),
+ new(rightCoordinate, -15)
+ ];
+ GeometryPoint[] expectedBottom =
+ [
+ new(leftCoordinate, -20),
+ new(middleXCoordinate, -20),
+ new(middleXCoordinate, -21),
+ new(rightCoordinate, -21)
+ ];
+ AssertGeometry(topLevelInBetweenAquifer, expectedTop);
+ AssertGeometry(bottomLevelInBetweenAquifer, expectedBottom);
+ }
+
+ ///
+ /// -------------------------------------------------------------- Level 0 m
+ /// top layer
+ /// |------------------------------- Level -5 m
+ /// |
+ /// | in-between aquifer
+ /// ------------------------------| layer right Level -10 m
+ /// in-between aquifer layer left |
+ /// ------------------------------------------------------------- Level -20 m
+ /// in-between layer
+ /// -------------------------------------------------------------- Level -25 m
+ /// bottom aquifer layer
+ /// -------------------------------------------------------------- Level -30 m
+ ///
+ [Test]
+ public void Given2DSoilProfileWithContinuousInBetweenAquiferConsistingOfTwoLayersWithRightLayerBottomLevelInRangeLeftLayer_WhenDeterminingLayerBoundaryPointsOfInBetweenAquifer_ThenExpectedCoordinatesReturned()
+ {
+ // Setup
+ var topLeftUpperLayer = new Point2D(leftCoordinate, 0);
+ var topRightUpperLayer = new Point2D(rightCoordinate, 0);
+ var bottomRightUpperLayer = new Point2D(rightCoordinate, -5);
+ var bottomIntermediateUpperUpperLayer = new Point2D(middleXCoordinate, -5);
+ var bottomIntermediateLowerUpperLayer = new Point2D(middleXCoordinate, -10);
+ var bottomLeftUpperLayer = new Point2D(leftCoordinate, -10);
+ var soilLayer = new SoilLayer2D
+ {
+ GeometrySurface = new GeometrySurface
+ {
+ OuterLoop = new GeometryLoop
+ {
+ CurveList =
+ {
+ new GeometryCurve(topLeftUpperLayer, topRightUpperLayer),
+ new GeometryCurve(topRightUpperLayer, bottomRightUpperLayer),
+ new GeometryCurve(bottomRightUpperLayer, bottomIntermediateUpperUpperLayer),
+ new GeometryCurve(bottomIntermediateUpperUpperLayer, bottomIntermediateLowerUpperLayer),
+ new GeometryCurve(bottomIntermediateLowerUpperLayer, bottomLeftUpperLayer),
+ new GeometryCurve(bottomLeftUpperLayer, topLeftUpperLayer)
+ }
+ }
+ }
+ };
+ SoilLayer2D soilLayerAquiferInBetweenLeft = CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, true);
+ SoilLayer2D soilLayerAquiferInBetweenRight = CreateRectangularSoilLayer2D(-5, -20, middleXCoordinate, rightCoordinate, true);
+ SoilLayer2D soilLayerInBetween = CreateRectangularSoilLayer2D(-20, -25, leftCoordinate, rightCoordinate, false);
+ SoilLayer2D soilLayerAquiferBottom = CreateRectangularSoilLayer2D(-25, -30, leftCoordinate, rightCoordinate, true);
+ soilLayerAquiferBottom.IsAquifer = true;
+
+ var soilProfile = new SoilProfile2D
+ {
+ Geometry = new GeometryData
+ {
+ Left = leftCoordinate,
+ Right = rightCoordinate,
+ Bottom = -30
+ }
+ };
+ soilProfile.Surfaces.Add(soilLayer);
+ soilProfile.Surfaces.Add(soilLayerAquiferInBetweenLeft);
+ soilProfile.Surfaces.Add(soilLayerAquiferInBetweenRight);
+ soilProfile.Surfaces.Add(soilLayerInBetween);
+ soilProfile.Surfaces.Add(soilLayerAquiferBottom);
+ soilProfile.Geometry.Surfaces.Add(new GeometrySurface());
+
+ // Call
+ bool isInBetweenLayerPresent = SoilProfile2DHelper.AreInBetweenAquiferClustersPresent(soilProfile, out int count);
+ SoilProfile2DHelper.DetermineAquiferLayerBoundaryPoints(SoilProfile2DHelper.LayerType.InBetweenAquiferCluster, soilProfile, out Point2D[] topLevelInBetweenAquifer, out Point2D[] bottomLevelInBetweenAquifer, 0);
+
+ // Assert
+ Assert.Multiple(() =>
+ {
+ Assert.That(isInBetweenLayerPresent, Is.True);
+ Assert.That(count, Is.EqualTo(1));
+ });
+ GeometryPoint[] expectedTop =
+ [
+ new(leftCoordinate, -10),
+ new(middleXCoordinate, -10),
+ new(middleXCoordinate, -5),
+ new(rightCoordinate, -5)
+ ];
+ GeometryPoint[] expectedBottom =
+ [
+ new(leftCoordinate, -20),
+ new(middleXCoordinate, -20),
+ new(middleXCoordinate, -20),
+ new(rightCoordinate, -20)
+ ];
+ AssertGeometry(topLevelInBetweenAquifer, expectedTop);
+ AssertGeometry(bottomLevelInBetweenAquifer, expectedBottom);
+ }
+
+ ///
+ /// ------------------------------------------------------------- Level 0 m
+ /// top layer
+ ///
+ /// -----------------------------| Level -10 m
+ /// in-between aquifer |
+ /// layer left |------------------------------- Level -15 m
+ /// | in-between aquifer layer right
+ /// | ------------------------------ Level -17 m
+ /// |
+ /// |
+ /// -----------------------------| Level -20 m
+ /// in-between layer
+ /// ------------------------------------------------------------- Level -25 m
+ /// bottom aquifer layer
+ /// ------------------------------------------------------------- Level -30 m
+ ///
+ [Test]
+ public void Given2DSoilProfileWithContinuousInBetweenAquiferConsistingOfTwoLayersWithRightLayerEnvelopedByLeftLayer_WhenDeterminingLayerBoundaryPointsOfInBetweenAquifer_ThenExpectedCoordinatesReturned()
+ {
+ // Setup
+ var topLeftUpperLayer = new Point2D(leftCoordinate, 0);
+ var topRightUpperLayer = new Point2D(rightCoordinate, 0);
+ var bottomRightUpperLayer = new Point2D(rightCoordinate, -15);
+ var bottomIntermediateLowerUpperLayer = new Point2D(middleXCoordinate, -15);
+ var bottomIntermediateUpperUpperLayer = new Point2D(middleXCoordinate, -10);
+ var bottomLeftUpperLayer = new Point2D(leftCoordinate, -10);
+ var soilLayer = new SoilLayer2D
+ {
+ GeometrySurface = new GeometrySurface
+ {
+ OuterLoop = new GeometryLoop
+ {
+ CurveList =
+ {
+ new GeometryCurve(topLeftUpperLayer, topRightUpperLayer),
+ new GeometryCurve(topRightUpperLayer, bottomRightUpperLayer),
+ new GeometryCurve(bottomRightUpperLayer, bottomIntermediateLowerUpperLayer),
+ new GeometryCurve(bottomIntermediateLowerUpperLayer, bottomIntermediateUpperUpperLayer),
+ new GeometryCurve(bottomIntermediateUpperUpperLayer, bottomLeftUpperLayer),
+ new GeometryCurve(bottomLeftUpperLayer, topLeftUpperLayer)
+ }
+ }
+ }
+ };
+ SoilLayer2D soilLayerAquiferInBetweenLeft = CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, true);
+ SoilLayer2D soilLayerAquiferInBetweenRight = CreateRectangularSoilLayer2D(-15, -17, middleXCoordinate, rightCoordinate, true);
+
+ var bottomLeftInBetweenAquiferLayerLeft = new Point2D(leftCoordinate, -20);
+ var bottomRightInBetweenAquiferLayerLeft = new Point2D(middleXCoordinate, -20);
+ var bottomLeftInBetweenAquiferLayerRight = new Point2D(middleXCoordinate, -17);
+ var bottomRightInBetweenAquiferLayerRight = new Point2D(rightCoordinate, -17);
+ var bottomRightInBetweenLayer = new Point2D(rightCoordinate, -25);
+ var bottomLeftInBetweenLayer = new Point2D(leftCoordinate, -25);
+ var soilLayerInBetween = new SoilLayer2D
+ {
+ GeometrySurface = new GeometrySurface
+ {
+ OuterLoop = new GeometryLoop
+ {
+ CurveList =
+ {
+ new GeometryCurve(bottomLeftInBetweenAquiferLayerLeft, bottomRightInBetweenAquiferLayerLeft),
+ new GeometryCurve(bottomRightInBetweenAquiferLayerLeft, bottomLeftInBetweenAquiferLayerRight),
+ new GeometryCurve(bottomLeftInBetweenAquiferLayerRight, bottomRightInBetweenAquiferLayerRight),
+ new GeometryCurve(bottomRightInBetweenAquiferLayerRight, bottomRightInBetweenLayer),
+ new GeometryCurve(bottomRightInBetweenLayer, bottomLeftInBetweenLayer),
+ new GeometryCurve(bottomLeftInBetweenLayer, bottomLeftInBetweenAquiferLayerLeft)
+ }
+ }
+ }
+ };
+ SoilLayer2D soilLayerAquiferBottom = CreateRectangularSoilLayer2D(-25, -30, leftCoordinate, rightCoordinate, true);
+
+ var soilProfile = new SoilProfile2D
+ {
+ Geometry = new GeometryData
+ {
+ Left = leftCoordinate,
+ Right = rightCoordinate,
+ Bottom = -30
+ }
+ };
+ soilProfile.Surfaces.Add(soilLayer);
+ soilProfile.Surfaces.Add(soilLayerAquiferInBetweenLeft);
+ soilProfile.Surfaces.Add(soilLayerAquiferInBetweenRight);
+ soilProfile.Surfaces.Add(soilLayerInBetween);
+ soilProfile.Surfaces.Add(soilLayerAquiferBottom);
+ soilProfile.Geometry.Surfaces.Add(new GeometrySurface());
+
+ // Call
+ bool isInBetweenLayerPresent = SoilProfile2DHelper.AreInBetweenAquiferClustersPresent(soilProfile, out int count);
+ SoilProfile2DHelper.DetermineAquiferLayerBoundaryPoints(SoilProfile2DHelper.LayerType.InBetweenAquiferCluster, soilProfile, out Point2D[] topLevelInBetweenAquifer, out Point2D[] bottomLevelInBetweenAquifer, 0);
+
+ // Assert
+ Assert.Multiple(() =>
+ {
+ Assert.That(isInBetweenLayerPresent, Is.True);
+ Assert.That(count, Is.EqualTo(1));
+ });
+ GeometryPoint[] expectedTop =
+ [
+ new(leftCoordinate, -10),
+ new(middleXCoordinate, -10),
+ new(middleXCoordinate, -15),
+ new(rightCoordinate, -15)
+ ];
+ GeometryPoint[] expectedBottom =
+ [
+ new(leftCoordinate, -20),
+ new(middleXCoordinate, -20),
+ new(middleXCoordinate, -17),
+ new(rightCoordinate, -17)
+ ];
+ AssertGeometry(topLevelInBetweenAquifer, expectedTop);
+ AssertGeometry(bottomLevelInBetweenAquifer, expectedBottom);
+ }
+
+ ///
+ /// ------------------------------------------------------------- Level 0 m
+ /// top layer
+ /// |------------------------------ Level -5 m
+ /// | in-between aquifer
+ /// ------------------------------| layer right Level -10 m
+ /// in-between aquifer layer left |
+ /// |
+ /// ------------------------------| Level -20 m
+ /// in-between layer |
+ /// |------------------------------ Level -21 m
+ ///
+ /// ------------------------------------------------------------- Level -25 m
+ /// bottom aquifer layer
+ /// ------------------------------------------------------------- Level -30 m
+ ///
+ [Test]
+ public void Given2DSoilProfileWithContinuousInBetweenAquiferConsistingOfTwoLayersWithLeftLayerEnvelopedByRightLayer_WhenDeterminingLayerBoundaryPointsOfInBetweenAquifer_ThenExpectedCoordinatesReturned()
+ {
+ // Setup
+ var topLeftUpperLayer = new Point2D(leftCoordinate, 0);
+ var topRightUpperLayer = new Point2D(rightCoordinate, 0);
+ var bottomRightUpperLayer = new Point2D(rightCoordinate, -5);
+ var bottomIntermediateLowerUpperLayer = new Point2D(middleXCoordinate, -5);
+ var bottomIntermediateUpperUpperLayer = new Point2D(middleXCoordinate, -10);
+ var bottomLeftUpperLayer = new Point2D(leftCoordinate, -10);
+ var soilLayer = new SoilLayer2D
+ {
+ GeometrySurface = new GeometrySurface
+ {
+ OuterLoop = new GeometryLoop
+ {
+ CurveList =
+ {
+ new GeometryCurve(topLeftUpperLayer, topRightUpperLayer),
+ new GeometryCurve(topRightUpperLayer, bottomRightUpperLayer),
+ new GeometryCurve(bottomRightUpperLayer, bottomIntermediateLowerUpperLayer),
+ new GeometryCurve(bottomIntermediateLowerUpperLayer, bottomIntermediateUpperUpperLayer),
+ new GeometryCurve(bottomIntermediateUpperUpperLayer, bottomLeftUpperLayer),
+ new GeometryCurve(bottomLeftUpperLayer, topLeftUpperLayer)
+ }
+ }
+ }
+ };
+
+ SoilLayer2D soilLayerAquiferInBetweenLeft = CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, true);
+ SoilLayer2D soilLayerAquiferInBetweenRight = CreateRectangularSoilLayer2D(-5, -21, middleXCoordinate, rightCoordinate, true);
+
+ var bottomLeftInBetweenAquiferLayerLeft = new Point2D(leftCoordinate, -20);
+ var bottomRightInBetweenAquiferLayerLeft = new Point2D(middleXCoordinate, -20);
+ var bottomLeftInBetweenAquiferLayerRight = new Point2D(middleXCoordinate, -21);
+ var bottomRightInBetweenAquiferLayerRight = new Point2D(rightCoordinate, -21);
+ var bottomRightInBetweenLayer = new Point2D(rightCoordinate, -25);
+ var bottomLeftInBetweenLayer = new Point2D(leftCoordinate, -25);
+ var soilLayerInBetween = new SoilLayer2D
+ {
+ GeometrySurface = new GeometrySurface
+ {
+ OuterLoop = new GeometryLoop
+ {
+ CurveList =
+ {
+ new GeometryCurve(bottomLeftInBetweenAquiferLayerLeft, bottomRightInBetweenAquiferLayerLeft),
+ new GeometryCurve(bottomRightInBetweenAquiferLayerLeft, bottomLeftInBetweenAquiferLayerRight),
+ new GeometryCurve(bottomLeftInBetweenAquiferLayerRight, bottomRightInBetweenAquiferLayerRight),
+ new GeometryCurve(bottomRightInBetweenAquiferLayerRight, bottomRightInBetweenLayer),
+ new GeometryCurve(bottomRightInBetweenLayer, bottomLeftInBetweenLayer),
+ new GeometryCurve(bottomLeftInBetweenLayer, bottomLeftInBetweenAquiferLayerLeft)
+ }
+ }
+ }
+ };
+ SoilLayer2D soilLayerAquiferBottom = CreateRectangularSoilLayer2D(-25, -30, leftCoordinate, rightCoordinate, true);
+
+ var soilProfile = new SoilProfile2D
+ {
+ Geometry = new GeometryData
+ {
+ Left = leftCoordinate,
+ Right = rightCoordinate,
+ Bottom = -30
+ }
+ };
+ soilProfile.Surfaces.Add(soilLayer);
+ soilProfile.Surfaces.Add(soilLayerAquiferInBetweenLeft);
+ soilProfile.Surfaces.Add(soilLayerAquiferInBetweenRight);
+ soilProfile.Surfaces.Add(soilLayerInBetween);
+ soilProfile.Surfaces.Add(soilLayerAquiferBottom);
+ soilProfile.Geometry.Surfaces.Add(new GeometrySurface());
+
+ // Call
+ bool isInBetweenLayerPresent = SoilProfile2DHelper.AreInBetweenAquiferClustersPresent(soilProfile, out int count);
+ SoilProfile2DHelper.DetermineAquiferLayerBoundaryPoints(SoilProfile2DHelper.LayerType.InBetweenAquiferCluster, soilProfile, out Point2D[] topLevelInBetweenAquifer, out Point2D[] bottomLevelInBetweenAquifer, 0);
+
+ // Assert
+ Assert.Multiple(() =>
+ {
+ Assert.That(isInBetweenLayerPresent, Is.True);
+ Assert.That(count, Is.EqualTo(1));
+ });
+ GeometryPoint[] expectedTop =
+ [
+ new(leftCoordinate, -10),
+ new(middleXCoordinate, -10),
+ new(middleXCoordinate, -5),
+ new(rightCoordinate, -5)
+ ];
+ GeometryPoint[] expectedBottom =
+ [
+ new(leftCoordinate, -20),
+ new(middleXCoordinate, -20),
+ new(middleXCoordinate, -21),
+ new(rightCoordinate, -21)
+ ];
+ AssertGeometry(topLevelInBetweenAquifer, expectedTop);
+ AssertGeometry(bottomLevelInBetweenAquifer, expectedBottom);
+ }
+
+ ///
+ /// --------------------------------------------------- Level 0 m
+ /// top layer
+ /// -------------------------|------------------------- Level -10 m
+ /// in-between layer left | in-between layer right
+ /// -------------------------|------------------------- Level -20 m
+ /// in-between layer
+ /// --------------------------------------------------- Level -25 m
+ /// bottom aquifer layer
+ /// --------------------------------------------------- Level -30 m
+ ///
+ [Test]
+ [TestCase(true, false)]
+ [TestCase(false, true)]
+ public void Given2DSoilProfileWithDiscontinuousInBetweenAquifer_WhenDeterminingInBetweenAquiferCount_ThenReturns0(
+ bool isLeftInBetweenLayerAquifer, bool isRightInBetweenLayerAquifer)
+ {
+ // Setup
+ SoilLayer2D soilLayer = CreateRectangularSoilLayer2D(0, -10, leftCoordinate, rightCoordinate, false);
+ SoilLayer2D soilLayerAquiferInBetweenLeft = CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, isLeftInBetweenLayerAquifer);
+ SoilLayer2D soilLayerAquiferInBetweenRight = CreateRectangularSoilLayer2D(-10, -20, middleXCoordinate, rightCoordinate, isRightInBetweenLayerAquifer);
+ SoilLayer2D soilLayerInBetween = CreateRectangularSoilLayer2D(-20, -25, leftCoordinate, rightCoordinate, false);
+ SoilLayer2D soilLayerAquiferBottom = CreateRectangularSoilLayer2D(-25, -30, leftCoordinate, rightCoordinate, true);
+
+ var soilProfile = new SoilProfile2D
+ {
+ Geometry = new GeometryData
+ {
+ Left = leftCoordinate,
+ Right = rightCoordinate,
+ Bottom = -30
+ }
+ };
+ soilProfile.Surfaces.Add(soilLayer);
+ soilProfile.Surfaces.Add(soilLayerAquiferInBetweenLeft);
+ soilProfile.Surfaces.Add(soilLayerAquiferInBetweenRight);
+ soilProfile.Surfaces.Add(soilLayerInBetween);
+ soilProfile.Surfaces.Add(soilLayerAquiferBottom);
+
+ // Call
+ bool isInBetweenLayerPresent = SoilProfile2DHelper.AreInBetweenAquiferClustersPresent(soilProfile, out int count);
+
+ // Assert
+ Assert.Multiple(() =>
+ {
+ Assert.That(isInBetweenLayerPresent, Is.False);
+ Assert.That(count, Is.EqualTo(0));
+ });
+ }
+
+ ///
+ /// Many test cases are considered using a different soil profile 2D:
+ /// Within the method below, pictures of these soil profiles 2D are drawn to get a better idea of the test.
+ ///
+ private static IEnumerable GetSoilProfilesWithContinuousBottomAquiferLayer()
+ {
+ // TEST CASE 1: "Right aquifer fully adjoins left aquifer"
+ //
+ // ------------------------------------------------------------- Level 0 m
+ // Upper layer (not aquifer)
+ // -----------------------------|------------------------------- Level -10 m
+ // Bottom aquifer layer left | Bottom aquifer layer right
+ // -----------------------------|------------------------------- Level -20 m
+ SoilLayer2D soilUpperLayer = CreateRectangularSoilLayer2D(0, -10, leftCoordinate, rightCoordinate, false);
+ SoilLayer2D soilBottomLayerAquiferPartLeft = CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, true);
+ SoilLayer2D soilBottomLayerAquiferPartRight = CreateRectangularSoilLayer2D(-10, -20, middleXCoordinate, rightCoordinate, true);
+ var soilProfileFullAdjoin = new SoilProfile2D
+ {
+ Geometry = new GeometryData
+ {
+ Left = leftCoordinate,
+ Right = rightCoordinate,
+ Bottom = -20
+ }
+ };
+ soilProfileFullAdjoin.Surfaces.Add(soilUpperLayer);
+ soilProfileFullAdjoin.Surfaces.Add(soilBottomLayerAquiferPartLeft);
+ soilProfileFullAdjoin.Surfaces.Add(soilBottomLayerAquiferPartRight);
+ soilProfileFullAdjoin.Geometry.Surfaces.Add(new GeometrySurface());
+
+ yield return new TestCaseData(soilProfileFullAdjoin, new[]
+ {
+ new GeometryPoint(leftCoordinate, -10),
+ new GeometryPoint(middleXCoordinate, -10),
+ new GeometryPoint(rightCoordinate, -10)
+ }).SetName("Right aquifer fully adjoins left aquifer");
+
+ // TEST CASE 2: "One aquifer bottom layer"
+ //
+ // ------------------------------------------------------------- Level 0 m
+ // Upper layer (not aquifer)
+ // ------------------------------------------------------------- Level -10 m
+ // Bottom aquifer layer
+ // ------------------------------------------------------------- Level -20 m
+ SoilLayer2D soilBottomLayerAquifer = CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, rightCoordinate, true);
+ var soilProfileOneBottomAquiferLayer = new SoilProfile2D
+ {
+ Geometry = new GeometryData
+ {
+ Left = leftCoordinate,
+ Right = rightCoordinate,
+ Bottom = -20
+ }
+ };
+ soilProfileOneBottomAquiferLayer.Surfaces.Add(soilUpperLayer);
+ soilProfileOneBottomAquiferLayer.Surfaces.Add(soilBottomLayerAquifer);
+ soilProfileOneBottomAquiferLayer.Geometry.Surfaces.Add(new GeometrySurface());
+
+ yield return new TestCaseData(soilProfileOneBottomAquiferLayer, new[]
+ {
+ new GeometryPoint(leftCoordinate, -10),
+ new GeometryPoint(rightCoordinate, -10)
+ }).SetName("One aquifer bottom layer");
+
+ // TEST CASE 3: "Right aquifer only bottom in range"
+ //
+ // ------------------------------------------------------------- Level 0 m
+ // Upper layer (not aquifer) |------------------------------ Level -5 m
+ // ------------------------------| Right bottom aquifer layer Level -10 m
+ // Left bottom aquifer layer |------------------------------ Level -15 m
+ // ------------------------------| Level -20 m
+ soilBottomLayerAquiferPartRight = CreateRectangularSoilLayer2D(-5, -15, middleXCoordinate, rightCoordinate, true);
+ var soilProfileRightSoilLayerBottomInRange = new SoilProfile2D
+ {
+ Geometry = new GeometryData
+ {
+ Left = leftCoordinate,
+ Right = rightCoordinate,
+ Bottom = -20
+ }
+ };
+ soilProfileRightSoilLayerBottomInRange.Surfaces.Add(soilUpperLayer);
+ soilProfileRightSoilLayerBottomInRange.Surfaces.Add(soilBottomLayerAquiferPartLeft);
+ soilProfileRightSoilLayerBottomInRange.Surfaces.Add(soilBottomLayerAquiferPartRight);
+ soilProfileRightSoilLayerBottomInRange.Geometry.Surfaces.Add(new GeometrySurface());
+
+ yield return new TestCaseData(soilProfileRightSoilLayerBottomInRange, new[]
+ {
+ new GeometryPoint(leftCoordinate, -10),
+ new GeometryPoint(middleXCoordinate, -10),
+ new GeometryPoint(middleXCoordinate, -5),
+ new GeometryPoint(rightCoordinate, -5)
+ }).SetName("Right aquifer only bottom in range");
+
+ // TEST CASE 4: "Right aquifer only top in range"
+ //
+ // ------------------------------------------------------------- Level 0 m
+ // Upper layer (not aquifer) |
+ // ------------------------------|------------------------------ Level -10 m
+ // Left bottom aquifer layer |------------------------------ Level -15 m
+ // ------------------------------| Right bottom aquifer layer | Level -20 m
+ // |------------------------------ Level -25 m
+ soilBottomLayerAquiferPartRight = CreateRectangularSoilLayer2D(-15, -25, middleXCoordinate, rightCoordinate, true);
+
+ var soilProfileRightSoilLayerTopInRange = new SoilProfile2D
+ {
+ Geometry = new GeometryData
+ {
+ Left = leftCoordinate,
+ Right = rightCoordinate,
+ Bottom = -25
+ }
+ };
+ soilProfileRightSoilLayerTopInRange.Surfaces.Add(soilUpperLayer);
+ soilProfileRightSoilLayerTopInRange.Surfaces.Add(soilBottomLayerAquiferPartLeft);
+ soilProfileRightSoilLayerTopInRange.Surfaces.Add(soilBottomLayerAquiferPartRight);
+ soilProfileRightSoilLayerTopInRange.Geometry.Surfaces.Add(new GeometrySurface());
+
+ yield return new TestCaseData(soilProfileRightSoilLayerTopInRange, new[]
+ {
+ new GeometryPoint(leftCoordinate, -10),
+ new GeometryPoint(middleXCoordinate, -10),
+ new GeometryPoint(middleXCoordinate, -15),
+ new GeometryPoint(rightCoordinate, -15)
+ }).SetName("Right aquifer only top in range");
+
+ // TEST CASE 5: "Right aquifer fully envelopes left aquifer"
+ //
+ // ------------------------------------------------------------- Level 0 m
+ // Upper layer (not aquifer) |------------------------------ Level -5 m
+ // ------------------------------| Level -10 m
+ // Left bottom aquifer layer | Right bottom aquifer layer Level -15 m
+ // ------------------------------| Level -20 m
+ // |------------------------------ Level -25 m
+ soilBottomLayerAquiferPartRight = CreateRectangularSoilLayer2D(-5, -25, middleXCoordinate, rightCoordinate, true);
+ var soilProfileRightAquiferLayerFullyEnvelopsLeft = new SoilProfile2D
+ {
+ Geometry = new GeometryData
+ {
+ Left = leftCoordinate,
+ Right = rightCoordinate,
+ Bottom = -25
+ }
+ };
+ soilProfileRightAquiferLayerFullyEnvelopsLeft.Surfaces.Add(soilUpperLayer);
+ soilProfileRightAquiferLayerFullyEnvelopsLeft.Surfaces.Add(soilBottomLayerAquiferPartLeft);
+ soilProfileRightAquiferLayerFullyEnvelopsLeft.Surfaces.Add(soilBottomLayerAquiferPartRight);
+ soilProfileRightAquiferLayerFullyEnvelopsLeft.Geometry.Surfaces.Add(new GeometrySurface());
+
+ yield return new TestCaseData(soilProfileRightAquiferLayerFullyEnvelopsLeft, new[]
+ {
+ new GeometryPoint(leftCoordinate, -10),
+ new GeometryPoint(middleXCoordinate, -10),
+ new GeometryPoint(middleXCoordinate, -5),
+ new GeometryPoint(rightCoordinate, -5)
+ }).SetName("Right aquifer fully envelopes left aquifer");
+
+ // TEST CASE 6: "Right aquifer fully enveloped by left aquifer"
+ //
+ // ------------------------------------------------------------- Level 0 m
+ // Upper layer (not aquifer) |
+ // ------------------------------|------------------------------ Level -10 m
+ // Left bottom aquifer layer |------------------------------ Level -15 m
+ // | Right bottom aquifer layer |
+ // |------------------------------ Level -17 m
+ // ------------------------------| Level -20 m
+ soilBottomLayerAquiferPartRight = CreateRectangularSoilLayer2D(-15, -17, middleXCoordinate, rightCoordinate, true);
+ var soilProfileRightAquiferLayerFullyEnvelopedByLeft = new SoilProfile2D
+ {
+ Geometry = new GeometryData
+ {
+ Left = leftCoordinate,
+ Right = rightCoordinate,
+ Bottom = -20
+ }
+ };
+ soilProfileRightAquiferLayerFullyEnvelopedByLeft.Surfaces.Add(soilUpperLayer);
+ soilProfileRightAquiferLayerFullyEnvelopedByLeft.Surfaces.Add(soilBottomLayerAquiferPartLeft);
+ soilProfileRightAquiferLayerFullyEnvelopedByLeft.Surfaces.Add(soilBottomLayerAquiferPartRight);
+ soilProfileRightAquiferLayerFullyEnvelopedByLeft.Geometry.Surfaces.Add(new GeometrySurface());
+
+ yield return new TestCaseData(soilProfileRightAquiferLayerFullyEnvelopedByLeft, new[]
+ {
+ new GeometryPoint(leftCoordinate, -10),
+ new GeometryPoint(middleXCoordinate, -10),
+ new GeometryPoint(middleXCoordinate, -15),
+ new GeometryPoint(rightCoordinate, -15)
+ }).SetName("Right aquifer fully enveloped by left aquifer");
+ }
+
+ private static SoilLayer2D CreateSoilLayer2D(Point2D topLeftCoordinate, Point2D topRightCoordinate,
+ Point2D bottomRightCoordinate, Point2D bottomLeftCoordinate, bool isAquifer)
+ {
+ return new SoilLayer2D
+ {
+ GeometrySurface = new GeometrySurface
+ {
+ OuterLoop = new GeometryLoop
+ {
+ CurveList =
+ {
+ new GeometryCurve(topLeftCoordinate, topRightCoordinate),
+ new GeometryCurve(topRightCoordinate, bottomRightCoordinate),
+ new GeometryCurve(bottomRightCoordinate, bottomLeftCoordinate),
+ new GeometryCurve(bottomLeftCoordinate, topLeftCoordinate)
+ }
+ }
+ },
+ IsAquifer = isAquifer
+ };
+ }
+
+ ///
+ /// Creates a rectangular .
+ ///
+ ///
+ ///
+ ///
+ ///
+ ///
+ /// A rectangular .
+ private static SoilLayer2D CreateRectangularSoilLayer2D(double topCoord, double bottomCoord, double leftCoord, double rightCoord, bool isAquifer)
+ {
+ var topLeftPoint = new Point2D(leftCoord, topCoord);
+ var topRightPoint = new Point2D(rightCoord, topCoord);
+ var bottomRightPoint = new Point2D(rightCoord, bottomCoord);
+ var bottomLeftPoint = new Point2D(leftCoord, bottomCoord);
+
+ return CreateSoilLayer2D(topLeftPoint, topRightPoint, bottomRightPoint, bottomLeftPoint, isAquifer);
+ }
+
+ private static void AssertGeometry(IEnumerable expectedPoints, IEnumerable actualPoints)
+ {
+ GeometryPoint[] convertedPoints = expectedPoints.Select(p => new GeometryPoint(p.X, p.Z)).ToArray();
+ AssertGeometry(convertedPoints, actualPoints);
+ }
+
+ private static void AssertGeometry(IEnumerable expectedPoints, IEnumerable actualPoints)
+ {
+ int expectedNrOfPoints = expectedPoints.Count();
+ Assert.That(actualPoints.Count(), Is.EqualTo(expectedNrOfPoints));
+
+ for (var i = 0; i < expectedNrOfPoints; i++)
+ {
+ GeometryPoint expectedPoint = expectedPoints.ElementAt(i);
+ GeometryPoint actualPoint = actualPoints.ElementAt(i);
+ Assert.Multiple(() =>
+ {
+ Assert.That(actualPoint.X, Is.EqualTo(expectedPoint.X).Within(precision5Decimals));
+ Assert.That(actualPoint.Z, Is.EqualTo(expectedPoint.Z).Within(precision5Decimals));
+ });
+ }
+ }
+}
\ No newline at end of file
Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/KernelWrappers/MacroStabilityCommon/PlLinesToWaternetConverterTests.cs
===================================================================
diff -u -r5325 -r5382
--- DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/KernelWrappers/MacroStabilityCommon/PlLinesToWaternetConverterTests.cs (.../PlLinesToWaternetConverterTests.cs) (revision 5325)
+++ DamEngine/trunk/src/Deltares.DamEngine.Calculators.Tests/KernelWrappers/MacroStabilityCommon/PlLinesToWaternetConverterTests.cs (.../PlLinesToWaternetConverterTests.cs) (revision 5382)
@@ -597,716 +597,9 @@
});
}
- ///
- /// Different soil profiles 2D are tested, see the pictures in method GetSoilProfilesWithContinuousBottomAquiferLayer,
- /// with a top clay layer and bottom aquifer layers always forming a continuous bottom layer.
- /// As there is only one aquifer, then the BottomAquifer is also the HighestAquifer.
- ///
- ///
- ///
- [Test]
- [TestCaseSource(nameof(GetSoilProfilesWithContinuousBottomAquiferLayer))]
- public void Given2DSoilProfileWithContinuousBottomAquifer_WhenDeterminingLayerBoundaryPointsOfBottomAquifer_ThenExpectedCoordinatesReturned(
- SoilProfile2D soilProfile, IEnumerable expectedBottomAquiferCoordinates)
- {
- // Call
- PlLinesToWaternetConverter.DetermineAquiferLayerBoundaryPoints(PlLinesToWaternetConverter.LayerType.BottomAquiferCluster, soilProfile, out Point2D[] bottomAquifer, out _);
- PlLinesToWaternetConverter.DetermineAquiferLayerBoundaryPoints(PlLinesToWaternetConverter.LayerType.HighestAquiferCluster, soilProfile, out Point2D[] highestAquifer, out _);
-
- // Assert
- AssertGeometry(bottomAquifer, expectedBottomAquiferCoordinates);
- AssertGeometry(highestAquifer, expectedBottomAquiferCoordinates);
- }
-
///
- /// |-------------------------------------------------------------| Level 0 m
- /// | Aquitard 1 |
- /// |-------------------------------------------------------------| Level -10 m
- /// | Aquitard 2 B /------------------------\ C | Level -12 m
- /// | / Aquifer 1 \ |
- /// | / point X \ |
- /// |---------------/--------------*---------------\--------------| Level -20 m
- /// | A Aquifer 2 D |
- /// |------------------------------*------------------------------| Level -30 m
- /// point Y
- ///
- [Test]
- [TestCase(-20,-30)]
- [TestCase(-20.1,-30)]
- [TestCase(-19.9,-30)]
- [TestCase(-20,-30.1)]
- [TestCase(-20,-29.9)]
- public void Given2DSoilProfileWithNotContinuousAquiferConnectedToContinuousAquifer_WhenDeterminingLayerBoundaryPointsOfAquifer_ThenExpectedCoordinatesReturned(double zPointX, double zPointY)
- {
- var pointA = new Point2D(leftCoordinate + (rightCoordinate - leftCoordinate) / 3, -20);
- var pointB = new Point2D(pointA.X + 0.01, -12);
- var pointC = new Point2D(leftCoordinate + 2 * (rightCoordinate - leftCoordinate) / 3, -12);
- var pointD = new Point2D(pointC.X + 0.01, -20);
- var pointX = new Point2D(middleXCoordinate, zPointX);
- var pointY = new Point2D(middleXCoordinate, zPointY);
-
- SoilLayer2D soilUpperLayer = CreateRectangularSoilLayer2D(0, -10, leftCoordinate, rightCoordinate, false);
- SoilLayer2D soilLayerAquitard2 = FactoryForSoilProfiles.CreatePolygoneSoilLayer2D([
- ..new[]
- {
- new Point2D(leftCoordinate, -10),
- new Point2D(rightCoordinate, -10),
- new Point2D(rightCoordinate, -20),
- pointD,
- pointC,
- pointB,
- pointA,
- new Point2D(leftCoordinate, -20)
- }
- ], null);
- SoilLayer2D soilLayerAquifer1 = FactoryForSoilProfiles.CreatePentagonSoilLayer2D(pointA, pointB, pointC, pointD, pointX, null, null, true);
- SoilLayer2D soilLayerAquifer2 = FactoryForSoilProfiles.CreatePolygoneSoilLayer2D([
- ..new[]
- {
- new Point2D(leftCoordinate, -20),
- pointA,
- pointX,
- pointD,
- new Point2D(rightCoordinate, -20),
- new Point2D(rightCoordinate, -30),
- pointY,
- new Point2D(leftCoordinate, -30)
- }
- ], null, true);
-
- var soilProfile = new SoilProfile2D
- {
- Geometry = new GeometryData
- {
- Left = leftCoordinate,
- Right = rightCoordinate,
- Bottom = -30
- }
- };
- soilProfile.Surfaces.Add(soilUpperLayer);
- soilProfile.Surfaces.Add(soilLayerAquitard2);
- soilProfile.Surfaces.Add(soilLayerAquifer1);
- soilProfile.Surfaces.Add(soilLayerAquifer2);
- soilProfile.Geometry.Surfaces.Add(new GeometrySurface());
-
- // Call
- PlLinesToWaternetConverter.DetermineAquiferLayerBoundaryPoints(PlLinesToWaternetConverter.LayerType.BottomAquiferCluster, soilProfile, out Point2D[] bottomAquifer, out _);
- PlLinesToWaternetConverter.DetermineAquiferLayerBoundaryPoints(PlLinesToWaternetConverter.LayerType.HighestAquiferCluster, soilProfile, out Point2D[] highestAquifer, out _);
-
- // Assert
- var expectedBottomAquiferCoordinates = new[]
- {
- new GeometryPoint(leftCoordinate, -20),
- new GeometryPoint(pointA.X, pointA.Z),
- new GeometryPoint(pointB.X, pointB.Z),
- new GeometryPoint(middleXCoordinate, -12),
- new GeometryPoint(pointC.X, pointC.Z),
- new GeometryPoint(pointD.X, pointD.Z),
- new GeometryPoint(rightCoordinate, -20)
- };
- AssertGeometry(bottomAquifer, expectedBottomAquiferCoordinates);
- AssertGeometry(highestAquifer, expectedBottomAquiferCoordinates);
- }
-
- ///
- /// --------------------------------------------------------------- Level 0 m
- /// top layer
- /// --------------------------------------------------------------- Level -10 m
- /// in-between aquifer layer left | in-between aquifer layer right
- /// --------------------------------------------------------------- Level -20 m
- /// in-between layer
- /// --------------------------------------------------------------- Level -25 m
- /// bottom aquifer layer
- /// --------------------------------------------------------------- Level -30 m
- ///
- [Test]
- public void Given2DSoilProfileWithContinuousInBetweenAquiferLayerConsistingOfTwoParts_WhenDeterminingLayerBoundaryPointsOfInBetweenAquifer_ThenExpectedCoordinatesReturned()
- {
- // Setup
- SoilLayer2D soilLayer = CreateRectangularSoilLayer2D(0, -10, leftCoordinate, rightCoordinate, false);
- SoilLayer2D soilLayerAquiferInBetweenLeft = CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, true);
- SoilLayer2D soilLayerAquiferInBetweenRight = CreateRectangularSoilLayer2D(-10, -20, middleXCoordinate, rightCoordinate, true);
- SoilLayer2D soilLayerInBetween = CreateRectangularSoilLayer2D(-20, -25, leftCoordinate, rightCoordinate, false);
- SoilLayer2D soilLayerAquiferBottom = CreateRectangularSoilLayer2D(-25, -30, leftCoordinate, rightCoordinate, true);
-
- var soilProfile = new SoilProfile2D
- {
- Geometry = new GeometryData
- {
- Left = leftCoordinate,
- Right = rightCoordinate,
- Bottom = -30
- }
- };
- soilProfile.Surfaces.Add(soilLayer);
- soilProfile.Surfaces.Add(soilLayerAquiferInBetweenLeft);
- soilProfile.Surfaces.Add(soilLayerAquiferInBetweenRight);
- soilProfile.Surfaces.Add(soilLayerInBetween);
- soilProfile.Surfaces.Add(soilLayerAquiferBottom);
- soilProfile.Geometry.Surfaces.Add(new GeometrySurface());
-
- // Call
- bool isInBetweenLayerPresent = PlLinesToWaternetConverter.AreInBetweenAquiferClustersPresent(soilProfile, out int count);
- PlLinesToWaternetConverter.DetermineAquiferLayerBoundaryPoints(PlLinesToWaternetConverter.LayerType.InBetweenAquiferCluster, soilProfile, out Point2D[] topLevelInBetweenAquifer, out Point2D[] bottomLevelInBetweenAquifer, 0);
-
- // Assert
- Assert.Multiple(() =>
- {
- Assert.That(isInBetweenLayerPresent, Is.True);
- Assert.That(count, Is.EqualTo(1));
- });
- GeometryPoint[] expectedTop =
- [
- new(leftCoordinate, -10),
- new(middleXCoordinate, -10),
- new(rightCoordinate, -10)
- ];
- GeometryPoint[] expectedBottom =
- [
- new(leftCoordinate, -20),
- new(middleXCoordinate, -20),
- new(rightCoordinate, -20)
- ];
- AssertGeometry(topLevelInBetweenAquifer, expectedTop);
- AssertGeometry(bottomLevelInBetweenAquifer, expectedBottom);
- }
-
- ///
/// --------------------------------------------------- Level 0 m
- /// top layer
- /// --------------------------------------------------- Level -10 m
- /// in-between aquifer layer
- /// --------------------------------------------------- Level -20 m
- /// in-between layer
- /// --------------------------------------------------- Level -25 m
- /// bottom aquifer layer
- /// --------------------------------------------------- Level -30 m
- ///
- [Test]
- public void Given2DSoilProfileWithContinuousInBetweenAquiferLayerConsistingOfOnePart_WhenDeterminingLayerBoundaryPointsOfInBetweenAquifer_ThenExpectedCoordinatesReturned()
- {
- // Setup
- SoilLayer2D soilLayer = CreateRectangularSoilLayer2D(0, -10, leftCoordinate, rightCoordinate, false);
- SoilLayer2D soilLayerAquiferInBetween = CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, rightCoordinate, true);
- SoilLayer2D soilLayerInBetween = CreateRectangularSoilLayer2D(-20, -25, leftCoordinate, rightCoordinate, false);
- SoilLayer2D soilLayerAquiferBottom = CreateRectangularSoilLayer2D(-25, -30, leftCoordinate, rightCoordinate, true);
-
- var soilProfile = new SoilProfile2D
- {
- Geometry = new GeometryData
- {
- Left = leftCoordinate,
- Right = rightCoordinate,
- Bottom = -30
- }
- };
- soilProfile.Surfaces.Add(soilLayer);
- soilProfile.Surfaces.Add(soilLayerAquiferInBetween);
- soilProfile.Surfaces.Add(soilLayerInBetween);
- soilProfile.Surfaces.Add(soilLayerAquiferBottom);
- soilProfile.Geometry.Surfaces.Add(new GeometrySurface());
-
- // Call
- bool isInBetweenLayerPresent = PlLinesToWaternetConverter.AreInBetweenAquiferClustersPresent(soilProfile, out int count);
- PlLinesToWaternetConverter.DetermineAquiferLayerBoundaryPoints(PlLinesToWaternetConverter.LayerType.InBetweenAquiferCluster, soilProfile, out Point2D[] topLevelInBetweenAquifer, out Point2D[] bottomLevelInBetweenAquifer, 0);
-
- // Assert
- Assert.Multiple(() =>
- {
- Assert.That(isInBetweenLayerPresent, Is.True);
- Assert.That(count, Is.EqualTo(1));
- });
- GeometryPoint[] expectedTop =
- [
- new(leftCoordinate, -10),
- new(rightCoordinate, -10)
- ];
- GeometryPoint[] expectedBottom =
- [
- new(leftCoordinate, -20),
- new(rightCoordinate, -20)
- ];
- AssertGeometry(topLevelInBetweenAquifer, expectedTop);
- AssertGeometry(bottomLevelInBetweenAquifer, expectedBottom);
- }
-
- ///
- /// ------------------------------------------------------------- Level 0 m
- /// top layer
- /// ------------------------------------------------------------- Level -10 m
- /// | Gap layer
- /// in-between aquifer |------------------------------- Level -15 m
- /// layer left |
- /// | in-between aquifer
- /// -----------------------------| layer right Level -20 m
- /// in-between layer |
- /// |------------------------------- Level -21 m
///
- /// ------------------------------------------------------------- Level -25 m
- /// bottom aquifer layer
- /// ------------------------------------------------------------- Level -30 m
- ///
- [Test]
- public void Given2DSoilProfileWithContinuousInBetweenAquiferConsistingOfTwoLayersWithRightLayerTopLevelInRangeLeftLayer_WhenDeterminingLayerBoundaryPointsOfInBetweenAquifer_ThenExpectedCoordinatesReturned()
- {
- // Setup
- SoilLayer2D soilLayer = CreateRectangularSoilLayer2D(0, -10, leftCoordinate, rightCoordinate, false);
- SoilLayer2D soilLayerAquiferInBetweenLeft = CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, true);
- // Add a layer to fill the gap between the right aquifer layer and the upper layer
- SoilLayer2D soilLayerGap = CreateRectangularSoilLayer2D(-10, -15, middleXCoordinate, rightCoordinate, false);
- SoilLayer2D soilLayerAquiferInBetweenRight = CreateRectangularSoilLayer2D(-15, -21, middleXCoordinate, rightCoordinate, true);
- // Add continuous in-between layer
- var bottomLeftInBetweenAquiferLayerLeft = new Point2D(leftCoordinate, -20);
- var bottomRightInBetweenAquiferLayerLeft = new Point2D(middleXCoordinate, -20);
- var bottomLeftInBetweenAquiferLayerRight = new Point2D(middleXCoordinate, -21);
- var bottomRightInBetweenAquiferLayerRight = new Point2D(rightCoordinate, -21);
- var bottomRightInBetweenLayer = new Point2D(rightCoordinate, -25);
- var bottomLeftInBetweenLayer = new Point2D(leftCoordinate, -25);
- var soilLayerInBetween = new SoilLayer2D
- {
- GeometrySurface = new GeometrySurface
- {
- OuterLoop = new GeometryLoop
- {
- CurveList =
- {
- new GeometryCurve(bottomLeftInBetweenAquiferLayerLeft, bottomRightInBetweenAquiferLayerLeft),
- new GeometryCurve(bottomRightInBetweenAquiferLayerLeft, bottomLeftInBetweenAquiferLayerRight),
- new GeometryCurve(bottomLeftInBetweenAquiferLayerRight, bottomRightInBetweenAquiferLayerRight),
- new GeometryCurve(bottomRightInBetweenAquiferLayerRight, bottomRightInBetweenLayer),
- new GeometryCurve(bottomRightInBetweenLayer, bottomLeftInBetweenLayer)
- }
- }
- }
- };
- SoilLayer2D soilLayerAquiferBottom = CreateRectangularSoilLayer2D(-25, -30, leftCoordinate, rightCoordinate, true);
-
- var soilProfile = new SoilProfile2D
- {
- Geometry = new GeometryData
- {
- Left = leftCoordinate,
- Right = rightCoordinate,
- Bottom = -30
- }
- };
- soilProfile.Surfaces.Add(soilLayer);
- soilProfile.Surfaces.Add(soilLayerAquiferInBetweenLeft);
- soilProfile.Surfaces.Add(soilLayerGap);
- soilProfile.Surfaces.Add(soilLayerAquiferInBetweenRight);
- soilProfile.Surfaces.Add(soilLayerInBetween);
- soilProfile.Surfaces.Add(soilLayerAquiferBottom);
- soilProfile.Geometry.Surfaces.Add(new GeometrySurface());
-
- // Call
- bool isInBetweenLayerPresent = PlLinesToWaternetConverter.AreInBetweenAquiferClustersPresent(soilProfile, out int count);
- PlLinesToWaternetConverter.DetermineAquiferLayerBoundaryPoints(PlLinesToWaternetConverter.LayerType.InBetweenAquiferCluster, soilProfile, out Point2D[] topLevelInBetweenAquifer, out Point2D[] bottomLevelInBetweenAquifer, 0);
-
- // Assert
- Assert.Multiple(() =>
- {
- Assert.That(isInBetweenLayerPresent, Is.True);
- Assert.That(count, Is.EqualTo(1));
- });
- GeometryPoint[] expectedTop =
- [
- new(leftCoordinate, -10),
- new(middleXCoordinate, -10),
- new(middleXCoordinate, -15),
- new(rightCoordinate, -15)
- ];
- GeometryPoint[] expectedBottom =
- [
- new(leftCoordinate, -20),
- new(middleXCoordinate, -20),
- new(middleXCoordinate, -21),
- new(rightCoordinate, -21)
- ];
- AssertGeometry(topLevelInBetweenAquifer, expectedTop);
- AssertGeometry(bottomLevelInBetweenAquifer, expectedBottom);
- }
-
- ///
- /// -------------------------------------------------------------- Level 0 m
- /// top layer
- /// |------------------------------- Level -5 m
- /// |
- /// | in-between aquifer
- /// ------------------------------| layer right Level -10 m
- /// in-between aquifer layer left |
- /// ------------------------------------------------------------- Level -20 m
- /// in-between layer
- /// -------------------------------------------------------------- Level -25 m
- /// bottom aquifer layer
- /// -------------------------------------------------------------- Level -30 m
- ///
- [Test]
- public void Given2DSoilProfileWithContinuousInBetweenAquiferConsistingOfTwoLayersWithRightLayerBottomLevelInRangeLeftLayer_WhenDeterminingLayerBoundaryPointsOfInBetweenAquifer_ThenExpectedCoordinatesReturned()
- {
- // Setup
- var topLeftUpperLayer = new Point2D(leftCoordinate, 0);
- var topRightUpperLayer = new Point2D(rightCoordinate, 0);
- var bottomRightUpperLayer = new Point2D(rightCoordinate, -5);
- var bottomIntermediateUpperUpperLayer = new Point2D(middleXCoordinate, -5);
- var bottomIntermediateLowerUpperLayer = new Point2D(middleXCoordinate, -10);
- var bottomLeftUpperLayer = new Point2D(leftCoordinate, -10);
- var soilLayer = new SoilLayer2D
- {
- GeometrySurface = new GeometrySurface
- {
- OuterLoop = new GeometryLoop
- {
- CurveList =
- {
- new GeometryCurve(topLeftUpperLayer, topRightUpperLayer),
- new GeometryCurve(topRightUpperLayer, bottomRightUpperLayer),
- new GeometryCurve(bottomRightUpperLayer, bottomIntermediateUpperUpperLayer),
- new GeometryCurve(bottomIntermediateUpperUpperLayer, bottomIntermediateLowerUpperLayer),
- new GeometryCurve(bottomIntermediateLowerUpperLayer, bottomLeftUpperLayer),
- new GeometryCurve(bottomLeftUpperLayer, topLeftUpperLayer)
- }
- }
- }
- };
- SoilLayer2D soilLayerAquiferInBetweenLeft = CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, true);
- SoilLayer2D soilLayerAquiferInBetweenRight = CreateRectangularSoilLayer2D(-5, -20, middleXCoordinate, rightCoordinate, true);
- SoilLayer2D soilLayerInBetween = CreateRectangularSoilLayer2D(-20, -25, leftCoordinate, rightCoordinate, false);
- SoilLayer2D soilLayerAquiferBottom = CreateRectangularSoilLayer2D(-25, -30, leftCoordinate, rightCoordinate, true);
- soilLayerAquiferBottom.IsAquifer = true;
-
- var soilProfile = new SoilProfile2D
- {
- Geometry = new GeometryData
- {
- Left = leftCoordinate,
- Right = rightCoordinate,
- Bottom = -30
- }
- };
- soilProfile.Surfaces.Add(soilLayer);
- soilProfile.Surfaces.Add(soilLayerAquiferInBetweenLeft);
- soilProfile.Surfaces.Add(soilLayerAquiferInBetweenRight);
- soilProfile.Surfaces.Add(soilLayerInBetween);
- soilProfile.Surfaces.Add(soilLayerAquiferBottom);
- soilProfile.Geometry.Surfaces.Add(new GeometrySurface());
-
- // Call
- bool isInBetweenLayerPresent = PlLinesToWaternetConverter.AreInBetweenAquiferClustersPresent(soilProfile, out int count);
- PlLinesToWaternetConverter.DetermineAquiferLayerBoundaryPoints(PlLinesToWaternetConverter.LayerType.InBetweenAquiferCluster, soilProfile, out Point2D[] topLevelInBetweenAquifer, out Point2D[] bottomLevelInBetweenAquifer, 0);
-
- // Assert
- Assert.Multiple(() =>
- {
- Assert.That(isInBetweenLayerPresent, Is.True);
- Assert.That(count, Is.EqualTo(1));
- });
- GeometryPoint[] expectedTop =
- [
- new(leftCoordinate, -10),
- new(middleXCoordinate, -10),
- new(middleXCoordinate, -5),
- new(rightCoordinate, -5)
- ];
- GeometryPoint[] expectedBottom =
- [
- new(leftCoordinate, -20),
- new(middleXCoordinate, -20),
- new(middleXCoordinate, -20),
- new(rightCoordinate, -20)
- ];
- AssertGeometry(topLevelInBetweenAquifer, expectedTop);
- AssertGeometry(bottomLevelInBetweenAquifer, expectedBottom);
- }
-
- ///
- /// ------------------------------------------------------------- Level 0 m
- /// top layer
- ///
- /// -----------------------------| Level -10 m
- /// in-between aquifer |
- /// layer left |------------------------------- Level -15 m
- /// | in-between aquifer layer right
- /// | ------------------------------ Level -17 m
- /// |
- /// |
- /// -----------------------------| Level -20 m
- /// in-between layer
- /// ------------------------------------------------------------- Level -25 m
- /// bottom aquifer layer
- /// ------------------------------------------------------------- Level -30 m
- ///
- [Test]
- public void Given2DSoilProfileWithContinuousInBetweenAquiferConsistingOfTwoLayersWithRightLayerEnvelopedByLeftLayer_WhenDeterminingLayerBoundaryPointsOfInBetweenAquifer_ThenExpectedCoordinatesReturned()
- {
- // Setup
- var topLeftUpperLayer = new Point2D(leftCoordinate, 0);
- var topRightUpperLayer = new Point2D(rightCoordinate, 0);
- var bottomRightUpperLayer = new Point2D(rightCoordinate, -15);
- var bottomIntermediateLowerUpperLayer = new Point2D(middleXCoordinate, -15);
- var bottomIntermediateUpperUpperLayer = new Point2D(middleXCoordinate, -10);
- var bottomLeftUpperLayer = new Point2D(leftCoordinate, -10);
- var soilLayer = new SoilLayer2D
- {
- GeometrySurface = new GeometrySurface
- {
- OuterLoop = new GeometryLoop
- {
- CurveList =
- {
- new GeometryCurve(topLeftUpperLayer, topRightUpperLayer),
- new GeometryCurve(topRightUpperLayer, bottomRightUpperLayer),
- new GeometryCurve(bottomRightUpperLayer, bottomIntermediateLowerUpperLayer),
- new GeometryCurve(bottomIntermediateLowerUpperLayer, bottomIntermediateUpperUpperLayer),
- new GeometryCurve(bottomIntermediateUpperUpperLayer, bottomLeftUpperLayer),
- new GeometryCurve(bottomLeftUpperLayer, topLeftUpperLayer)
- }
- }
- }
- };
- SoilLayer2D soilLayerAquiferInBetweenLeft = CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, true);
- SoilLayer2D soilLayerAquiferInBetweenRight = CreateRectangularSoilLayer2D(-15, -17, middleXCoordinate, rightCoordinate, true);
-
- var bottomLeftInBetweenAquiferLayerLeft = new Point2D(leftCoordinate, -20);
- var bottomRightInBetweenAquiferLayerLeft = new Point2D(middleXCoordinate, -20);
- var bottomLeftInBetweenAquiferLayerRight = new Point2D(middleXCoordinate, -17);
- var bottomRightInBetweenAquiferLayerRight = new Point2D(rightCoordinate, -17);
- var bottomRightInBetweenLayer = new Point2D(rightCoordinate, -25);
- var bottomLeftInBetweenLayer = new Point2D(leftCoordinate, -25);
- var soilLayerInBetween = new SoilLayer2D
- {
- GeometrySurface = new GeometrySurface
- {
- OuterLoop = new GeometryLoop
- {
- CurveList =
- {
- new GeometryCurve(bottomLeftInBetweenAquiferLayerLeft, bottomRightInBetweenAquiferLayerLeft),
- new GeometryCurve(bottomRightInBetweenAquiferLayerLeft, bottomLeftInBetweenAquiferLayerRight),
- new GeometryCurve(bottomLeftInBetweenAquiferLayerRight, bottomRightInBetweenAquiferLayerRight),
- new GeometryCurve(bottomRightInBetweenAquiferLayerRight, bottomRightInBetweenLayer),
- new GeometryCurve(bottomRightInBetweenLayer, bottomLeftInBetweenLayer),
- new GeometryCurve(bottomLeftInBetweenLayer, bottomLeftInBetweenAquiferLayerLeft)
- }
- }
- }
- };
- SoilLayer2D soilLayerAquiferBottom = CreateRectangularSoilLayer2D(-25, -30, leftCoordinate, rightCoordinate, true);
-
- var soilProfile = new SoilProfile2D
- {
- Geometry = new GeometryData
- {
- Left = leftCoordinate,
- Right = rightCoordinate,
- Bottom = -30
- }
- };
- soilProfile.Surfaces.Add(soilLayer);
- soilProfile.Surfaces.Add(soilLayerAquiferInBetweenLeft);
- soilProfile.Surfaces.Add(soilLayerAquiferInBetweenRight);
- soilProfile.Surfaces.Add(soilLayerInBetween);
- soilProfile.Surfaces.Add(soilLayerAquiferBottom);
- soilProfile.Geometry.Surfaces.Add(new GeometrySurface());
-
- // Call
- bool isInBetweenLayerPresent = PlLinesToWaternetConverter.AreInBetweenAquiferClustersPresent(soilProfile, out int count);
- PlLinesToWaternetConverter.DetermineAquiferLayerBoundaryPoints(PlLinesToWaternetConverter.LayerType.InBetweenAquiferCluster, soilProfile, out Point2D[] topLevelInBetweenAquifer, out Point2D[] bottomLevelInBetweenAquifer, 0);
-
- // Assert
- Assert.Multiple(() =>
- {
- Assert.That(isInBetweenLayerPresent, Is.True);
- Assert.That(count, Is.EqualTo(1));
- });
- GeometryPoint[] expectedTop =
- [
- new(leftCoordinate, -10),
- new(middleXCoordinate, -10),
- new(middleXCoordinate, -15),
- new(rightCoordinate, -15)
- ];
- GeometryPoint[] expectedBottom =
- [
- new(leftCoordinate, -20),
- new(middleXCoordinate, -20),
- new(middleXCoordinate, -17),
- new(rightCoordinate, -17)
- ];
- AssertGeometry(topLevelInBetweenAquifer, expectedTop);
- AssertGeometry(bottomLevelInBetweenAquifer, expectedBottom);
- }
-
- ///
- /// ------------------------------------------------------------- Level 0 m
- /// top layer
- /// |------------------------------ Level -5 m
- /// | in-between aquifer
- /// ------------------------------| layer right Level -10 m
- /// in-between aquifer layer left |
- /// |
- /// ------------------------------| Level -20 m
- /// in-between layer |
- /// |------------------------------ Level -21 m
- ///
- /// ------------------------------------------------------------- Level -25 m
- /// bottom aquifer layer
- /// ------------------------------------------------------------- Level -30 m
- ///
- [Test]
- public void Given2DSoilProfileWithContinuousInBetweenAquiferConsistingOfTwoLayersWithLeftLayerEnvelopedByRightLayer_WhenDeterminingLayerBoundaryPointsOfInBetweenAquifer_ThenExpectedCoordinatesReturned()
- {
- // Setup
- var topLeftUpperLayer = new Point2D(leftCoordinate, 0);
- var topRightUpperLayer = new Point2D(rightCoordinate, 0);
- var bottomRightUpperLayer = new Point2D(rightCoordinate, -5);
- var bottomIntermediateLowerUpperLayer = new Point2D(middleXCoordinate, -5);
- var bottomIntermediateUpperUpperLayer = new Point2D(middleXCoordinate, -10);
- var bottomLeftUpperLayer = new Point2D(leftCoordinate, -10);
- var soilLayer = new SoilLayer2D
- {
- GeometrySurface = new GeometrySurface
- {
- OuterLoop = new GeometryLoop
- {
- CurveList =
- {
- new GeometryCurve(topLeftUpperLayer, topRightUpperLayer),
- new GeometryCurve(topRightUpperLayer, bottomRightUpperLayer),
- new GeometryCurve(bottomRightUpperLayer, bottomIntermediateLowerUpperLayer),
- new GeometryCurve(bottomIntermediateLowerUpperLayer, bottomIntermediateUpperUpperLayer),
- new GeometryCurve(bottomIntermediateUpperUpperLayer, bottomLeftUpperLayer),
- new GeometryCurve(bottomLeftUpperLayer, topLeftUpperLayer)
- }
- }
- }
- };
-
- SoilLayer2D soilLayerAquiferInBetweenLeft = CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, true);
- SoilLayer2D soilLayerAquiferInBetweenRight = CreateRectangularSoilLayer2D(-5, -21, middleXCoordinate, rightCoordinate, true);
-
- var bottomLeftInBetweenAquiferLayerLeft = new Point2D(leftCoordinate, -20);
- var bottomRightInBetweenAquiferLayerLeft = new Point2D(middleXCoordinate, -20);
- var bottomLeftInBetweenAquiferLayerRight = new Point2D(middleXCoordinate, -21);
- var bottomRightInBetweenAquiferLayerRight = new Point2D(rightCoordinate, -21);
- var bottomRightInBetweenLayer = new Point2D(rightCoordinate, -25);
- var bottomLeftInBetweenLayer = new Point2D(leftCoordinate, -25);
- var soilLayerInBetween = new SoilLayer2D
- {
- GeometrySurface = new GeometrySurface
- {
- OuterLoop = new GeometryLoop
- {
- CurveList =
- {
- new GeometryCurve(bottomLeftInBetweenAquiferLayerLeft, bottomRightInBetweenAquiferLayerLeft),
- new GeometryCurve(bottomRightInBetweenAquiferLayerLeft, bottomLeftInBetweenAquiferLayerRight),
- new GeometryCurve(bottomLeftInBetweenAquiferLayerRight, bottomRightInBetweenAquiferLayerRight),
- new GeometryCurve(bottomRightInBetweenAquiferLayerRight, bottomRightInBetweenLayer),
- new GeometryCurve(bottomRightInBetweenLayer, bottomLeftInBetweenLayer),
- new GeometryCurve(bottomLeftInBetweenLayer, bottomLeftInBetweenAquiferLayerLeft)
- }
- }
- }
- };
- SoilLayer2D soilLayerAquiferBottom = CreateRectangularSoilLayer2D(-25, -30, leftCoordinate, rightCoordinate, true);
-
- var soilProfile = new SoilProfile2D
- {
- Geometry = new GeometryData
- {
- Left = leftCoordinate,
- Right = rightCoordinate,
- Bottom = -30
- }
- };
- soilProfile.Surfaces.Add(soilLayer);
- soilProfile.Surfaces.Add(soilLayerAquiferInBetweenLeft);
- soilProfile.Surfaces.Add(soilLayerAquiferInBetweenRight);
- soilProfile.Surfaces.Add(soilLayerInBetween);
- soilProfile.Surfaces.Add(soilLayerAquiferBottom);
- soilProfile.Geometry.Surfaces.Add(new GeometrySurface());
-
- // Call
- bool isInBetweenLayerPresent = PlLinesToWaternetConverter.AreInBetweenAquiferClustersPresent(soilProfile, out int count);
- PlLinesToWaternetConverter.DetermineAquiferLayerBoundaryPoints(PlLinesToWaternetConverter.LayerType.InBetweenAquiferCluster, soilProfile, out Point2D[] topLevelInBetweenAquifer, out Point2D[] bottomLevelInBetweenAquifer, 0);
-
- // Assert
- Assert.Multiple(() =>
- {
- Assert.That(isInBetweenLayerPresent, Is.True);
- Assert.That(count, Is.EqualTo(1));
- });
- GeometryPoint[] expectedTop =
- [
- new(leftCoordinate, -10),
- new(middleXCoordinate, -10),
- new(middleXCoordinate, -5),
- new(rightCoordinate, -5)
- ];
- GeometryPoint[] expectedBottom =
- [
- new(leftCoordinate, -20),
- new(middleXCoordinate, -20),
- new(middleXCoordinate, -21),
- new(rightCoordinate, -21)
- ];
- AssertGeometry(topLevelInBetweenAquifer, expectedTop);
- AssertGeometry(bottomLevelInBetweenAquifer, expectedBottom);
- }
-
- ///
- /// --------------------------------------------------- Level 0 m
- /// top layer
- /// -------------------------|------------------------- Level -10 m
- /// in-between layer left | in-between layer right
- /// -------------------------|------------------------- Level -20 m
- /// in-between layer
- /// --------------------------------------------------- Level -25 m
- /// bottom aquifer layer
- /// --------------------------------------------------- Level -30 m
- ///
- [Test]
- [TestCase(true, false)]
- [TestCase(false, true)]
- public void Given2DSoilProfileWithDiscontinuousInBetweenAquifer_WhenDeterminingInBetweenAquiferCount_ThenReturns0(
- bool isLeftInBetweenLayerAquifer, bool isRightInBetweenLayerAquifer)
- {
- // Setup
- SoilLayer2D soilLayer = CreateRectangularSoilLayer2D(0, -10, leftCoordinate, rightCoordinate, false);
- SoilLayer2D soilLayerAquiferInBetweenLeft = CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, isLeftInBetweenLayerAquifer);
- SoilLayer2D soilLayerAquiferInBetweenRight = CreateRectangularSoilLayer2D(-10, -20, middleXCoordinate, rightCoordinate, isRightInBetweenLayerAquifer);
- SoilLayer2D soilLayerInBetween = CreateRectangularSoilLayer2D(-20, -25, leftCoordinate, rightCoordinate, false);
- SoilLayer2D soilLayerAquiferBottom = CreateRectangularSoilLayer2D(-25, -30, leftCoordinate, rightCoordinate, true);
-
- var soilProfile = new SoilProfile2D
- {
- Geometry = new GeometryData
- {
- Left = leftCoordinate,
- Right = rightCoordinate,
- Bottom = -30
- }
- };
- soilProfile.Surfaces.Add(soilLayer);
- soilProfile.Surfaces.Add(soilLayerAquiferInBetweenLeft);
- soilProfile.Surfaces.Add(soilLayerAquiferInBetweenRight);
- soilProfile.Surfaces.Add(soilLayerInBetween);
- soilProfile.Surfaces.Add(soilLayerAquiferBottom);
-
- // Call
- bool isInBetweenLayerPresent = PlLinesToWaternetConverter.AreInBetweenAquiferClustersPresent(soilProfile, out int count);
-
- // Assert
- Assert.Multiple(() =>
- {
- Assert.That(isInBetweenLayerPresent, Is.False);
- Assert.That(count, Is.EqualTo(0));
- });
- }
-
- ///
- /// --------------------------------------------------- Level 0 m
- ///
/// |------------------------- Level -5 m
/// top layer | right aquifer
/// |------------------------- Level -9 m
@@ -1814,196 +1107,6 @@
return soilProfile1D;
}
- ///
- /// Many test cases are considered using a different soil profile 2D:
- /// Within the method below, pictures of these soil profiles 2D are drawn to get a better idea of the test.
- ///
- private static IEnumerable GetSoilProfilesWithContinuousBottomAquiferLayer()
- {
- // TEST CASE 1: "Right aquifer fully adjoins left aquifer"
- //
- // ------------------------------------------------------------- Level 0 m
- // Upper layer (not aquifer)
- // -----------------------------|------------------------------- Level -10 m
- // Bottom aquifer layer left | Bottom aquifer layer right
- // -----------------------------|------------------------------- Level -20 m
- SoilLayer2D soilUpperLayer = CreateRectangularSoilLayer2D(0, -10, leftCoordinate, rightCoordinate, false);
- SoilLayer2D soilBottomLayerAquiferPartLeft = CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, true);
- SoilLayer2D soilBottomLayerAquiferPartRight = CreateRectangularSoilLayer2D(-10, -20, middleXCoordinate, rightCoordinate, true);
- var soilProfileFullAdjoin = new SoilProfile2D
- {
- Geometry = new GeometryData
- {
- Left = leftCoordinate,
- Right = rightCoordinate,
- Bottom = -20
- }
- };
- soilProfileFullAdjoin.Surfaces.Add(soilUpperLayer);
- soilProfileFullAdjoin.Surfaces.Add(soilBottomLayerAquiferPartLeft);
- soilProfileFullAdjoin.Surfaces.Add(soilBottomLayerAquiferPartRight);
- soilProfileFullAdjoin.Geometry.Surfaces.Add(new GeometrySurface());
-
- yield return new TestCaseData(soilProfileFullAdjoin, new[]
- {
- new GeometryPoint(leftCoordinate, -10),
- new GeometryPoint(middleXCoordinate, -10),
- new GeometryPoint(rightCoordinate, -10)
- }).SetName("Right aquifer fully adjoins left aquifer");
-
- // TEST CASE 2: "One aquifer bottom layer"
- //
- // ------------------------------------------------------------- Level 0 m
- // Upper layer (not aquifer)
- // ------------------------------------------------------------- Level -10 m
- // Bottom aquifer layer
- // ------------------------------------------------------------- Level -20 m
- SoilLayer2D soilBottomLayerAquifer = CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, rightCoordinate, true);
- var soilProfileOneBottomAquiferLayer = new SoilProfile2D
- {
- Geometry = new GeometryData
- {
- Left = leftCoordinate,
- Right = rightCoordinate,
- Bottom = -20
- }
- };
- soilProfileOneBottomAquiferLayer.Surfaces.Add(soilUpperLayer);
- soilProfileOneBottomAquiferLayer.Surfaces.Add(soilBottomLayerAquifer);
- soilProfileOneBottomAquiferLayer.Geometry.Surfaces.Add(new GeometrySurface());
-
- yield return new TestCaseData(soilProfileOneBottomAquiferLayer, new[]
- {
- new GeometryPoint(leftCoordinate, -10),
- new GeometryPoint(rightCoordinate, -10)
- }).SetName("One aquifer bottom layer");
-
- // TEST CASE 3: "Right aquifer only bottom in range"
- //
- // ------------------------------------------------------------- Level 0 m
- // Upper layer (not aquifer) |------------------------------ Level -5 m
- // ------------------------------| Right bottom aquifer layer Level -10 m
- // Left bottom aquifer layer |------------------------------ Level -15 m
- // ------------------------------| Level -20 m
- soilBottomLayerAquiferPartRight = CreateRectangularSoilLayer2D(-5, -15, middleXCoordinate, rightCoordinate, true);
- var soilProfileRightSoilLayerBottomInRange = new SoilProfile2D
- {
- Geometry = new GeometryData
- {
- Left = leftCoordinate,
- Right = rightCoordinate,
- Bottom = -20
- }
- };
- soilProfileRightSoilLayerBottomInRange.Surfaces.Add(soilUpperLayer);
- soilProfileRightSoilLayerBottomInRange.Surfaces.Add(soilBottomLayerAquiferPartLeft);
- soilProfileRightSoilLayerBottomInRange.Surfaces.Add(soilBottomLayerAquiferPartRight);
- soilProfileRightSoilLayerBottomInRange.Geometry.Surfaces.Add(new GeometrySurface());
-
- yield return new TestCaseData(soilProfileRightSoilLayerBottomInRange, new[]
- {
- new GeometryPoint(leftCoordinate, -10),
- new GeometryPoint(middleXCoordinate, -10),
- new GeometryPoint(middleXCoordinate, -5),
- new GeometryPoint(rightCoordinate, -5)
- }).SetName("Right aquifer only bottom in range");
-
- // TEST CASE 4: "Right aquifer only top in range"
- //
- // ------------------------------------------------------------- Level 0 m
- // Upper layer (not aquifer) |
- // ------------------------------|------------------------------ Level -10 m
- // Left bottom aquifer layer |------------------------------ Level -15 m
- // ------------------------------| Right bottom aquifer layer | Level -20 m
- // |------------------------------ Level -25 m
- soilBottomLayerAquiferPartRight = CreateRectangularSoilLayer2D(-15, -25, middleXCoordinate, rightCoordinate, true);
-
- var soilProfileRightSoilLayerTopInRange = new SoilProfile2D
- {
- Geometry = new GeometryData
- {
- Left = leftCoordinate,
- Right = rightCoordinate,
- Bottom = -25
- }
- };
- soilProfileRightSoilLayerTopInRange.Surfaces.Add(soilUpperLayer);
- soilProfileRightSoilLayerTopInRange.Surfaces.Add(soilBottomLayerAquiferPartLeft);
- soilProfileRightSoilLayerTopInRange.Surfaces.Add(soilBottomLayerAquiferPartRight);
- soilProfileRightSoilLayerTopInRange.Geometry.Surfaces.Add(new GeometrySurface());
-
- yield return new TestCaseData(soilProfileRightSoilLayerTopInRange, new[]
- {
- new GeometryPoint(leftCoordinate, -10),
- new GeometryPoint(middleXCoordinate, -10),
- new GeometryPoint(middleXCoordinate, -15),
- new GeometryPoint(rightCoordinate, -15)
- }).SetName("Right aquifer only top in range");
-
- // TEST CASE 5: "Right aquifer fully envelopes left aquifer"
- //
- // ------------------------------------------------------------- Level 0 m
- // Upper layer (not aquifer) |------------------------------ Level -5 m
- // ------------------------------| Level -10 m
- // Left bottom aquifer layer | Right bottom aquifer layer Level -15 m
- // ------------------------------| Level -20 m
- // |------------------------------ Level -25 m
- soilBottomLayerAquiferPartRight = CreateRectangularSoilLayer2D(-5, -25, middleXCoordinate, rightCoordinate, true);
- var soilProfileRightAquiferLayerFullyEnvelopsLeft = new SoilProfile2D
- {
- Geometry = new GeometryData
- {
- Left = leftCoordinate,
- Right = rightCoordinate,
- Bottom = -25
- }
- };
- soilProfileRightAquiferLayerFullyEnvelopsLeft.Surfaces.Add(soilUpperLayer);
- soilProfileRightAquiferLayerFullyEnvelopsLeft.Surfaces.Add(soilBottomLayerAquiferPartLeft);
- soilProfileRightAquiferLayerFullyEnvelopsLeft.Surfaces.Add(soilBottomLayerAquiferPartRight);
- soilProfileRightAquiferLayerFullyEnvelopsLeft.Geometry.Surfaces.Add(new GeometrySurface());
-
- yield return new TestCaseData(soilProfileRightAquiferLayerFullyEnvelopsLeft, new[]
- {
- new GeometryPoint(leftCoordinate, -10),
- new GeometryPoint(middleXCoordinate, -10),
- new GeometryPoint(middleXCoordinate, -5),
- new GeometryPoint(rightCoordinate, -5)
- }).SetName("Right aquifer fully envelopes left aquifer");
-
- // TEST CASE 6: "Right aquifer fully enveloped by left aquifer"
- //
- // ------------------------------------------------------------- Level 0 m
- // Upper layer (not aquifer) |
- // ------------------------------|------------------------------ Level -10 m
- // Left bottom aquifer layer |------------------------------ Level -15 m
- // | Right bottom aquifer layer |
- // |------------------------------ Level -17 m
- // ------------------------------| Level -20 m
- soilBottomLayerAquiferPartRight = CreateRectangularSoilLayer2D(-15, -17, middleXCoordinate, rightCoordinate, true);
- var soilProfileRightAquiferLayerFullyEnvelopedByLeft = new SoilProfile2D
- {
- Geometry = new GeometryData
- {
- Left = leftCoordinate,
- Right = rightCoordinate,
- Bottom = -20
- }
- };
- soilProfileRightAquiferLayerFullyEnvelopedByLeft.Surfaces.Add(soilUpperLayer);
- soilProfileRightAquiferLayerFullyEnvelopedByLeft.Surfaces.Add(soilBottomLayerAquiferPartLeft);
- soilProfileRightAquiferLayerFullyEnvelopedByLeft.Surfaces.Add(soilBottomLayerAquiferPartRight);
- soilProfileRightAquiferLayerFullyEnvelopedByLeft.Geometry.Surfaces.Add(new GeometrySurface());
-
- yield return new TestCaseData(soilProfileRightAquiferLayerFullyEnvelopedByLeft, new[]
- {
- new GeometryPoint(leftCoordinate, -10),
- new GeometryPoint(middleXCoordinate, -10),
- new GeometryPoint(middleXCoordinate, -15),
- new GeometryPoint(rightCoordinate, -15)
- }).SetName("Right aquifer fully enveloped by left aquifer");
- }
-
private static SoilLayer2D CreateSoilLayer2D(Point2D topLeftCoordinate, Point2D topRightCoordinate,
Point2D bottomRightCoordinate, Point2D bottomLeftCoordinate, bool isAquifer)
{
Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/KernelWrappers/MacroStabilityCommon/PlLinesToWaternetConverter.cs
===================================================================
diff -u -r5329 -r5382
--- DamEngine/trunk/src/Deltares.DamEngine.Calculators/KernelWrappers/MacroStabilityCommon/PlLinesToWaternetConverter.cs (.../PlLinesToWaternetConverter.cs) (revision 5329)
+++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/KernelWrappers/MacroStabilityCommon/PlLinesToWaternetConverter.cs (.../PlLinesToWaternetConverter.cs) (revision 5382)
@@ -20,10 +20,10 @@
// All rights reserved.
using System;
-using System.Collections;
using System.Collections.Generic;
using System.Data;
using System.Linq;
+using Deltares.DamEngine.Calculators.KernelWrappers.Common;
using Deltares.DamEngine.Calculators.Properties;
using Deltares.DamEngine.Data.General;
using Deltares.DamEngine.Data.General.PlLines;
@@ -37,21 +37,6 @@
public static class PlLinesToWaternetConverter
{
- public enum LayerType
- {
- BottomAquiferCluster,
- InBetweenAquiferCluster,
- HighestAquiferCluster,
- LowestLayer
- }
-
- private enum BoundaryType
- {
- Top,
- Bottom
- }
-
- private const double deviationX = 1e-06;
private const double toleranceAlmostEqual = 1e-09;
private const string waternetLine1Name = "Waternet line phreatic line";
@@ -152,7 +137,7 @@
ThrowWhenPlLinesIsNull(plLines);
ThrowWhenSoilProfileIsNull(soilProfile);
- DetermineAquiferLayerBoundaryPoints(LayerType.BottomAquiferCluster, soilProfile, out Point2D[] bottomAquiferCoordinates, out _);
+ SoilProfile2DHelper.DetermineAquiferLayerBoundaryPoints(SoilProfile2DHelper.LayerType.BottomAquiferCluster, soilProfile, out Point2D[] bottomAquiferCoordinates, out _);
if (bottomAquiferCoordinates == null)
{
throw new NoNullAllowedException(string.Format(Resources.NoBottomAquiferLayer, soilProfile.Name));
@@ -208,19 +193,7 @@
waternetLine.SyncCalcPoints();
return waternetLine;
}
-
- ///
- /// Determine all the xCoordinates to make cross-sections.
- ///
- /// The soil profile 2D.
- /// All the xCoordinates of the soil profile 2D.
- private static double[] DetermineAllXCoordinatesOfSoilProfile(SoilProfile2D soilProfile)
- {
- IEnumerable points = soilProfile.Surfaces.SelectMany(surf => surf.GeometrySurface.OuterLoop.CalcPoints);
- double[] xCoordinates = points.Select(point => point.X).OrderBy(x => x).Distinct().ToArray();
- return xCoordinates;
- }
-
+
private static void CreateWaternetLinesForInBetweenAquifers(Waternet waternet, SoilProfile1D soilProfile1D, double xLeft, double xRight, PlLine plLine4, IntrusionVerticalWaterPressureType? pressureType)
{
var headLine = CreateLine(plLine4, headLine4Name);
@@ -266,7 +239,7 @@
return;
}
- if (!AreInBetweenAquiferClustersPresent(soilProfile, out int inBetweenAquiferCount))
+ if (!SoilProfile2DHelper.AreInBetweenAquiferClustersPresent(soilProfile, out int inBetweenAquiferCount))
{
return;
}
@@ -275,7 +248,7 @@
waternet.HeadLineList.Add(headLine);
for (var i = 0; i < inBetweenAquiferCount; i++)
{
- DetermineAquiferLayerBoundaryPoints(LayerType.InBetweenAquiferCluster, soilProfile, out Point2D[] inBetweenAquiferUpperCoordinates, out Point2D[] inBetweenAquiferLowerCoordinates, i);
+ SoilProfile2DHelper.DetermineAquiferLayerBoundaryPoints(SoilProfile2DHelper.LayerType.InBetweenAquiferCluster, soilProfile, out Point2D[] inBetweenAquiferUpperCoordinates, out Point2D[] inBetweenAquiferLowerCoordinates, i);
if (inBetweenAquiferUpperCoordinates.Any() && inBetweenAquiferLowerCoordinates.Any())
{
@@ -296,28 +269,6 @@
}
}
- internal static bool AreInBetweenAquiferClustersPresent(SoilProfile2D soilProfile, out int count)
- {
- double[] xCoordinates = DetermineAllXCoordinatesOfSoilProfile(soilProfile);
- var currentCount = 0;
- var previousCount = 0;
- for (var i = 0; i < xCoordinates.Length; i++)
- {
- SoilProfile1D crossSection = soilProfile.GetSoilProfile1D(xCoordinates[i]);
- currentCount = crossSection.GetInBetweenAquiferClusters?.Count ?? 0;
- if (i > 0 && currentCount != previousCount)
- {
- count = 0;
- return false;
- }
-
- previousCount = currentCount;
- }
-
- count = currentCount;
- return count > 0;
- }
-
private static TLineType CreateLine(PlLine plLine, string name)
where TLineType : GeometryPointString, new()
{
@@ -349,118 +300,7 @@
return line;
}
-
- ///
- /// Determines all the points of the layer boundary for the specified layer type:
- /// - For LayerType = BottomAquiferCluster, layerBoundaryTop is the top boundary of the bottom aquifer (= waternet line for PL3)
- /// - For LayerType = InBetweenAquiferCluster, layerBoundaryTop and layerBoundaryBottom are both boundaries of the in-between aquifer (= waternet line for PL4)
- /// - For LayerType = HighestAquiferCluster, layerBoundaryTop is the top of the highest aquifer (= waternet line for PL1 for "Hydrostatic" waternet)
- /// - For LayerType = LowestLayer, layerBoundaryBottom is the bottom boundary of the lowest layer (= waternet line for PL1 for "Full hydrostatic" waternet)
- /// When the aquifer is not continuous, null top and bottom boundaries are returned.
- ///
- /// The type of layer boundary.
- /// The soil profile 2D.
- /// All the points of the layer top boundary.
- /// All the points of the layer bottom boundary.
- /// In case of several in-between aquifers, the index of the in-between aquifer must be specified.
- /// All the points of the layer boundary.
- internal static void DetermineAquiferLayerBoundaryPoints(LayerType layerType, SoilProfile2D soilProfile, out Point2D[] layerBoundaryTop, out Point2D[] layerBoundaryBottom, int indexInBetweenAquifer = -1)
- {
- double[] xCoordinates = DetermineAllXCoordinatesOfSoilProfile(soilProfile);
- var xCoordinatesAll = new List();
- foreach (double xCoordinate in xCoordinates)
- {
- if (HasAquiferAVerticalPartAtGivenX(layerType, xCoordinate, soilProfile, indexInBetweenAquifer))
- {
- xCoordinatesAll.Add(xCoordinate - deviationX);
- xCoordinatesAll.Add(xCoordinate + deviationX);
- }
- else
- {
- xCoordinatesAll.Add(xCoordinate);
- }
- }
-
- var layerBoundaryTopPoints = new List();
- var layerBoundaryBottomPoints = new List();
- double previousAquiferTop = double.NaN;
- double previousAquiferBottom = double.NaN;
- foreach (double xCoordinate in xCoordinatesAll)
- {
- SoilProfile1D crossSection = soilProfile.GetSoilProfile1D(xCoordinate);
-
- // Determine if the cluster of layers is in range of the previous cluster of layers.
- // If not, return empty coordinates, because the cluster of layers is interrupted.
- double currentAquiferTop = GetLevel(layerType, BoundaryType.Top, crossSection, indexInBetweenAquifer);
- double currentAquiferBottom = GetLevel(layerType, BoundaryType.Bottom, crossSection, indexInBetweenAquifer);
-
- if (!double.IsNaN(previousAquiferTop) && !double.IsNaN(previousAquiferBottom)
- && !double.IsNaN(currentAquiferTop)
- && !double.IsNaN(currentAquiferBottom)
- && !AreHorizontallyConnected(previousAquiferTop, previousAquiferBottom, currentAquiferTop, currentAquiferBottom))
- {
- layerBoundaryTop = null;
- layerBoundaryBottom = null;
- return;
- }
-
- if (!double.IsNaN(currentAquiferTop) && !double.IsNaN(currentAquiferBottom))
- {
- previousAquiferTop = currentAquiferTop;
- previousAquiferBottom = currentAquiferBottom;
- layerBoundaryTopPoints.Add(new Point2D(xCoordinate, currentAquiferTop));
- layerBoundaryBottomPoints.Add(new Point2D(xCoordinate, currentAquiferBottom));
- }
- }
-
- // Perform a short validation that the coordinates are fully defined from the beginning to the end
- // of the profile. If not, the layer is not continuous.
- if (!IsLayerBoundaryContinuous(layerBoundaryTopPoints, xCoordinates.First(), xCoordinates.Last())
- || !IsLayerBoundaryContinuous(layerBoundaryBottomPoints, xCoordinates.First(), xCoordinates.Last()))
- {
- layerBoundaryTop = null;
- layerBoundaryBottom = null;
- return;
- }
- layerBoundaryTop = layerBoundaryTopPoints.ToArray();
- layerBoundaryBottom = layerBoundaryBottomPoints.ToArray();
- }
-
- private static bool IsLayerBoundaryContinuous(IEnumerable boundaryPoints, double leftGeometryBoundary, double rightGeometryBoundary)
- {
- IEnumerable point2Ds = boundaryPoints.ToList();
- return point2Ds.Any() && (Math.Abs(point2Ds.First().X - leftGeometryBoundary) < toleranceAlmostEqual)
- && Math.Abs(point2Ds.Last().X - rightGeometryBoundary) < toleranceAlmostEqual;
- }
-
- private static double GetLevel(LayerType layerType, BoundaryType boundaryType, SoilProfile1D soilProfile1D, int indexInBetweenAquifer)
- {
- SoilLayer1D layer = GetLayer(layerType, boundaryType, soilProfile1D, indexInBetweenAquifer);
- if (layer != null)
- {
- return boundaryType == BoundaryType.Top ? layer.TopLevel : layer.BottomLevel;
- }
-
- return double.NaN;
- }
- private static SoilLayer1D GetLayer(LayerType layerType, BoundaryType boundaryType, SoilProfile1D soilProfile1D, int indexInBetweenAquifer)
- {
- switch (layerType)
- {
- case LayerType.BottomAquiferCluster:
- return boundaryType == BoundaryType.Top ? soilProfile1D.BottomAquiferLayer : soilProfile1D.DeepestAquiferLayer;
- case LayerType.InBetweenAquiferCluster:
- return boundaryType == BoundaryType.Top ? soilProfile1D.GetInBetweenAquiferClusters[indexInBetweenAquifer].Item1 : soilProfile1D.GetInBetweenAquiferClusters[indexInBetweenAquifer].Item2;
- case LayerType.HighestAquiferCluster:
- return boundaryType == BoundaryType.Top ? soilProfile1D.GetHighestAquifer() : soilProfile1D.GetLowestLayerOfHighestAquiferCluster();
- case LayerType.LowestLayer:
- return soilProfile1D.Layers.Last();
- }
-
- return null;
- }
-
///
/// The position of the waternet line associated to the phreatic line depends on the water pressure type:
/// - For DAM Standard type, this line lies on the bottom of the soil layers “in which the phreatic plane lies”.
@@ -540,7 +380,7 @@
}
case IntrusionVerticalWaterPressureType.HydroStatic:
{
- DetermineAquiferLayerBoundaryPoints(LayerType.HighestAquiferCluster, soilProfile2D, out Point2D[] highestAquiferCoordinates, out _);
+ SoilProfile2DHelper.DetermineAquiferLayerBoundaryPoints(SoilProfile2DHelper.LayerType.HighestAquiferCluster, soilProfile2D, out Point2D[] highestAquiferCoordinates, out _);
return CreateWaternetLine(highestAquiferCoordinates);
}
case IntrusionVerticalWaterPressureType.Linear:
@@ -550,7 +390,7 @@
}
case IntrusionVerticalWaterPressureType.FullHydroStatic:
{
- DetermineAquiferLayerBoundaryPoints(LayerType.LowestLayer, soilProfile2D, out _, out Point2D[] lowestBoundaryCoordinates);
+ SoilProfile2DHelper.DetermineAquiferLayerBoundaryPoints(SoilProfile2DHelper.LayerType.LowestLayer, soilProfile2D, out _, out Point2D[] lowestBoundaryCoordinates);
return CreateWaternetLine(lowestBoundaryCoordinates);
}
case null:
@@ -637,46 +477,7 @@
return waternetLine;
}
-
- private static bool HasAquiferAVerticalPartAtGivenX(LayerType layerType, double xCoordinate, SoilProfile2D soilProfile, int indexInBetweenAquifer)
- {
- SoilProfile1D crossSectionLeft = soilProfile.GetSoilProfile1D(xCoordinate - deviationX);
- SoilProfile1D crossSectionRight = soilProfile.GetSoilProfile1D(xCoordinate + deviationX);
- if (crossSectionLeft == null || crossSectionRight == null)
- {
- return false;
- }
-
- double aquiferLeftTop = GetLevel(layerType, BoundaryType.Top, crossSectionLeft, indexInBetweenAquifer);
- double aquiferLefBottom = GetLevel(layerType, BoundaryType.Bottom, crossSectionLeft, indexInBetweenAquifer);
- double aquiferRightTop = GetLevel(layerType, BoundaryType.Top, crossSectionRight, indexInBetweenAquifer);
- double aquiferRightBottom = GetLevel(layerType, BoundaryType.Bottom, crossSectionRight, indexInBetweenAquifer);
- if (!double.IsNaN(aquiferLeftTop) && !double.IsNaN(aquiferLefBottom) && !double.IsNaN(aquiferRightTop) && !double.IsNaN(aquiferRightBottom))
- {
- return Math.Abs(aquiferLeftTop - aquiferRightTop) > GeometryConstants.Accuracy || Math.Abs(aquiferLefBottom - aquiferRightBottom) > GeometryConstants.Accuracy;
- }
-
- return false;
- }
-
- private static bool AreHorizontallyConnected(double leftLayerTop, double leftLayerBottom, double rightLayerTop, double rightLayerBottom)
- {
- // Left soil layer envelopes whole right soil layer
- if (leftLayerBottom <= rightLayerBottom && leftLayerTop >= rightLayerTop)
- {
- return true;
- }
-
- // Right soil layer envelopes whole left soil layer
- if (rightLayerBottom <= leftLayerBottom && rightLayerTop >= leftLayerTop)
- {
- return true;
- }
-
- return (rightLayerTop <= leftLayerTop && rightLayerTop >= leftLayerBottom) // Top level lies in-between the left soil layer
- || (rightLayerBottom >= leftLayerBottom && rightLayerBottom <= leftLayerTop); // Bottom level lies in-between the left soil layer
- }
-
+
private static bool IsBelowSoilProfile(SoilProfile1D soilProfile, PlLine line)
{
double bottomSoilProfileLevel = soilProfile.BottomLevel;
Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/KernelWrappers/Common/SoilProfile2DHelper.cs
===================================================================
diff -u
--- DamEngine/trunk/src/Deltares.DamEngine.Calculators/KernelWrappers/Common/SoilProfile2DHelper.cs (revision 0)
+++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/KernelWrappers/Common/SoilProfile2DHelper.cs (revision 5382)
@@ -0,0 +1,232 @@
+// 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;
+using System.Collections.Generic;
+using System.Linq;
+using Deltares.DamEngine.Data.Geometry;
+using Deltares.DamEngine.Data.Geotechnics;
+
+namespace Deltares.DamEngine.Calculators.KernelWrappers.Common;
+
+public static class SoilProfile2DHelper
+{
+ public enum LayerType
+ {
+ BottomAquiferCluster,
+ InBetweenAquiferCluster,
+ HighestAquiferCluster,
+ LowestLayer
+ }
+
+ private enum BoundaryType
+ {
+ Top,
+ Bottom
+ }
+
+ private const double deviationX = 1e-06;
+ private const double toleranceAlmostEqual = 1e-09;
+
+ ///
+ /// Determine all the xCoordinates to make cross-sections.
+ ///
+ /// The soil profile 2D.
+ /// All the xCoordinates of the soil profile 2D.
+ private static double[] DetermineAllXCoordinatesOfSoilProfile(SoilProfile2D soilProfile)
+ {
+ IEnumerable points = soilProfile.Surfaces.SelectMany(surf => surf.GeometrySurface.OuterLoop.CalcPoints);
+ double[] xCoordinates = points.Select(point => point.X).OrderBy(x => x).Distinct().ToArray();
+ return xCoordinates;
+ }
+
+ internal static bool AreInBetweenAquiferClustersPresent(SoilProfile2D soilProfile, out int count)
+ {
+ double[] xCoordinates = DetermineAllXCoordinatesOfSoilProfile(soilProfile);
+ var currentCount = 0;
+ var previousCount = 0;
+ for (var i = 0; i < xCoordinates.Length; i++)
+ {
+ SoilProfile1D crossSection = soilProfile.GetSoilProfile1D(xCoordinates[i]);
+ currentCount = crossSection.GetInBetweenAquiferClusters?.Count ?? 0;
+ if (i > 0 && currentCount != previousCount)
+ {
+ count = 0;
+ return false;
+ }
+
+ previousCount = currentCount;
+ }
+
+ count = currentCount;
+ return count > 0;
+ }
+
+ ///
+ /// Determines all the points of the layer boundary for the specified layer type:
+ /// - For LayerType = BottomAquiferCluster, layerBoundaryTop is the top boundary of the bottom aquifer (= waternet line for PL3)
+ /// - For LayerType = InBetweenAquiferCluster, layerBoundaryTop and layerBoundaryBottom are both boundaries of the in-between aquifer (= waternet line for PL4)
+ /// - For LayerType = HighestAquiferCluster, layerBoundaryTop is the top of the highest aquifer (= waternet line for PL1 for "Hydrostatic" waternet)
+ /// - For LayerType = LowestLayer, layerBoundaryBottom is the bottom boundary of the lowest layer (= waternet line for PL1 for "Full hydrostatic" waternet)
+ /// When the aquifer is not continuous, null top and bottom boundaries are returned.
+ ///
+ /// The type of layer boundary.
+ /// The soil profile 2D.
+ /// All the points of the layer top boundary.
+ /// All the points of the layer bottom boundary.
+ /// In case of several in-between aquifers, the index of the in-between aquifer must be specified.
+ /// All the points of the layer boundary.
+ internal static void DetermineAquiferLayerBoundaryPoints(LayerType layerType, SoilProfile2D soilProfile, out Point2D[] layerBoundaryTop, out Point2D[] layerBoundaryBottom, int indexInBetweenAquifer = -1)
+ {
+ double[] xCoordinates = DetermineAllXCoordinatesOfSoilProfile(soilProfile);
+ var xCoordinatesAll = new List();
+ foreach (double xCoordinate in xCoordinates)
+ {
+ if (HasAquiferAVerticalPartAtGivenX(layerType, xCoordinate, soilProfile, indexInBetweenAquifer))
+ {
+ xCoordinatesAll.Add(xCoordinate - deviationX);
+ xCoordinatesAll.Add(xCoordinate + deviationX);
+ }
+ else
+ {
+ xCoordinatesAll.Add(xCoordinate);
+ }
+ }
+
+ var layerBoundaryTopPoints = new List();
+ var layerBoundaryBottomPoints = new List();
+ double previousAquiferTop = double.NaN;
+ double previousAquiferBottom = double.NaN;
+ foreach (double xCoordinate in xCoordinatesAll)
+ {
+ SoilProfile1D crossSection = soilProfile.GetSoilProfile1D(xCoordinate);
+
+ // Determine if the cluster of layers is in range of the previous cluster of layers.
+ // If not, return empty coordinates, because the cluster of layers is interrupted.
+ double currentAquiferTop = GetLevel(layerType, BoundaryType.Top, crossSection, indexInBetweenAquifer);
+ double currentAquiferBottom = GetLevel(layerType, BoundaryType.Bottom, crossSection, indexInBetweenAquifer);
+
+ if (!double.IsNaN(previousAquiferTop) && !double.IsNaN(previousAquiferBottom)
+ && !double.IsNaN(currentAquiferTop)
+ && !double.IsNaN(currentAquiferBottom)
+ && !AreHorizontallyConnected(previousAquiferTop, previousAquiferBottom, currentAquiferTop, currentAquiferBottom))
+ {
+ layerBoundaryTop = null;
+ layerBoundaryBottom = null;
+ return;
+ }
+
+ if (!double.IsNaN(currentAquiferTop) && !double.IsNaN(currentAquiferBottom))
+ {
+ previousAquiferTop = currentAquiferTop;
+ previousAquiferBottom = currentAquiferBottom;
+ layerBoundaryTopPoints.Add(new Point2D(xCoordinate, currentAquiferTop));
+ layerBoundaryBottomPoints.Add(new Point2D(xCoordinate, currentAquiferBottom));
+ }
+ }
+
+ // Perform a short validation that the coordinates are fully defined from the beginning to the end
+ // of the profile. If not, the layer is not continuous.
+ if (!IsLayerBoundaryContinuous(layerBoundaryTopPoints, xCoordinates.First(), xCoordinates.Last())
+ || !IsLayerBoundaryContinuous(layerBoundaryBottomPoints, xCoordinates.First(), xCoordinates.Last()))
+ {
+ layerBoundaryTop = null;
+ layerBoundaryBottom = null;
+ return;
+ }
+ layerBoundaryTop = layerBoundaryTopPoints.ToArray();
+ layerBoundaryBottom = layerBoundaryBottomPoints.ToArray();
+ }
+
+ private static bool IsLayerBoundaryContinuous(IEnumerable boundaryPoints, double leftGeometryBoundary, double rightGeometryBoundary)
+ {
+ IEnumerable point2Ds = boundaryPoints.ToList();
+ return point2Ds.Any() && (Math.Abs(point2Ds.First().X - leftGeometryBoundary) < toleranceAlmostEqual)
+ && Math.Abs(point2Ds.Last().X - rightGeometryBoundary) < toleranceAlmostEqual;
+ }
+
+ private static double GetLevel(LayerType layerType, BoundaryType boundaryType, SoilProfile1D soilProfile1D, int indexInBetweenAquifer)
+ {
+ SoilLayer1D layer = GetLayer(layerType, boundaryType, soilProfile1D, indexInBetweenAquifer);
+ if (layer != null)
+ {
+ return boundaryType == BoundaryType.Top ? layer.TopLevel : layer.BottomLevel;
+ }
+
+ return double.NaN;
+ }
+
+ private static SoilLayer1D GetLayer(LayerType layerType, BoundaryType boundaryType, SoilProfile1D soilProfile1D, int indexInBetweenAquifer)
+ {
+ switch (layerType)
+ {
+ case LayerType.BottomAquiferCluster:
+ return boundaryType == BoundaryType.Top ? soilProfile1D.BottomAquiferLayer : soilProfile1D.DeepestAquiferLayer;
+ case LayerType.InBetweenAquiferCluster:
+ return boundaryType == BoundaryType.Top ? soilProfile1D.GetInBetweenAquiferClusters[indexInBetweenAquifer].Item1 : soilProfile1D.GetInBetweenAquiferClusters[indexInBetweenAquifer].Item2;
+ case LayerType.HighestAquiferCluster:
+ return boundaryType == BoundaryType.Top ? soilProfile1D.GetHighestAquifer() : soilProfile1D.GetLowestLayerOfHighestAquiferCluster();
+ case LayerType.LowestLayer:
+ return soilProfile1D.Layers.Last();
+ }
+
+ return null;
+ }
+
+ private static bool HasAquiferAVerticalPartAtGivenX(LayerType layerType, double xCoordinate, SoilProfile2D soilProfile, int indexInBetweenAquifer)
+ {
+ SoilProfile1D crossSectionLeft = soilProfile.GetSoilProfile1D(xCoordinate - deviationX);
+ SoilProfile1D crossSectionRight = soilProfile.GetSoilProfile1D(xCoordinate + deviationX);
+ if (crossSectionLeft == null || crossSectionRight == null)
+ {
+ return false;
+ }
+
+ double aquiferLeftTop = GetLevel(layerType, BoundaryType.Top, crossSectionLeft, indexInBetweenAquifer);
+ double aquiferLefBottom = GetLevel(layerType, BoundaryType.Bottom, crossSectionLeft, indexInBetweenAquifer);
+ double aquiferRightTop = GetLevel(layerType, BoundaryType.Top, crossSectionRight, indexInBetweenAquifer);
+ double aquiferRightBottom = GetLevel(layerType, BoundaryType.Bottom, crossSectionRight, indexInBetweenAquifer);
+ if (!double.IsNaN(aquiferLeftTop) && !double.IsNaN(aquiferLefBottom) && !double.IsNaN(aquiferRightTop) && !double.IsNaN(aquiferRightBottom))
+ {
+ return Math.Abs(aquiferLeftTop - aquiferRightTop) > GeometryConstants.Accuracy || Math.Abs(aquiferLefBottom - aquiferRightBottom) > GeometryConstants.Accuracy;
+ }
+
+ return false;
+ }
+
+ private static bool AreHorizontallyConnected(double leftLayerTop, double leftLayerBottom, double rightLayerTop, double rightLayerBottom)
+ {
+ // Left soil layer envelopes whole right soil layer
+ if (leftLayerBottom <= rightLayerBottom && leftLayerTop >= rightLayerTop)
+ {
+ return true;
+ }
+
+ // Right soil layer envelopes whole left soil layer
+ if (rightLayerBottom <= leftLayerBottom && rightLayerTop >= leftLayerTop)
+ {
+ return true;
+ }
+
+ return (rightLayerTop <= leftLayerTop && rightLayerTop >= leftLayerBottom) // Top level lies in-between the left soil layer
+ || (rightLayerBottom >= leftLayerBottom && rightLayerBottom <= leftLayerTop); // Bottom level lies in-between the left soil layer
+ }
+}
\ No newline at end of file