// Copyright (C) Stichting Deltares 2025. All rights reserved.
//
// This file is part of the Dam Engine.
//
// The Dam Engine is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see .
//
// All names, logos, and references to "Deltares" are registered trademarks of
// Stichting Deltares and remain full property of Stichting Deltares at all times.
// All rights reserved.
using System.Collections.Generic;
using System.Linq;
using Deltares.DamEngine.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);
var soilProfile = new SoilProfile2D
{
Geometry = new GeometryData
{
Left = leftCoordinate,
Right = rightCoordinate,
Bottom = -30
}
};
SoilLayer2D soilUpperLayer = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(0, -10, leftCoordinate, rightCoordinate, soilProfile);
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, soilProfile);
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, soilProfile, true);
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
var soilProfile = new SoilProfile2D
{
Geometry = new GeometryData
{
Left = leftCoordinate,
Right = rightCoordinate,
Bottom = -30
}
};
SoilLayer2D soilLayer = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(0, -10, leftCoordinate, rightCoordinate, soilProfile);
SoilLayer2D soilLayerAquiferInBetweenLeft = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-10, -20,
leftCoordinate, middleXCoordinate, soilProfile, null, true);
SoilLayer2D soilLayerAquiferInBetweenRight = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-10, -20, middleXCoordinate, rightCoordinate, soilProfile, null, true);
SoilLayer2D soilLayerInBetweenAquifer = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-20, -22, leftCoordinate, rightCoordinate, soilProfile, null, true);
SoilLayer2D soilLayerInBetweenAquitard = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-22, -25, leftCoordinate, rightCoordinate, soilProfile);
SoilLayer2D soilLayerAquiferBottom = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-25, -30, leftCoordinate, rightCoordinate, soilProfile, null, true);
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
var soilProfile = new SoilProfile2D
{
Geometry = new GeometryData
{
Left = leftCoordinate,
Right = rightCoordinate,
Bottom = -30
}
};
SoilLayer2D soilLayer = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(0, -10, leftCoordinate, rightCoordinate, soilProfile);
SoilLayer2D soilLayerAquiferInBetween = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, rightCoordinate, soilProfile, null, true);
SoilLayer2D soilLayerInBetween = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-20, -25, leftCoordinate, rightCoordinate, soilProfile);
SoilLayer2D soilLayerAquiferBottom = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-25, -30, leftCoordinate, rightCoordinate, soilProfile, null, true);
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
var soilProfile = new SoilProfile2D
{
Geometry = new GeometryData
{
Left = leftCoordinate,
Right = rightCoordinate,
Bottom = -30
}
};
SoilLayer2D soilLayer = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(0, -10, leftCoordinate, rightCoordinate, soilProfile);
SoilLayer2D soilLayerAquiferInBetweenLeft = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, soilProfile, null, true);
// Add a layer to fill the gap between the right aquifer layer and the upper layer
SoilLayer2D soilLayerGap = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-10, -15, middleXCoordinate, rightCoordinate, soilProfile);
SoilLayer2D soilLayerAquiferInBetweenRight = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-15, -21, middleXCoordinate, rightCoordinate, soilProfile, null, 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 = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-25, -30, leftCoordinate, rightCoordinate, soilProfile, null, true);
soilProfile.Surfaces.Add(soilLayer);
soilProfile.Surfaces.Add(soilLayerAquiferInBetweenLeft);
soilProfile.Surfaces.Add(soilLayerGap);
soilProfile.Surfaces.Add(soilLayerAquiferInBetweenRight);
soilProfile.Surfaces.Add(soilLayerInBetween); //Poly??
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(1));
Assert.That(bottomLevelInBetweenAquifer, Has.Count.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[0].Points, expectedTop);
AssertGeometry(bottomLevelInBetweenAquifer[0].Points, 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 soilProfile = new SoilProfile2D
{
Geometry = new GeometryData
{
Left = leftCoordinate,
Right = rightCoordinate,
Bottom = -30
}
};
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);
SoilLayer2D soilLayer = FactoryForSoilProfiles.CreatePolygoneSoilLayer2D([
..new[]
{
topLeftUpperLayer,
topRightUpperLayer,
bottomRightUpperLayer,
bottomIntermediateUpperUpperLayer,
bottomIntermediateLowerUpperLayer,
bottomLeftUpperLayer
}
], null, soilProfile);
SoilLayer2D soilLayerAquiferInBetweenLeft = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, soilProfile, null, true);
SoilLayer2D soilLayerAquiferInBetweenRight = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-5, -20, middleXCoordinate, rightCoordinate, soilProfile, null, true);
SoilLayer2D soilLayerInBetween = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-20, -25, leftCoordinate, rightCoordinate, soilProfile);
SoilLayer2D soilLayerAquiferBottom = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-25, -30, leftCoordinate, rightCoordinate, soilProfile, null, true);
soilLayerAquiferBottom.IsAquifer = true;
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(1));
Assert.That(bottomLevelInBetweenAquifer, Has.Count.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(rightCoordinate, -20)
];
AssertGeometry(topLevelInBetweenAquifer[0].Points, expectedTop);
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 soilProfile = new SoilProfile2D
{
Geometry = new GeometryData
{
Left = leftCoordinate,
Right = rightCoordinate,
Bottom = -30
}
};
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);
SoilLayer2D soilLayer = FactoryForSoilProfiles.CreatePolygoneSoilLayer2D([
..new[]
{
topLeftUpperLayer,
topRightUpperLayer,
bottomRightUpperLayer,
bottomIntermediateLowerUpperLayer,
bottomIntermediateUpperUpperLayer,
bottomLeftUpperLayer
}
], null, soilProfile);
SoilLayer2D soilLayerAquiferInBetweenLeft = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, soilProfile, null, true);
SoilLayer2D soilLayerAquiferInBetweenRight = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-15, -17, middleXCoordinate, rightCoordinate, soilProfile, null, 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);
SoilLayer2D soilLayerInBetween = FactoryForSoilProfiles.CreatePolygoneSoilLayer2D([
..new[]
{
bottomLeftInBetweenAquiferLayerLeft,
bottomRightInBetweenAquiferLayerLeft,
bottomLeftInBetweenAquiferLayerRight,
bottomRightInBetweenAquiferLayerRight,
bottomRightInBetweenLayer,
bottomLeftInBetweenLayer
}
], null, soilProfile);
SoilLayer2D soilLayerAquiferBottom = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-25, -30, leftCoordinate, rightCoordinate, soilProfile, null, true);
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(1));
Assert.That(bottomLevelInBetweenAquifer, Has.Count.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[0].Points, expectedTop);
AssertGeometry(bottomLevelInBetweenAquifer[0].Points, 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 soilProfile = new SoilProfile2D
{
Geometry = new GeometryData
{
Left = leftCoordinate,
Right = rightCoordinate,
Bottom = -30
}
};
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);
SoilLayer2D soilLayer = FactoryForSoilProfiles.CreatePolygoneSoilLayer2D([
..new[]
{
topLeftUpperLayer,
topRightUpperLayer,
bottomRightUpperLayer,
bottomIntermediateLowerUpperLayer,
bottomIntermediateUpperUpperLayer,
bottomLeftUpperLayer
}
], null, soilProfile);
SoilLayer2D soilLayerAquiferInBetweenLeft = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, soilProfile, null, true);
SoilLayer2D soilLayerAquiferInBetweenRight = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-5, -21, middleXCoordinate, rightCoordinate, soilProfile, null, 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);
SoilLayer2D soilLayerInBetween = FactoryForSoilProfiles.CreatePolygoneSoilLayer2D([
..new[]
{
bottomLeftInBetweenAquiferLayerLeft,
bottomRightInBetweenAquiferLayerLeft,
bottomLeftInBetweenAquiferLayerRight,
bottomRightInBetweenAquiferLayerRight,
bottomRightInBetweenLayer,
bottomLeftInBetweenLayer
}
], null, soilProfile);
SoilLayer2D soilLayerAquiferBottom = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-25, -30, leftCoordinate, rightCoordinate, soilProfile, null, true);
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(1));
Assert.That(bottomLevelInBetweenAquifer, Has.Count.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[0].Points, expectedTop);
AssertGeometry(bottomLevelInBetweenAquifer[0].Points, expectedBottom);
}
///
/// ----------------------------------------------\ 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);
var soilProfile = new SoilProfile2D
{
Geometry = new GeometryData
{
Left = leftCoordinate,
Right = rightCoordinate,
Bottom = -20
}
};
// Setup
SoilLayer2D soilLayerTop = FactoryForSoilProfiles.CreateHexagonSoilLayer2D(new Point2D(leftCoordinate, 0), pointE, pointF, pointD, pointB, new Point2D(leftCoordinate, -10), soilProfile);
SoilLayer2D soilLayerInBetweenAquifer = FactoryForSoilProfiles.CreatePolygoneSoilLayer2D([
..new[]
{
new Point2D(leftCoordinate, -10),
pointB,
pointD,
pointF,
pointG,
pointC,
pointA,
new Point2D(leftCoordinate, -13)
}
], null, soilProfile, true);
SoilLayer2D soilLayerAquitard = FactoryForSoilProfiles.CreateHexagonSoilLayer2D(new Point2D(leftCoordinate, -13), pointA, pointC, pointG, new Point2D(rightCoordinate, -15), new Point2D(leftCoordinate, -15), soilProfile);
SoilLayer2D soilLayerAquiferBottom = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-15, -20, leftCoordinate, rightCoordinate, soilProfile, null, true);
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);
}
[Test]
public void GivenAListOfPolyLines_WhenConnectingThem_ThenExpectedConnectedPolyLinesReturned()
{
// Setup
var polyLine1 = new GeometryPointString();
polyLine1.Points.Add(new Point2D(-1, 2));
polyLine1.Points.Add(new Point2D(3, 4));
polyLine1.Points.Add(new Point2D(5, 6));
var polyLine2 = new GeometryPointString();
polyLine2.Points.Add(new Point2D(5, 6));
polyLine2.Points.Add(new Point2D(9, 1));
polyLine2.Points.Add(new Point2D(15, 26));
var polyLine3 = new GeometryPointString();
polyLine3.Points.Add(new Point2D(3, 4));
polyLine3.Points.Add(new Point2D(9, 5));
polyLine3.Points.Add(new Point2D(6, 8));
var polyLine4 = new GeometryPointString();
polyLine4.Points.Add(new Point2D(15, 14));
polyLine4.Points.Add(new Point2D(16, 14));
var polyLines = new List
{
polyLine1,
polyLine2,
polyLine3,
polyLine4
};
// Call
List connectedPolyLines = SoilProfile2DHelper.ConnectPolyLines(polyLines);
// Assert - Expected is that poly-lines 1, 2 and 4 are connected but poly-line 3 not
Assert.Multiple(() =>
{
Assert.That(connectedPolyLines, Has.Count.EqualTo(2));
Assert.That(connectedPolyLines[0].Points, Has.Count.EqualTo(7));
Assert.That(connectedPolyLines[1].Points, Has.Count.EqualTo(3));
Assert.That(connectedPolyLines[0].Points[0].X, Is.EqualTo(-1));
Assert.That(connectedPolyLines[0].Points[0].Z, Is.EqualTo(2));
Assert.That(connectedPolyLines[0].Points[1].X, Is.EqualTo(3));
Assert.That(connectedPolyLines[0].Points[1].Z, Is.EqualTo(4));
Assert.That(connectedPolyLines[0].Points[2].X, Is.EqualTo(5));
Assert.That(connectedPolyLines[0].Points[2].Z, Is.EqualTo(6));
Assert.That(connectedPolyLines[0].Points[3].X, Is.EqualTo(9));
Assert.That(connectedPolyLines[0].Points[3].Z, Is.EqualTo(1));
Assert.That(connectedPolyLines[0].Points[4].X, Is.EqualTo(15));
Assert.That(connectedPolyLines[0].Points[4].Z, Is.EqualTo(26));
Assert.That(connectedPolyLines[0].Points[5].X, Is.EqualTo(15));
Assert.That(connectedPolyLines[0].Points[5].Z, Is.EqualTo(14));
Assert.That(connectedPolyLines[0].Points[6].X, Is.EqualTo(16));
Assert.That(connectedPolyLines[0].Points[6].Z, Is.EqualTo(14));
});
}
///
/// 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
var soilProfileFullAdjoin = new SoilProfile2D
{
Geometry = new GeometryData
{
Left = leftCoordinate,
Right = rightCoordinate,
Bottom = -20
}
};
SoilLayer2D soilUpperLayer = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(0, -10, leftCoordinate, rightCoordinate, soilProfileFullAdjoin);
SoilLayer2D soilBottomLayerAquiferPartLeft = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, soilProfileFullAdjoin, null, true);
SoilLayer2D soilBottomLayerAquiferPartRight = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-10, -20, middleXCoordinate, rightCoordinate, soilProfileFullAdjoin, null, true);
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
var soilProfileOneBottomAquiferLayer = new SoilProfile2D
{
Geometry = new GeometryData
{
Left = leftCoordinate,
Right = rightCoordinate,
Bottom = -20
}
};
SoilLayer2D soilBottomLayerAquifer = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, rightCoordinate, soilProfileOneBottomAquiferLayer, null, true);
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
var soilProfileRightSoilLayerBottomInRange = new SoilProfile2D
{
Geometry = new GeometryData
{
Left = leftCoordinate,
Right = rightCoordinate,
Bottom = -20
}
};
soilBottomLayerAquiferPartRight = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-5, -15, middleXCoordinate, rightCoordinate, soilProfileRightSoilLayerBottomInRange, null, true);
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
var soilProfileRightSoilLayerTopInRange = new SoilProfile2D
{
Geometry = new GeometryData
{
Left = leftCoordinate,
Right = rightCoordinate,
Bottom = -25
}
};
soilBottomLayerAquiferPartRight = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-15, -25, middleXCoordinate, rightCoordinate, soilProfileRightSoilLayerTopInRange, null, true);
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
var soilProfileRightAquiferLayerFullyEnvelopsLeft = new SoilProfile2D
{
Geometry = new GeometryData
{
Left = leftCoordinate,
Right = rightCoordinate,
Bottom = -25
}
};
soilBottomLayerAquiferPartRight = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-5, -25, middleXCoordinate, rightCoordinate, soilProfileRightAquiferLayerFullyEnvelopsLeft, null, true);
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
var soilProfileRightAquiferLayerFullyEnvelopedByLeft = new SoilProfile2D
{
Geometry = new GeometryData
{
Left = leftCoordinate,
Right = rightCoordinate,
Bottom = -20
}
};
soilBottomLayerAquiferPartRight = FactoryForSoilProfiles.CreateRectangularSoilLayer2D(-15, -17, middleXCoordinate, rightCoordinate, soilProfileRightAquiferLayerFullyEnvelopedByLeft, null, true);
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
};
}
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));
});
}
}
}