// 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.Data;
using System.Linq;
using Deltares.DamEngine.Calculators.KernelWrappers.MacroStabilityCommon;
using Deltares.DamEngine.Data.General;
using Deltares.DamEngine.Data.General.PlLines;
using Deltares.DamEngine.Data.Geometry;
using Deltares.DamEngine.Data.Geotechnics;
using NUnit.Framework;
namespace Deltares.DamEngine.Calculators.Tests.KernelWrappers.MacroStabilityCommon;
public class PlLinesToWaternetConverterTests
{
private const double precision3Decimals = 0.00051;
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);
private const double penetrationLength = 0.5;
[Test]
[TestCase(0)]
[TestCase(0.01)]
[TestCase(10)]
public void ConvertPlLineToWaternet_PlLinesFullyDefinedAtOrBelowBottomSoil1DProfile_ReturnsEmptyWaternet(double offsetFromBottomOfProfile)
{
// Setup
SoilProfile1D soilProfile = CreateSoilProfile1DForTest();
double bottomLevel = soilProfile.BottomLevel;
double plLineZCoordinate = bottomLevel - offsetFromBottomOfProfile;
var plLines = new PlLines();
PlLine plLine = plLines.Lines[PlLineType.Pl1];
plLine.Points.Add(new PlLinePoint(leftCoordinate, plLineZCoordinate));
plLine.Points.Add(new PlLinePoint(rightCoordinate, plLineZCoordinate));
plLine = plLines.Lines[PlLineType.Pl2];
plLine.Points.Add(new PlLinePoint(leftCoordinate, plLineZCoordinate));
plLine.Points.Add(new PlLinePoint(rightCoordinate, plLineZCoordinate));
plLine = plLines.Lines[PlLineType.Pl3];
plLine.Points.Add(new PlLinePoint(leftCoordinate, plLineZCoordinate));
plLine.Points.Add(new PlLinePoint(rightCoordinate, plLineZCoordinate));
plLine = plLines.Lines[PlLineType.Pl4];
plLine.Points.Add(new PlLinePoint(leftCoordinate, plLineZCoordinate));
plLine.Points.Add(new PlLinePoint(rightCoordinate, plLineZCoordinate));
// Call
Waternet waternet = PlLinesToWaternetConverter.ConvertPlLineToWaternet(plLines, soilProfile, penetrationLength, leftCoordinate, rightCoordinate);
// Assert
Assert.That(waternet.PhreaticLine, Is.Null);
Assert.That(waternet.HeadLineList, Is.Empty);
Assert.That(waternet.WaternetLineList, Is.Empty);
}
[Test]
public void TestConvertPlLinesToWaternet()
{
PlLines plLines = CreatePlLinesForTest();
SoilProfile1D soilProfile1D = CreateSoilProfile1DForTest();
Assert.Multiple(() =>
{
Assert.That(soilProfile1D.InBetweenAquiferLayer.TopLevel, Is.EqualTo(-2.111).Within(precision3Decimals));
Assert.That(soilProfile1D.BottomAquiferLayer.TopLevel, Is.EqualTo(-6.111).Within(precision3Decimals));
});
const double penetrateLength = 2.1;
const double left = 0;
const double right = 100;
Waternet waternet = PlLinesToWaternetConverter.ConvertPlLineToWaternet(plLines, soilProfile1D, penetrateLength, left, right);
// Pl 1 is only the phreatic line, a headline or waternet line does not have to be created
// Pl 2 gets waternet line to level of BottomAquiferLayer.TopLevel + penetrationLength
// Pl 3 gets waternet line to level of InBetweenAquiferLayer.TopLevel
// Pl 4 gets waternet line to level of BottomAquiferLayer.TopLevel
// expected phreatic line from pl 1
Assert.That(waternet.PhreaticLine.Points, Has.Count.EqualTo(3));
Assert.Multiple(() =>
{
Assert.That(waternet.PhreaticLine.Points[0].X, Is.EqualTo(0).Within(precision3Decimals));
Assert.That(waternet.PhreaticLine.Points[0].Z, Is.EqualTo(0).Within(precision3Decimals));
Assert.That(waternet.PhreaticLine.Points[1].X, Is.EqualTo(50).Within(precision3Decimals));
Assert.That(waternet.PhreaticLine.Points[1].Z, Is.EqualTo(1).Within(precision3Decimals));
Assert.That(waternet.PhreaticLine.Points[2].X, Is.EqualTo(100).Within(precision3Decimals));
Assert.That(waternet.PhreaticLine.Points[2].Z, Is.EqualTo(1).Within(precision3Decimals));
// expected head lines from pl 2, 3 and 4
Assert.That(waternet.HeadLineList, Has.Count.EqualTo(3));
});
Assert.Multiple(() =>
{
Assert.That(waternet.HeadLineList[0].Points.Count, Is.EqualTo(2));
Assert.That(waternet.HeadLineList[1].Points.Count, Is.EqualTo(3));
Assert.That(waternet.HeadLineList[2].Points.Count, Is.EqualTo(2));
// check the points of first head line that represents pl 2
Assert.That(waternet.HeadLineList[0].Points[0].X, Is.EqualTo(0).Within(precision3Decimals));
Assert.That(waternet.HeadLineList[0].Points[0].Z, Is.EqualTo(0).Within(precision3Decimals));
Assert.That(waternet.HeadLineList[0].Points[1].X, Is.EqualTo(100).Within(precision3Decimals));
Assert.That(waternet.HeadLineList[0].Points[1].Z, Is.EqualTo(-1).Within(precision3Decimals));
// expected waternet lines from pl 2, 3 and 4
Assert.That(waternet.WaternetLineList.Count, Is.EqualTo(3));
});
Assert.Multiple(() =>
{
// expected waternet line 0 is connected to pl2 with level -6.111 + 2.1 = -4.011
Assert.That(waternet.WaternetLineList[0].HeadLine, Is.EqualTo(waternet.HeadLineList[0]));
Assert.That(waternet.WaternetLineList[0].Points[0].X, Is.EqualTo(0).Within(precision3Decimals));
Assert.That(waternet.WaternetLineList[0].Points[0].Z, Is.EqualTo(-4.011).Within(precision3Decimals));
Assert.That(waternet.WaternetLineList[0].Points[1].X, Is.EqualTo(100).Within(precision3Decimals));
Assert.That(waternet.WaternetLineList[0].Points[1].Z, Is.EqualTo(-4.011).Within(precision3Decimals));
// expected waternet line 1 is connected to pl3 with level -6.111
Assert.That(waternet.WaternetLineList[1].HeadLine, Is.EqualTo(waternet.HeadLineList[1]));
Assert.That(waternet.WaternetLineList[1].Points[0].Z, Is.EqualTo(-6.111).Within(precision3Decimals));
// expected waternet line 2 is connected to pl4 with level -2.111
Assert.That(waternet.WaternetLineList[2].HeadLine, Is.EqualTo(waternet.HeadLineList[2]));
Assert.That(waternet.WaternetLineList[2].Points[0].Z, Is.EqualTo(-2.111).Within(precision3Decimals));
});
}
[Test]
public void TestConvertPlLinesToWaternetWhenNoHeadLinesExpected()
{
PlLines plLines = CreatePlLinesForTest();
SoilProfile1D soilProfile1D = CreateSoilProfile1DForTest();
Waternet waternet = PlLinesToWaternetConverter.ConvertPlLineToWaternet(plLines, soilProfile1D, 0, 0, 0);
// head lines
Assert.That(waternet.HeadLineList, Has.Count.EqualTo(3));
Assert.Multiple(() =>
{
Assert.That(waternet.HeadLineList[0].Points.Count, Is.EqualTo(2));
Assert.That(waternet.HeadLineList[1].Points.Count, Is.EqualTo(3));
Assert.That(waternet.HeadLineList[2].Points.Count, Is.EqualTo(2));
// phreatic line
Assert.That(waternet.PhreaticLine.Points.Count, Is.EqualTo(3));
});
// check that no headline are added when Pl2, Pl3 or Pl4 does not exist or has no points
plLines.Lines[PlLineType.Pl3] = null;
plLines.Lines[PlLineType.Pl4].Points.Clear();
waternet = PlLinesToWaternetConverter.ConvertPlLineToWaternet(plLines, soilProfile1D, 0, 0, 0);
// head lines
Assert.That(waternet.HeadLineList, Has.Count.EqualTo(1));
Assert.Multiple(() =>
{
Assert.That(waternet.HeadLineList[0].Points, Has.Count.EqualTo(2));
// phreatic line
Assert.That(waternet.PhreaticLine.Points, Has.Count.EqualTo(3));
});
}
[Test]
public void TestConvertPlLinesToWaternetWhenNoWaternetLinesExpected()
{
PlLines plLines = CreatePlLinesForTest();
SoilProfile1D soilProfile1D = CreateSoilProfile1DForTest();
const double penetrateLength = 2.1;
Waternet waternet = PlLinesToWaternetConverter.ConvertPlLineToWaternet(plLines, soilProfile1D, penetrateLength, 0, 0);
Assert.Multiple(() =>
{
Assert.That(waternet.HeadLineList, Has.Count.EqualTo(3));
Assert.That(waternet.WaternetLineList, Has.Count.EqualTo(3));
});
// check that no waternetlines are added for pl3 when InBetweenAquiferLayer is null
soilProfile1D = CreateSoilProfile1DWith1AquiferForTest();
waternet = PlLinesToWaternetConverter.ConvertPlLineToWaternet(plLines, soilProfile1D, penetrateLength, 0, 0);
Assert.Multiple(() =>
{
Assert.That(waternet.HeadLineList, Has.Count.EqualTo(3));
Assert.That(waternet.WaternetLineList, Has.Count.EqualTo(2));
});
Assert.Multiple(() =>
{
// expected waternet line 0 is connected to pl2 with level -6.111 + 2.1 = -4.011
Assert.That(waternet.WaternetLineList[0].HeadLine, Is.EqualTo(waternet.HeadLineList[0]));
Assert.That(waternet.WaternetLineList[0].Points[0].Z, Is.EqualTo(-4.011).Within(precision3Decimals));
// expected waternet line 1 is connected to pl3 with level -6.111
Assert.That(waternet.WaternetLineList[1].HeadLine, Is.EqualTo(waternet.HeadLineList[1]));
Assert.That(waternet.WaternetLineList[1].Points[0].Z, Is.EqualTo(-6.111).Within(precision3Decimals));
});
// check that no waternetlines are added for pl2, pl3 and pl4 when BottomAquiferLayer is null
soilProfile1D = CreateSoilProfile1DWithoutAquifersForTest();
waternet = PlLinesToWaternetConverter.ConvertPlLineToWaternet(plLines, soilProfile1D, penetrateLength, 0, 0);
Assert.Multiple(() =>
{
Assert.That(waternet.HeadLineList, Has.Count.EqualTo(3));
Assert.That(waternet.WaternetLineList, Is.Empty);
});
}
[Test]
public void TestConvertLevelToWaternetLine()
{
const double level = 1.234;
const double left = -50.111;
const double right = 50.123;
WaternetLine waternetLine = PlLinesToWaternetConverter.CreateWaternetLine(level, left, right);
Assert.That(waternetLine.Points, Has.Count.EqualTo(2));
Assert.Multiple(() =>
{
Assert.That(waternetLine.Points[0].X, Is.EqualTo(-50.111).Within(precision3Decimals));
Assert.That(waternetLine.Points[0].Z, Is.EqualTo(1.234).Within(precision3Decimals));
Assert.That(waternetLine.Points[1].X, Is.EqualTo(50.123).Within(precision3Decimals));
Assert.That(waternetLine.Points[1].Z, Is.EqualTo(1.234).Within(precision3Decimals));
});
}
///
/// 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.
/// Expected is that:
/// - PL3 is connected to the top of the bottom aquifer layer
/// - PL2 is connected to the line parallel to the top of the bottom aquifer layer but shifted by 0.5 m (penetration length) upwards
/// - PL4 is not used because no in-between aquifer is present
///
///
///
[Test]
[TestCaseSource(nameof(GetSoilProfilesWithContinuousBottomAquiferLayer))]
public void ConvertPlLineToWaternet_ValidPLLinesAndSoilProfile2DWithContinuousAquiferLayers_ReturnsExpectedWaternet(
SoilProfile2D soilProfile, IEnumerable expectedBottomAquiferCoordinates)
{
// Setup
PlLines plLines = CreateAllPlLines();
// Call
Waternet waternet = PlLinesToWaternetConverter.ConvertPlLineToWaternet(plLines, soilProfile, penetrationLength);
// Assert
AssertGeometry(plLines.Lines[PlLineType.Pl1].Points, waternet.PhreaticLine.Points);
Assert.That(waternet.HeadLineList, Has.Count.EqualTo(3));
AssertGeometry(plLines.Lines[PlLineType.Pl2].Points, waternet.HeadLineList[0].Points);
AssertGeometry(plLines.Lines[PlLineType.Pl3].Points, waternet.HeadLineList[1].Points);
AssertGeometry(plLines.Lines[PlLineType.Pl4].Points, waternet.HeadLineList[2].Points);
Assert.That(waternet.WaternetLineList, Has.Count.EqualTo(2));
WaternetLine pl2WaternetLine = waternet.WaternetLineList[0];
Assert.That(pl2WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[0]));
GeometryPoint[] offSetAquiferCoordinates = expectedBottomAquiferCoordinates.Select(aquiferCoordinate => new GeometryPoint(aquiferCoordinate.X, aquiferCoordinate.Z + penetrationLength))
.ToArray();
AssertGeometry(offSetAquiferCoordinates, pl2WaternetLine.Points);
WaternetLine pl3WaternetLine = waternet.WaternetLineList[1];
Assert.That(pl3WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[1]));
AssertGeometry(expectedBottomAquiferCoordinates, pl3WaternetLine.Points);
}
///
/// --------------------------------------------------------------- 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 ConvertPlLineToWaternet_ValidPLLinesAndSoilProfile2DWithContinuousInBetweenAquiferLayerConsistOfTwoParts_ReturnsExpectedWaternet()
{
// 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);
PlLines plLines = CreateAllPlLines();
// Call
Waternet waternet = PlLinesToWaternetConverter.ConvertPlLineToWaternet(plLines, soilProfile, penetrationLength);
// Assert
AssertGeometry(plLines.Lines[PlLineType.Pl1].Points, waternet.PhreaticLine.Points);
Assert.That(waternet.HeadLineList, Has.Count.EqualTo(3));
AssertGeometry(plLines.Lines[PlLineType.Pl2].Points, waternet.HeadLineList[0].Points);
AssertGeometry(plLines.Lines[PlLineType.Pl3].Points, waternet.HeadLineList[1].Points);
AssertGeometry(plLines.Lines[PlLineType.Pl4].Points, waternet.HeadLineList[2].Points);
Assert.That(waternet.WaternetLineList, Has.Count.EqualTo(3));
Point2D[] expectedBottomAquiferCoordinates =
[
new Point2D(leftCoordinate, -25),
new Point2D(middleXCoordinate, -25),
new Point2D(rightCoordinate, -25)
];
WaternetLine pl2WaternetLine = waternet.WaternetLineList[0];
Assert.That(pl2WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[0]));
GeometryPoint[] offSetAquiferCoordinates = expectedBottomAquiferCoordinates.Select(aquiferCoordinate => new GeometryPoint(aquiferCoordinate.X, aquiferCoordinate.Z + penetrationLength))
.ToArray();
AssertGeometry(offSetAquiferCoordinates, pl2WaternetLine.Points);
WaternetLine pl3WaternetLine = waternet.WaternetLineList[1];
Assert.That(pl3WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[1]));
AssertGeometry(expectedBottomAquiferCoordinates, pl3WaternetLine.Points);
WaternetLine pl4WaternetLine = waternet.WaternetLineList[2];
Assert.That(pl4WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[2]));
AssertGeometry([
new Point2D(leftCoordinate, -10),
new Point2D(middleXCoordinate, -10),
new Point2D(rightCoordinate, -10)
], pl4WaternetLine.Points);
}
///
/// --------------------------------------------------- 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 ConvertPlLineToWaternet_ValidPLLinesAndSoilProfile2DWithContinuousInBetweenAquiferLayerConsistOfOnePart_ReturnsExpectedWaternet()
{
// 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);
PlLines plLines = CreateAllPlLines();
// Call
Waternet waternet = PlLinesToWaternetConverter.ConvertPlLineToWaternet(plLines, soilProfile, penetrationLength);
// Assert
AssertGeometry(plLines.Lines[PlLineType.Pl1].Points, waternet.PhreaticLine.Points);
Assert.That(waternet.HeadLineList, Has.Count.EqualTo(3));
AssertGeometry(plLines.Lines[PlLineType.Pl2].Points, waternet.HeadLineList[0].Points);
AssertGeometry(plLines.Lines[PlLineType.Pl3].Points, waternet.HeadLineList[1].Points);
AssertGeometry(plLines.Lines[PlLineType.Pl4].Points, waternet.HeadLineList[2].Points);
Assert.That(waternet.WaternetLineList, Has.Count.EqualTo(3));
var bottomRightInBetweenLayer = new Point2D(rightCoordinate, -25);
var bottomLeftInBetweenLayer = new Point2D(leftCoordinate, -25);
Point2D[] expectedBottomAquiferCoordinates =
[
bottomLeftInBetweenLayer,
bottomRightInBetweenLayer
];
WaternetLine pl2WaternetLine = waternet.WaternetLineList[0];
Assert.That(pl2WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[0]));
GeometryPoint[] offSetAquiferCoordinates = expectedBottomAquiferCoordinates.Select(aquiferCoordinate => new GeometryPoint(aquiferCoordinate.X, aquiferCoordinate.Z + penetrationLength))
.ToArray();
AssertGeometry(offSetAquiferCoordinates, pl2WaternetLine.Points);
WaternetLine pl3WaternetLine = waternet.WaternetLineList[1];
Assert.That(pl3WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[1]));
AssertGeometry(expectedBottomAquiferCoordinates, pl3WaternetLine.Points);
WaternetLine pl4WaternetLine = waternet.WaternetLineList[2];
Assert.That(pl4WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[2]));
var bottomRightUpperLayer = new Point2D(rightCoordinate, -10);
var bottomLeftUpperLayer = new Point2D(leftCoordinate, -10);
AssertGeometry([
bottomLeftUpperLayer,
bottomRightUpperLayer
], pl4WaternetLine.Points);
}
///
/// ------------------------------------------------------------- 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 ConvertPlLineToWaternet_ValidPLLinesAndSoilProfile2DWithContinuousInBetweenAquiferLayerRightLayerTopLevelInRangeLeftLayer_ReturnsExpectedWaternet()
{
// 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);
PlLines plLines = CreateAllPlLines();
// Call
Waternet waternet = PlLinesToWaternetConverter.ConvertPlLineToWaternet(plLines, soilProfile, penetrationLength);
// Assert
AssertGeometry(plLines.Lines[PlLineType.Pl1].Points, waternet.PhreaticLine.Points);
Assert.That(waternet.HeadLineList, Has.Count.EqualTo(3));
AssertGeometry(plLines.Lines[PlLineType.Pl2].Points, waternet.HeadLineList[0].Points);
AssertGeometry(plLines.Lines[PlLineType.Pl3].Points, waternet.HeadLineList[1].Points);
AssertGeometry(plLines.Lines[PlLineType.Pl4].Points, waternet.HeadLineList[2].Points);
Assert.That(waternet.WaternetLineList, Has.Count.EqualTo(3));
Point2D[] expectedBottomAquiferCoordinates =
{
bottomLeftInBetweenLayer,
new(middleXCoordinate, -25),
bottomRightInBetweenLayer
};
WaternetLine pl2WaternetLine = waternet.WaternetLineList[0];
Assert.That(pl2WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[0]));
GeometryPoint[] offSetAquiferCoordinates = expectedBottomAquiferCoordinates.Select(aquiferCoordinate => new GeometryPoint(aquiferCoordinate.X, aquiferCoordinate.Z + penetrationLength))
.ToArray();
AssertGeometry(offSetAquiferCoordinates, pl2WaternetLine.Points);
WaternetLine pl3WaternetLine = waternet.WaternetLineList[1];
Assert.That(pl3WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[1]));
AssertGeometry(expectedBottomAquiferCoordinates, pl3WaternetLine.Points);
WaternetLine pl4WaternetLine = waternet.WaternetLineList[2];
Assert.That(pl4WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[2]));
AssertGeometry([
new GeometryPoint(leftCoordinate, -10),
new GeometryPoint(middleXCoordinate, -10),
new GeometryPoint(rightCoordinate, -15)
], pl4WaternetLine.Points);
}
///
/// -------------------------------------------------------------- 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 ConvertPlLineToWaternet_ValidPLLinesAndSoilProfile2DWithContinuousInBetweenAquiferLayerRightLayerBottomLevelInRangeLeftLayer_ReturnsExpectedWaternet()
{
// 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);
PlLines plLines = CreateAllPlLines();
// Call
Waternet waternet = PlLinesToWaternetConverter.ConvertPlLineToWaternet(plLines, soilProfile, penetrationLength);
// Assert
AssertGeometry(plLines.Lines[PlLineType.Pl1].Points, waternet.PhreaticLine.Points);
Assert.That(waternet.HeadLineList, Has.Count.EqualTo(3));
AssertGeometry(plLines.Lines[PlLineType.Pl2].Points, waternet.HeadLineList[0].Points);
AssertGeometry(plLines.Lines[PlLineType.Pl3].Points, waternet.HeadLineList[1].Points);
AssertGeometry(plLines.Lines[PlLineType.Pl4].Points, waternet.HeadLineList[2].Points);
Assert.That(waternet.WaternetLineList, Has.Count.EqualTo(3));
var bottomRightInBetweenLayer = new Point2D(rightCoordinate, -25);
var bottomLeftInBetweenLayer = new Point2D(leftCoordinate, -25);
Point2D[] expectedBottomAquiferCoordinates =
{
bottomLeftInBetweenLayer,
new Point2D(middleXCoordinate, -25),
bottomRightInBetweenLayer
};
WaternetLine pl2WaternetLine = waternet.WaternetLineList[0];
Assert.That(pl2WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[0]));
GeometryPoint[] offSetAquiferCoordinates = expectedBottomAquiferCoordinates.Select(aquiferCoordinate => new GeometryPoint(aquiferCoordinate.X, aquiferCoordinate.Z + penetrationLength))
.ToArray();
AssertGeometry(offSetAquiferCoordinates, pl2WaternetLine.Points);
WaternetLine pl3WaternetLine = waternet.WaternetLineList[1];
Assert.That(pl3WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[1]));
AssertGeometry(expectedBottomAquiferCoordinates, pl3WaternetLine.Points);
WaternetLine pl4WaternetLine = waternet.WaternetLineList[2];
Assert.That(pl4WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[2]));
AssertGeometry(new[]
{
bottomLeftUpperLayer,
bottomIntermediateUpperUpperLayer,
bottomRightUpperLayer
}, pl4WaternetLine.Points);
}
///
/// ------------------------------------------------------------- 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 ConvertPlLineToWaternet_ValidPLLinesAndSoilProfile2DWithContinuousInBetweenAquiferLayerRightLayerEnvelopedByLeftLayer_ReturnsExpectedWaternet()
{
// 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);
PlLines plLines = CreateAllPlLines();
// Call
Waternet waternet = PlLinesToWaternetConverter.ConvertPlLineToWaternet(plLines, soilProfile, penetrationLength);
// Assert
AssertGeometry(plLines.Lines[PlLineType.Pl1].Points, waternet.PhreaticLine.Points);
Assert.That(waternet.HeadLineList, Has.Count.EqualTo(3));
AssertGeometry(plLines.Lines[PlLineType.Pl2].Points, waternet.HeadLineList[0].Points);
AssertGeometry(plLines.Lines[PlLineType.Pl3].Points, waternet.HeadLineList[1].Points);
AssertGeometry(plLines.Lines[PlLineType.Pl4].Points, waternet.HeadLineList[2].Points);
Assert.That(waternet.WaternetLineList.Count, Is.EqualTo(3));
Point2D[] expectedBottomAquiferCoordinates =
{
bottomLeftInBetweenLayer,
new Point2D(middleXCoordinate, -25),
bottomRightInBetweenLayer
};
WaternetLine pl2WaternetLine = waternet.WaternetLineList[0];
Assert.That(pl2WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[0]));
GeometryPoint[] offSetAquiferCoordinates = expectedBottomAquiferCoordinates.Select(aquiferCoordinate => new GeometryPoint(aquiferCoordinate.X, aquiferCoordinate.Z + penetrationLength))
.ToArray();
AssertGeometry(offSetAquiferCoordinates, pl2WaternetLine.Points);
WaternetLine pl3WaternetLine = waternet.WaternetLineList[1];
Assert.That(pl3WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[1]));
AssertGeometry(expectedBottomAquiferCoordinates, pl3WaternetLine.Points);
WaternetLine pl4WaternetLine = waternet.WaternetLineList[2];
Assert.That(pl4WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[2]));
AssertGeometry(new[]
{
bottomLeftUpperLayer,
bottomIntermediateUpperUpperLayer,
bottomRightUpperLayer
}, pl4WaternetLine.Points);
}
///
/// ------------------------------------------------------------- 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 ConvertPlLineToWaternet_ValidPLLinesAndSoilProfile2DWithContinuousInBetweenAquiferLayerRightLayerEnvelopesLeftLayer_ReturnsExpectedWaternet()
{
// 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);
PlLines plLines = CreateAllPlLines();
// Call
Waternet waternet = PlLinesToWaternetConverter.ConvertPlLineToWaternet(plLines, soilProfile, penetrationLength);
// Assert
AssertGeometry(plLines.Lines[PlLineType.Pl1].Points, waternet.PhreaticLine.Points);
Assert.That(waternet.HeadLineList, Has.Count.EqualTo(3));
AssertGeometry(plLines.Lines[PlLineType.Pl2].Points, waternet.HeadLineList[0].Points);
AssertGeometry(plLines.Lines[PlLineType.Pl3].Points, waternet.HeadLineList[1].Points);
AssertGeometry(plLines.Lines[PlLineType.Pl4].Points, waternet.HeadLineList[2].Points);
Assert.That(waternet.WaternetLineList, Has.Count.EqualTo(3));
Point2D[] expectedBottomAquiferCoordinates =
{
bottomLeftInBetweenLayer,
new Point2D(middleXCoordinate, -25),
bottomRightInBetweenLayer
};
WaternetLine pl2WaternetLine = waternet.WaternetLineList[0];
Assert.That(pl2WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[0]));
GeometryPoint[] offSetAquiferCoordinates = expectedBottomAquiferCoordinates.Select(aquiferCoordinate => new GeometryPoint(aquiferCoordinate.X, aquiferCoordinate.Z + penetrationLength))
.ToArray();
AssertGeometry(offSetAquiferCoordinates, pl2WaternetLine.Points);
WaternetLine pl3WaternetLine = waternet.WaternetLineList[1];
Assert.That(pl3WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[1]));
AssertGeometry(expectedBottomAquiferCoordinates, pl3WaternetLine.Points);
WaternetLine pl4WaternetLine = waternet.WaternetLineList[2];
Assert.That(pl4WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[2]));
AssertGeometry(new[]
{
bottomLeftUpperLayer,
bottomIntermediateLowerUpperLayer,
bottomRightUpperLayer
}, pl4WaternetLine.Points);
}
///
/// --------------------------------------------------- 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 ConvertPlLineToWaternet_ValidPLLinesAndSoilProfile2DWithDiscontinuousInBetweenAquiferLayer_ReturnsExpectedWaternet(
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);
PlLines plLines = CreateAllPlLines();
// Call
Waternet waternet = PlLinesToWaternetConverter.ConvertPlLineToWaternet(plLines, soilProfile, penetrationLength);
// Assert
AssertGeometry(plLines.Lines[PlLineType.Pl1].Points, waternet.PhreaticLine.Points);
Assert.That(waternet.HeadLineList, Has.Count.EqualTo(3));
AssertGeometry(plLines.Lines[PlLineType.Pl2].Points, waternet.HeadLineList[0].Points);
AssertGeometry(plLines.Lines[PlLineType.Pl3].Points, waternet.HeadLineList[1].Points);
AssertGeometry(plLines.Lines[PlLineType.Pl4].Points, waternet.HeadLineList[2].Points);
Assert.That(waternet.WaternetLineList, Has.Count.EqualTo(2));
var bottomRightInBetweenLayer = new Point2D(rightCoordinate, -25);
var bottomLeftInBetweenLayer = new Point2D(leftCoordinate, -25);
Point2D[] expectedBottomAquiferCoordinates =
{
bottomLeftInBetweenLayer,
new Point2D(middleXCoordinate, -25),
bottomRightInBetweenLayer
};
WaternetLine pl2WaternetLine = waternet.WaternetLineList[0];
Assert.That(pl2WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[0]));
GeometryPoint[] offSetAquiferCoordinates = expectedBottomAquiferCoordinates.Select(aquiferCoordinate => new GeometryPoint(aquiferCoordinate.X, aquiferCoordinate.Z + penetrationLength))
.ToArray();
AssertGeometry(offSetAquiferCoordinates, pl2WaternetLine.Points);
WaternetLine pl3WaternetLine = waternet.WaternetLineList[1];
Assert.That(pl3WaternetLine.HeadLine, Is.SameAs(waternet.HeadLineList[1]));
AssertGeometry(expectedBottomAquiferCoordinates, pl3WaternetLine.Points);
}
///
/// --------------------------------------------------- Level 0 m
///
/// |------------------------- Level -5 m
/// top layer | right aquifer
/// |------------------------- Level -9 m
///
/// -------------------------|------------------------- Level -10 m
/// left aquifer |
/// -------------------------| Level -20 m
///
[Test]
public void ConvertPlLineToWaternet_ValidPLLinesAndSoilProfile2DWithDiscontinuousBottomAquiferLayer_ReturnsEmptyWaternet()
{
// Setup
SoilLayer2D soilLayer = CreateRectangularSoilLayer2D(0, -10, leftCoordinate, rightCoordinate, false);
SoilLayer2D soilLayerAquiferPartOne = CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, true);
SoilLayer2D soilLayerAquiferPartTwo = CreateRectangularSoilLayer2D(-5, -9, middleXCoordinate, rightCoordinate, true);
var soilProfile = new SoilProfile2D
{
Geometry = new GeometryData
{
Left = leftCoordinate,
Right = rightCoordinate,
Bottom = -20
}
};
soilProfile.Surfaces.Add(soilLayer);
soilProfile.Surfaces.Add(soilLayerAquiferPartOne);
soilProfile.Surfaces.Add(soilLayerAquiferPartTwo);
PlLines plLines = CreateAllPlLines();
// Call
Waternet waternet = PlLinesToWaternetConverter.ConvertPlLineToWaternet(plLines, soilProfile, penetrationLength);
// Assert
AssertGeometry(plLines.Lines[PlLineType.Pl1].Points, waternet.PhreaticLine.Points);
AssertGeometry(plLines.Lines[PlLineType.Pl2].Points, waternet.HeadLineList[0].Points);
AssertGeometry(plLines.Lines[PlLineType.Pl3].Points, waternet.HeadLineList[1].Points);
AssertGeometry(plLines.Lines[PlLineType.Pl4].Points, waternet.HeadLineList[2].Points);
Assert.That(waternet.WaternetLineList, Is.Empty);
}
///
/// --------------------------------------------------- Level 0 m
/// top layer
/// -------------------------|------------------------- Level -10 m
/// bottom layer left | bottom layer right
/// -------------------------|------------------------- Level -20 m
///
[Test]
[TestCase(true, false)]
[TestCase(false, true)]
public void ConvertPlLineToWaternet_ValidPLLinesAndSoilProfile2DWithBottomAquiferLayerNotSpanningWholeInterval_ReturnsEmptyWaternet(
bool isLeftBottomLayerAquifer, bool isRightBottomLayerAquifer)
{
// Setup
SoilLayer2D soilLayer = CreateRectangularSoilLayer2D(0, -10, leftCoordinate, rightCoordinate, false);
SoilLayer2D soilLayerAquiferPartOne = CreateRectangularSoilLayer2D(-10, -20, leftCoordinate, middleXCoordinate, isLeftBottomLayerAquifer);
SoilLayer2D soilLayerAquiferPartTwo = CreateRectangularSoilLayer2D(-10, -20, middleXCoordinate, rightCoordinate, isRightBottomLayerAquifer);
var soilProfile = new SoilProfile2D
{
Geometry = new GeometryData
{
Left = leftCoordinate,
Right = rightCoordinate,
Bottom = -20
}
};
soilProfile.Surfaces.Add(soilLayer);
soilProfile.Surfaces.Add(soilLayerAquiferPartOne);
soilProfile.Surfaces.Add(soilLayerAquiferPartTwo);
PlLines plLines = CreateAllPlLines();
// Call
Waternet waternet = PlLinesToWaternetConverter.ConvertPlLineToWaternet(plLines, soilProfile, penetrationLength);
// Assert
AssertGeometry(plLines.Lines[PlLineType.Pl1].Points, waternet.PhreaticLine.Points);
AssertGeometry(plLines.Lines[PlLineType.Pl2].Points, waternet.HeadLineList[0].Points);
AssertGeometry(plLines.Lines[PlLineType.Pl3].Points, waternet.HeadLineList[1].Points);
AssertGeometry(plLines.Lines[PlLineType.Pl4].Points, waternet.HeadLineList[2].Points);
Assert.That(waternet.WaternetLineList, Is.Empty);
}
[Test]
[SetUICulture("nl-NL")]
public void TestLanguageNLThrowsExceptionWhenSoilProfile1DIsNull()
{
var plLines = new PlLines();
Assert.That(() => PlLinesToWaternetConverter.ConvertPlLineToWaternet(plLines, null, 0, 0, 0), Throws.InstanceOf().With.Message.EqualTo("Geen ondergrond profiel gedefinieerd"));
}
[Test]
[SetUICulture("nl-NL")]
public void TestLanguageNLThrowsExceptionWhenPlLinesIsNull()
{
var soilProfile1D = new SoilProfile1D();
Assert.That(() => PlLinesToWaternetConverter.ConvertPlLineToWaternet(null, soilProfile1D, 0, 0, 0), Throws.InstanceOf().With.Message.EqualTo("Geen object voor pn-lijnen gedefinieerd"));
}
[Test]
[SetUICulture("nl-NL")]
public void ConvertPlLineToWaternet_SoilProfileNull_ThrowsException()
{
var plLines = new PlLines();
Assert.That(() => PlLinesToWaternetConverter.ConvertPlLineToWaternet(plLines, null, 0), Throws.InstanceOf().With.Message.EqualTo("Geen ondergrond profiel gedefinieerd"));
}
[Test]
[SetUICulture("nl-NL")]
public void ConvertPlLineToWaternet_ProfileLinesNull_ThrowsException()
{
var soilProfile = new SoilProfile2D();
Assert.That(() => PlLinesToWaternetConverter.ConvertPlLineToWaternet(null, soilProfile, 0), Throws.InstanceOf().With.Message.EqualTo("Geen object voor pn-lijnen gedefinieerd"));
}
private static PlLines CreatePlLinesForTest()
{
var plLines = new PlLines();
// pl 1 is phreatic line
PlLine plLine = plLines.Lines[PlLineType.Pl1];
plLine.IsPhreatic = true;
plLine.Points.Add(new PlLinePoint(0, 0));
plLine.Points.Add(new PlLinePoint(50, 1));
plLine.Points.Add(new PlLinePoint(100, 1));
// pl 2 first equal to point of pl 1
plLine = plLines.Lines[PlLineType.Pl2];
plLine.Points.Add(new PlLinePoint(0, 0));
plLine.Points.Add(new PlLinePoint(100, -1));
// pl 3
plLine = plLines.Lines[PlLineType.Pl3];
plLine.Points.Add(new PlLinePoint(0, 1));
plLine.Points.Add(new PlLinePoint(50, 0));
plLine.Points.Add(new PlLinePoint(100, -1));
// pl 4
plLine = plLines.Lines[PlLineType.Pl4];
plLine.Points.Add(new PlLinePoint(0, -5));
plLine.Points.Add(new PlLinePoint(100, -5));
return plLines;
}
private static SoilProfile1D CreateSoilProfile1DForTest()
{
var soilProfile1D = new SoilProfile1D
{
BottomLevel = -30.0
};
var layer = new SoilLayer1D
{
Name = "L1a",
TopLevel = 1.212,
IsAquifer = true // aquifer at top
};
soilProfile1D.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = "L1b",
TopLevel = 1.212,
IsAquifer = false
};
soilProfile1D.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = "L2a",
TopLevel = -2.111, // top of in-between aquifer
IsAquifer = true
};
soilProfile1D.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = "L2b",
TopLevel = -2.151,
IsAquifer = true
};
soilProfile1D.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = "L3",
TopLevel = -3.373,
IsAquifer = false
};
soilProfile1D.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = "L4",
TopLevel = -4.151,
IsAquifer = true
};
soilProfile1D.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = "L5",
TopLevel = -5.373,
IsAquifer = false
};
soilProfile1D.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = "L6a",
TopLevel = -6.111, // top of bottom aquifer
IsAquifer = true
};
soilProfile1D.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = "L6b",
TopLevel = -6.151,
IsAquifer = true
};
soilProfile1D.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = "L7",
TopLevel = -7.373,
IsAquifer = false
};
soilProfile1D.Layers.Add(layer);
return soilProfile1D;
}
private static SoilProfile1D CreateSoilProfile1DWith1AquiferForTest()
{
var soilProfile1D = new SoilProfile1D
{
BottomLevel = -30.0
};
var layer = new SoilLayer1D
{
Name = "L1b",
TopLevel = 1.212,
IsAquifer = false
};
soilProfile1D.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = "L6a",
TopLevel = -6.111, // top of bottom aquifer
IsAquifer = true
};
soilProfile1D.Layers.Add(layer);
return soilProfile1D;
}
private static SoilProfile1D CreateSoilProfile1DWithoutAquifersForTest()
{
var soilProfile1D = new SoilProfile1D
{
BottomLevel = -30.0
};
var layer = new SoilLayer1D
{
Name = "L1b",
TopLevel = 1.212,
IsAquifer = false
};
soilProfile1D.Layers.Add(layer);
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);
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);
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, -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(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, -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(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));
Assert.That(actualPoint.Z, Is.EqualTo(expectedPoint.Z));
});
}
}
private static PlLines CreateAllPlLines()
{
var plLines = new PlLines();
PlLine plLine = plLines.Lines[PlLineType.Pl1];
plLine.Name = "Phreatic line";
plLine.Points.Add(new PlLinePoint(leftCoordinate, -5));
plLine.Points.Add(new PlLinePoint(rightCoordinate, -5));
plLine = plLines.Lines[PlLineType.Pl2];
plLine.Name = "PL 2";
plLine.Points.Add(new PlLinePoint(leftCoordinate, -6));
plLine.Points.Add(new PlLinePoint(rightCoordinate, -6));
plLine = plLines.Lines[PlLineType.Pl3];
plLine.Name = "PL 3";
plLine.Points.Add(new PlLinePoint(leftCoordinate, -7));
plLine.Points.Add(new PlLinePoint(rightCoordinate, -7));
plLine = plLines.Lines[PlLineType.Pl4];
plLine.Name = "PL 4";
plLine.Points.Add(new PlLinePoint(leftCoordinate, -8));
plLine.Points.Add(new PlLinePoint(rightCoordinate, -8));
return plLines;
}
}