// 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.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 const double leftCoordinate = -50; private const double rightCoordinate = 50; private const 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 aquitard /// --------------------------------------------------------------- Level -10 m /// in-between aquifer layer left | in-between aquifer layer right /// --------------------------------------------------------------- Level -20 m /// in-between aquifer layer /// --------------------------------------------------------------- Level -22 m /// in-between aquitard /// --------------------------------------------------------------- Level -25 m /// bottom aquifer layer /// --------------------------------------------------------------- Level -30 m /// [Test] public void Given2DSoilProfileWithContinuousInBetweenAquiferClusterConsistingOfThreeParts_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 soilLayerInBetweenAquifer = CreateRectangularSoilLayer2D(-20, -22, leftCoordinate, rightCoordinate, true); SoilLayer2D soilLayerInBetweenAquitard = CreateRectangularSoilLayer2D(-22, -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(soilLayerInBetweenAquifer); soilProfile.Surfaces.Add(soilLayerInBetweenAquitard); soilProfile.Surfaces.Add(soilLayerAquiferBottom); soilProfile.Geometry.Surfaces.Add(soilLayer.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerAquiferInBetweenLeft.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerAquiferInBetweenRight.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerInBetweenAquifer.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerInBetweenAquitard.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerAquiferBottom.GeometrySurface); // Call SoilProfile2DHelper.DetermineInBetweenAquifersLayerBoundaryPoints(soilProfile, out List topLevelInBetweenAquifer, out List bottomLevelInBetweenAquifer); // Assert Assert.Multiple(() => { Assert.That(topLevelInBetweenAquifer, Has.Count.EqualTo(1)); Assert.That(bottomLevelInBetweenAquifer, Has.Count.EqualTo(1)); }); GeometryPoint[] expectedTop = [ new(leftCoordinate, -10), new(middleXCoordinate, -10), new(rightCoordinate, -10) ]; GeometryPoint[] expectedBottom = [ new(leftCoordinate, -22), new(rightCoordinate, -22) ]; AssertGeometry(topLevelInBetweenAquifer[0].Points, expectedTop); AssertGeometry(bottomLevelInBetweenAquifer[0].Points, 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(soilLayer.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerAquiferInBetween.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerInBetween.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerAquiferBottom.GeometrySurface); // Call SoilProfile2DHelper.DetermineInBetweenAquifersLayerBoundaryPoints(soilProfile, out List topLevelInBetweenAquifer, out List bottomLevelInBetweenAquifer); // Assert Assert.Multiple(() => { Assert.That(topLevelInBetweenAquifer, Has.Count.EqualTo(1)); Assert.That(bottomLevelInBetweenAquifer, Has.Count.EqualTo(1)); }); GeometryPoint[] expectedTop = [ new(leftCoordinate, -10), new(rightCoordinate, -10) ]; GeometryPoint[] expectedBottom = [ new(leftCoordinate, -20), new(rightCoordinate, -20) ]; AssertGeometry(topLevelInBetweenAquifer[0].Points, expectedTop); AssertGeometry(bottomLevelInBetweenAquifer[0].Points, 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(soilLayer.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerAquiferInBetweenLeft.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerGap.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerAquiferInBetweenRight.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerInBetween.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerAquiferBottom.GeometrySurface); // Call SoilProfile2DHelper.DetermineInBetweenAquifersLayerBoundaryPoints(soilProfile, out List topLevelInBetweenAquifer, out List bottomLevelInBetweenAquifer); // Assert Assert.Multiple(() => { Assert.That(topLevelInBetweenAquifer, Has.Count.EqualTo(2)); Assert.That(bottomLevelInBetweenAquifer, Has.Count.EqualTo(2)); }); GeometryPoint[] expectedTop1 = [ new(leftCoordinate, -10), new(middleXCoordinate, -10) ]; GeometryPoint[] expectedTop2 = [ new(middleXCoordinate, -15), new(rightCoordinate, -15) ]; GeometryPoint[] expectedBottom1 = [ new(leftCoordinate, -20), new(middleXCoordinate, -20) ]; GeometryPoint[] expectedBottom2 = [ new(middleXCoordinate, -21), new(rightCoordinate, -21) ]; AssertGeometry(topLevelInBetweenAquifer[0].Points, expectedTop1); AssertGeometry(topLevelInBetweenAquifer[1].Points, expectedTop2); AssertGeometry(bottomLevelInBetweenAquifer[0].Points, expectedBottom1); AssertGeometry(bottomLevelInBetweenAquifer[1].Points, expectedBottom2); } /// /// -------------------------------------------------------------- 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(soilLayer.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerAquiferInBetweenLeft.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerAquiferInBetweenRight.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerInBetween.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerAquiferBottom.GeometrySurface); // Call SoilProfile2DHelper.DetermineInBetweenAquifersLayerBoundaryPoints(soilProfile, out List topLevelInBetweenAquifer, out List bottomLevelInBetweenAquifer); // Assert Assert.Multiple(() => { Assert.That(topLevelInBetweenAquifer, Has.Count.EqualTo(2)); Assert.That(bottomLevelInBetweenAquifer, Has.Count.EqualTo(1)); }); GeometryPoint[] expectedTop1 = [ new(leftCoordinate, -10), new(middleXCoordinate, -10) ]; GeometryPoint[] expectedTop2 = [ new(middleXCoordinate, -5), new(rightCoordinate, -5) ]; GeometryPoint[] expectedBottom = [ new(leftCoordinate, -20), new(middleXCoordinate, -20), new(rightCoordinate, -20) ]; AssertGeometry(topLevelInBetweenAquifer[0].Points, expectedTop1); AssertGeometry(topLevelInBetweenAquifer[1].Points, expectedTop2); AssertGeometry(bottomLevelInBetweenAquifer[0].Points, 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(soilLayer.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerAquiferInBetweenLeft.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerAquiferInBetweenRight.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerInBetween.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerAquiferBottom.GeometrySurface); // Call SoilProfile2DHelper.DetermineInBetweenAquifersLayerBoundaryPoints(soilProfile, out List topLevelInBetweenAquifer, out List bottomLevelInBetweenAquifer); // Assert Assert.Multiple(() => { Assert.That(topLevelInBetweenAquifer, Has.Count.EqualTo(2)); Assert.That(bottomLevelInBetweenAquifer, Has.Count.EqualTo(2)); }); GeometryPoint[] expectedTop1 = [ new(leftCoordinate, -10), new(middleXCoordinate, -10) ]; GeometryPoint[] expectedTop2 = [ new(middleXCoordinate, -15), new(rightCoordinate, -15) ]; GeometryPoint[] expectedBottom1 = [ new(leftCoordinate, -20), new(middleXCoordinate, -20) ]; GeometryPoint[] expectedBottom2 = [ new(middleXCoordinate, -17), new(rightCoordinate, -17) ]; AssertGeometry(topLevelInBetweenAquifer[0].Points, expectedTop1); AssertGeometry(topLevelInBetweenAquifer[1].Points, expectedTop2); AssertGeometry(bottomLevelInBetweenAquifer[0].Points, expectedBottom1); AssertGeometry(bottomLevelInBetweenAquifer[1].Points, expectedBottom2); } /// /// ------------------------------------------------------------- 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(soilLayer.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerAquiferInBetweenLeft.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerAquiferInBetweenRight.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerInBetween.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerAquiferBottom.GeometrySurface); // Call SoilProfile2DHelper.DetermineInBetweenAquifersLayerBoundaryPoints(soilProfile, out List topLevelInBetweenAquifer, out List bottomLevelInBetweenAquifer); // Assert Assert.Multiple(() => { Assert.That(topLevelInBetweenAquifer, Has.Count.EqualTo(2)); Assert.That(bottomLevelInBetweenAquifer, Has.Count.EqualTo(2)); }); GeometryPoint[] expectedTop1 = [ new(leftCoordinate, -10), new(middleXCoordinate, -10) ]; GeometryPoint[] expectedTop2 = [ new(middleXCoordinate, -5), new(rightCoordinate, -5) ]; GeometryPoint[] expectedBottom1 = [ new(leftCoordinate, -20), new(middleXCoordinate, -20) ]; GeometryPoint[] expectedBottom2 = [ new(middleXCoordinate, -21), new(rightCoordinate, -21) ]; AssertGeometry(topLevelInBetweenAquifer[0].Points, expectedTop1); AssertGeometry(topLevelInBetweenAquifer[1].Points, expectedTop2); AssertGeometry(bottomLevelInBetweenAquifer[0].Points, expectedBottom1); AssertGeometry(bottomLevelInBetweenAquifer[1].Points, expectedBottom2); } /// /// ----------------------------------------------\ E Level 0 m /// D /-------------------\ F Level -2 m /// Top aquitard / /------------------\ G Level -4 m /// B / / C | /// ---------------------/ / | Level -10 m /// in-between aquifer / Aquitard | /// ---------------------/ A | Level -13 m /// ------------------------------------------------| Level -15 m /// bottom aquifer | /// ------------------------------------------------| Level -20 m /// [Test] public void Given2DSoilProfileNotVerticalAtRightBoundaryAndWithInBetweenAquiferWithJump_WhenDeterminingLayerBoundaryPointsOfInBetweenAquifer_ThenExpectedCoordinatesReturned() { var pointA = new Point2D(middleXCoordinate - 10, -13); var pointB = new Point2D(middleXCoordinate - 10, -10); var pointC = new Point2D(middleXCoordinate + 10, -4); var pointD = new Point2D(middleXCoordinate + 10, -2); var pointE = new Point2D(rightCoordinate - 2, 0); var pointF = new Point2D(rightCoordinate - 1, -2); var pointG = new Point2D(rightCoordinate, -4); // Setup SoilLayer2D soilLayerTop = FactoryForSoilProfiles.CreateHexagonSoilLayer2D(new Point2D(leftCoordinate, 0), pointE, pointF, pointD, pointB, new Point2D(leftCoordinate, -10)); SoilLayer2D soilLayerInBetweenAquifer = FactoryForSoilProfiles.CreatePolygoneSoilLayer2D([ ..new[] { new Point2D(leftCoordinate, -10), pointB, pointD, pointF, pointG, pointC, pointA, new Point2D(leftCoordinate, -13) } ], null, true); SoilLayer2D soilLayerAquitard = FactoryForSoilProfiles.CreateHexagonSoilLayer2D(new Point2D(leftCoordinate, -13), pointA, pointC, pointG, new Point2D(rightCoordinate, -15), new Point2D(leftCoordinate, -15)); SoilLayer2D soilLayerAquiferBottom = CreateRectangularSoilLayer2D(-15, -20, leftCoordinate, rightCoordinate, true); var soilProfile = new SoilProfile2D { Geometry = new GeometryData { Left = leftCoordinate, Right = rightCoordinate, Bottom = -20 } }; soilProfile.Surfaces.Add(soilLayerTop); soilProfile.Surfaces.Add(soilLayerInBetweenAquifer); soilProfile.Surfaces.Add(soilLayerAquitard); soilProfile.Surfaces.Add(soilLayerAquiferBottom); soilProfile.Geometry.Surfaces.Add(soilLayerTop.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerInBetweenAquifer.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerAquitard.GeometrySurface); soilProfile.Geometry.Surfaces.Add(soilLayerAquiferBottom.GeometrySurface); // Call SoilProfile2DHelper.DetermineInBetweenAquifersLayerBoundaryPoints(soilProfile, out List topLevelInBetweenAquifer, out List bottomLevelInBetweenAquifer); // Assert Assert.Multiple(() => { Assert.That(topLevelInBetweenAquifer, Has.Count.EqualTo(1)); Assert.That(bottomLevelInBetweenAquifer, Has.Count.EqualTo(1)); }); GeometryPoint[] expectedTop = [ new(leftCoordinate, -10), new(pointB.X, pointB.Z), new(pointD.X, pointD.Z), new(pointF.X, pointF.Z), new(pointG.X, pointG.Z) ]; GeometryPoint[] expectedBottom = [ new(leftCoordinate, -13), new(pointA.X, pointA.Z), new(pointC.X, pointC.Z), new(pointG.X, pointG.Z) ]; AssertGeometry(topLevelInBetweenAquifer[0].Points, expectedTop); AssertGeometry(bottomLevelInBetweenAquifer[0].Points, expectedBottom); } /// /// 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"); } [Test] public void GivenAListOfPolyLines_WhenConnectingThem_ThenExpectedConnectedPolyLinesReturned() { // Setup var polyLine1 = new GeometryPointString(); polyLine1.CalcPoints.Add(new Point2D(-1, 2)); polyLine1.CalcPoints.Add(new Point2D(3, 4)); polyLine1.CalcPoints.Add(new Point2D(5, 6)); var polyLine2 = new GeometryPointString(); polyLine2.CalcPoints.Add(new Point2D(5, 6)); polyLine2.CalcPoints.Add(new Point2D(9, 1)); polyLine2.CalcPoints.Add(new Point2D(15, 26)); var polyLine3 = new GeometryPointString(); polyLine3.CalcPoints.Add(new Point2D(3, 4)); polyLine3.CalcPoints.Add(new Point2D(9, 5)); polyLine3.CalcPoints.Add(new Point2D(6, 8)); var polyLines = new List { polyLine1, polyLine2, polyLine3 }; // Call List connectedPolyLines = SoilProfile2DHelper.ConnectPolyLines(polyLines); // Assert - Expected is that poly-lines 1 and 2 are connected but poly-line 3 not Assert.Multiple(() => { Assert.That(connectedPolyLines, Has.Count.EqualTo(2)); Assert.That(connectedPolyLines[0].CalcPoints, Has.Count.EqualTo(5)); Assert.That(connectedPolyLines[1].CalcPoints, Has.Count.EqualTo(3)); Assert.That(connectedPolyLines[0].CalcPoints[0].X, Is.EqualTo(-1)); Assert.That(connectedPolyLines[0].CalcPoints[0].Z, Is.EqualTo(2)); Assert.That(connectedPolyLines[0].CalcPoints[1].X, Is.EqualTo(3)); Assert.That(connectedPolyLines[0].CalcPoints[1].Z, Is.EqualTo(4)); Assert.That(connectedPolyLines[0].CalcPoints[2].X, Is.EqualTo(5)); Assert.That(connectedPolyLines[0].CalcPoints[2].Z, Is.EqualTo(6)); Assert.That(connectedPolyLines[0].CalcPoints[3].X, Is.EqualTo(9)); Assert.That(connectedPolyLines[0].CalcPoints[3].Z, Is.EqualTo(1)); Assert.That(connectedPolyLines[0].CalcPoints[4].X, Is.EqualTo(15)); Assert.That(connectedPolyLines[0].CalcPoints[4].Z, Is.EqualTo(26)); }); } 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)); }); } } }