// 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.Data.Geometry;
using Deltares.DamEngine.Data.Geotechnics;
using Deltares.DamEngine.TestHelpers.Factories;
using NUnit.Framework;
namespace Deltares.DamEngine.Data.Tests.Geotechnics;
[TestFixture]
public class SoilSurfaceProfileTests
{
[Test]
public void GivenProfile1DWithOneLayerAndSurfaceLineWhenConverToProfile2DThenCorrectSoilProfile2DIsCreated()
{
// Given Profile1D with one layer and surface line
const string layerName = "Layer";
const string topLayerName = "TopLayer";
SoilLayer1D soilLayer = FactoryForSoilProfiles.CreateSoilLayer(-5, layerName);
var profile = new SoilProfile1D
{
BottomLevel = -10
};
profile.Layers.Add(soilLayer);
SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[]
{
new Point2D(0, 0),
new Point2D(5, 10),
new Point2D(10, 10)
});
// When Convert to Profile2D
var soilSurfaceProfile = new SoilSurfaceProfile
{
SoilProfile = profile,
SurfaceLine2 = surfaceLine,
DikeEmbankmentMaterial = new Soil
{
Name = topLayerName
}
};
SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D();
// Then SoilProfile2D is created
Assert.Multiple(() =>
{
Assert.That(soilProfile2D.Geometry.Points.Count, Is.EqualTo(9));
Assert.That(soilProfile2D.Geometry.Curves.Count, Is.EqualTo(10));
Assert.That(soilProfile2D.Geometry.Surfaces.Count, Is.EqualTo(2));
Assert.That(soilProfile2D.Geometry.Surfaces[0].OuterLoop.CurveList.Count, Is.EqualTo(6));
Assert.That(soilProfile2D.Geometry.Surfaces[1].OuterLoop.CurveList.Count, Is.EqualTo(6));
Assert.That(soilProfile2D.Geometry.Surfaces[0].OuterLoop.IsContinuous(), Is.True);
Assert.That(soilProfile2D.Geometry.Surfaces[1].OuterLoop.IsContinuous(), Is.True);
Assert.That(soilProfile2D.Geometry.Surfaces[0].OuterLoop.IsClockWise(), Is.True);
Assert.That(soilProfile2D.Geometry.Surfaces[1].OuterLoop.IsClockWise(), Is.True);
});
}
[Test]
public void ConvertToSoilProfile2D_WithSurfaceLineFullyAboveSoilLayers_ReturnsExpectedSoilProfile2D()
{
// Setup
const string bottomLayerName = "BottomLayer";
const string middleLayerName = "MiddleLayer";
const string topLayerName = "TopLayer";
SoilLayer1D bottomLayer = FactoryForSoilProfiles.CreateSoilLayer(-5, bottomLayerName);
SoilLayer1D middleLayer = FactoryForSoilProfiles.CreateSoilLayer(-2, middleLayerName);
var profile = new SoilProfile1D
{
BottomLevel = -10
};
profile.Layers.Add(bottomLayer);
profile.Layers.Add(middleLayer);
SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[]
{
new Point2D(0, 0),
new Point2D(5, 10),
new Point2D(10, 10)
});
var soilSurfaceProfile = new SoilSurfaceProfile
{
SoilProfile = profile,
SurfaceLine2 = surfaceLine,
DikeEmbankmentMaterial = new Soil
{
Name = topLayerName
}
};
// Call
SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D();
// Assert
IList soilLayer2Ds = soilProfile2D.Surfaces;
Assert.That(soilLayer2Ds, Has.Count.EqualTo(3));
SoilLayer2D topSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, topLayerName));
AssertDikeEmbankmentSoilLayerProperties(soilSurfaceProfile, topSoilLayer2D);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(0, 0), new Point2D(5, 10)),
new GeometryCurve(new Point2D(5, 10), new Point2D(10, 10)),
new GeometryCurve(new Point2D(10, 10), new Point2D(10, -2)),
new GeometryCurve(new Point2D(10, -2), new Point2D(5, -2)),
new GeometryCurve(new Point2D(5, -2), new Point2D(0, -2)),
new GeometryCurve(new Point2D(0, -2), new Point2D(0, 0))
}, topSoilLayer2D.GeometrySurface.OuterLoop.CurveList);
SoilLayer2D middleSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, middleLayerName));
AssertSoilLayerProperties(middleLayer, middleSoilLayer2D);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(0, -2), new Point2D(5, -2)),
new GeometryCurve(new Point2D(5, -2), new Point2D(10, -2)),
new GeometryCurve(new Point2D(10, -2), new Point2D(10, -5)),
new GeometryCurve(new Point2D(10, -5), new Point2D(5, -5)),
new GeometryCurve(new Point2D(5, -5), new Point2D(0, -5)),
new GeometryCurve(new Point2D(0, -5), new Point2D(0, -2))
}, middleSoilLayer2D.GeometrySurface.OuterLoop.CurveList);
SoilLayer2D bottomSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName));
AssertSoilLayerProperties(bottomLayer, bottomSoilLayer2D);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(0, -5), new Point2D(5, -5)),
new GeometryCurve(new Point2D(5, -5), new Point2D(10, -5)),
new GeometryCurve(new Point2D(10, -5), new Point2D(10, -10)),
new GeometryCurve(new Point2D(10, -10), new Point2D(5, -10)),
new GeometryCurve(new Point2D(5, -10), new Point2D(0, -10)),
new GeometryCurve(new Point2D(0, -10), new Point2D(0, -5))
}, bottomSoilLayer2D.GeometrySurface.OuterLoop.CurveList);
}
[Test]
public void ConvertToSoilProfile2D_WithLayerFullyAboveSurfaceLine_ReturnsExpectedSoilProfile2D()
{
// Setup
const string bottomLayerName = "BottomLayer";
const string middleLayerName = "MiddleLayer";
const string topLayerName = "TopLayer";
SoilLayer1D irrelevantLayer = FactoryForSoilProfiles.CreateSoilLayer(0, "Does not matter");
SoilLayer1D bottomLayer = FactoryForSoilProfiles.CreateSoilLayer(-5, bottomLayerName);
SoilLayer1D middleLayer = FactoryForSoilProfiles.CreateSoilLayer(-2, middleLayerName);
var profile = new SoilProfile1D
{
BottomLevel = -10
};
profile.Layers.Add(bottomLayer);
profile.Layers.Add(middleLayer);
profile.Layers.Add(irrelevantLayer);
SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[]
{
new Point2D(0, -5),
new Point2D(5, -3),
new Point2D(10, -5)
});
var soilSurfaceProfile = new SoilSurfaceProfile
{
SoilProfile = profile,
SurfaceLine2 = surfaceLine,
DikeEmbankmentMaterial = new Soil
{
Name = topLayerName
}
};
// Call
SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D();
// Assert
IList soilLayer2Ds = soilProfile2D.Surfaces;
Assert.That(soilLayer2Ds, Has.Count.EqualTo(2));
SoilLayer2D middleSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, middleLayerName));
AssertSoilLayerProperties(middleLayer, middleSoilLayer2D);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(0, -5), new Point2D(5, -3)),
new GeometryCurve(new Point2D(5, -3), new Point2D(10, -5)),
new GeometryCurve(new Point2D(10, -5), new Point2D(5, -5)),
new GeometryCurve(new Point2D(5, -5), new Point2D(0, -5))
}, middleSoilLayer2D.GeometrySurface.OuterLoop.CurveList);
SoilLayer2D bottomSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName));
AssertSoilLayerProperties(bottomLayer, bottomSoilLayer2D);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(0, -5), new Point2D(5, -5)),
new GeometryCurve(new Point2D(5, -5), new Point2D(10, -5)),
new GeometryCurve(new Point2D(10, -5), new Point2D(10, -10)),
new GeometryCurve(new Point2D(10, -10), new Point2D(5, -10)),
new GeometryCurve(new Point2D(5, -10), new Point2D(0, -10)),
new GeometryCurve(new Point2D(0, -10), new Point2D(0, -5))
}, bottomSoilLayer2D.GeometrySurface.OuterLoop.CurveList);
}
[Test]
public void ConvertToSoilProfile2D_WithSurfaceLineFullyEnvelopedByTopSoilLayer_ReturnsExpectedSoilProfile2D()
{
// Setup
const string bottomLayerName = "BottomLayer";
const string middleLayerName = "MiddleLayer";
const string topLayerName = "TopLayer";
SoilLayer1D bottomLayer = FactoryForSoilProfiles.CreateSoilLayer(-5, bottomLayerName);
SoilLayer1D middleLayer = FactoryForSoilProfiles.CreateSoilLayer(-2, middleLayerName);
var profile = new SoilProfile1D();
profile.Layers.Add(bottomLayer);
profile.Layers.Add(middleLayer);
profile.BottomLevel = -10;
SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[]
{
new Point2D(0, -4),
new Point2D(5, -2.5),
new Point2D(10, -2.5)
});
var soilSurfaceProfile = new SoilSurfaceProfile
{
SoilProfile = profile,
SurfaceLine2 = surfaceLine,
DikeEmbankmentMaterial = new Soil
{
Name = topLayerName
}
};
// Call
SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D();
// Assert
IList soilLayer2Ds = soilProfile2D.Surfaces;
Assert.That(soilLayer2Ds, Has.Count.EqualTo(2));
SoilLayer2D middleLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, middleLayerName));
AssertSoilLayerProperties(middleLayer, middleLayer2D);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(0, -4), new Point2D(5, -2.5)),
new GeometryCurve(new Point2D(5, -2.5), new Point2D(10, -2.5)),
new GeometryCurve(new Point2D(10, -2.5), new Point2D(10, -5)),
new GeometryCurve(new Point2D(10, -5), new Point2D(5, -5)),
new GeometryCurve(new Point2D(5, -5), new Point2D(0, -5)),
new GeometryCurve(new Point2D(0, -5), new Point2D(0, -4))
}, middleLayer2D.GeometrySurface.OuterLoop.CurveList);
SoilLayer2D bottomLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName));
AssertSoilLayerProperties(bottomLayer, bottomLayer2D);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(0, -5), new Point2D(5, -5)),
new GeometryCurve(new Point2D(5, -5), new Point2D(10, -5)),
new GeometryCurve(new Point2D(10, -5), new Point2D(10, -10)),
new GeometryCurve(new Point2D(10, -10), new Point2D(5, -10)),
new GeometryCurve(new Point2D(5, -10), new Point2D(0, -10)),
new GeometryCurve(new Point2D(0, -10), new Point2D(0, -5))
}, bottomLayer2D.GeometrySurface.OuterLoop.CurveList);
}
[Test]
public void ConvertToSoilProfile2D_WithSurfaceLinePartiallyEnvelopedByTopSoilLayer_ReturnsExpectedSoilProfile2D()
{
// Setup
const string bottomLayerName = "BottomLayer";
const string middleLayerName = "MiddleLayer";
const string topLayerName = "TopLayer";
SoilLayer1D bottomLayer = FactoryForSoilProfiles.CreateSoilLayer(-5, bottomLayerName);
SoilLayer1D middleLayer = FactoryForSoilProfiles.CreateSoilLayer(0, middleLayerName);
var profile = new SoilProfile1D();
profile.Layers.Add(bottomLayer);
profile.Layers.Add(middleLayer);
profile.BottomLevel = -10;
SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[]
{
new Point2D(0, -2.5),
new Point2D(5, 2.5),
new Point2D(10, -2.5)
});
var soilSurfaceProfile = new SoilSurfaceProfile
{
SoilProfile = profile,
SurfaceLine2 = surfaceLine,
DikeEmbankmentMaterial = new Soil
{
Name = topLayerName
}
};
// Call
SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D();
// Assert
IList soilLayer2Ds = soilProfile2D.Surfaces;
Assert.That(soilLayer2Ds, Has.Count.EqualTo(3));
SoilLayer2D topSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, topLayerName));
AssertDikeEmbankmentSoilLayerProperties(soilSurfaceProfile, topSoilLayer2D);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(2.5, 0), new Point2D(5, 2.5)),
new GeometryCurve(new Point2D(5, 2.5), new Point2D(7.5, 0)),
new GeometryCurve(new Point2D(7.5, 0), new Point2D(5, 0)),
new GeometryCurve(new Point2D(5, 0), new Point2D(2.5, 0))
}, topSoilLayer2D.GeometrySurface.OuterLoop.CurveList);
SoilLayer2D middleSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, middleLayerName));
AssertSoilLayerProperties(middleLayer, middleSoilLayer2D);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(0, -2.5), new Point2D(2.5, 0)),
new GeometryCurve(new Point2D(2.5, 0), new Point2D(5, 0)),
new GeometryCurve(new Point2D(5, 0), new Point2D(7.5, 0)),
new GeometryCurve(new Point2D(7.5, 0), new Point2D(10, -2.5)),
new GeometryCurve(new Point2D(10, -2.5), new Point2D(10, -5)),
new GeometryCurve(new Point2D(10, -5), new Point2D(7.5, -5)),
new GeometryCurve(new Point2D(7.5, -5), new Point2D(5, -5)),
new GeometryCurve(new Point2D(5, -5), new Point2D(2.5, -5)),
new GeometryCurve(new Point2D(2.5, -5), new Point2D(0, -5)),
new GeometryCurve(new Point2D(0, -5), new Point2D(0, -2.5))
}, middleSoilLayer2D.GeometrySurface.OuterLoop.CurveList);
SoilLayer2D bottomSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName));
AssertSoilLayerProperties(bottomLayer, bottomSoilLayer2D);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(0, -5), new Point2D(2.5, -5)),
new GeometryCurve(new Point2D(2.5, -5), new Point2D(5, -5)),
new GeometryCurve(new Point2D(5, -5), new Point2D(7.5, -5)),
new GeometryCurve(new Point2D(7.5, -5), new Point2D(10, -5)),
new GeometryCurve(new Point2D(10, -5), new Point2D(10, -10)),
new GeometryCurve(new Point2D(10, -10), new Point2D(7.5, -10)),
new GeometryCurve(new Point2D(7.5, -10), new Point2D(5, -10)),
new GeometryCurve(new Point2D(5, -10), new Point2D(2.5, -10)),
new GeometryCurve(new Point2D(2.5, -10), new Point2D(0, -10)),
new GeometryCurve(new Point2D(0, -10), new Point2D(0, -5))
}, bottomSoilLayer2D.GeometrySurface.OuterLoop.CurveList);
}
[Test]
public void ConvertToSoilProfile2D_WithSurfaceLineIntersectingSoilLayers_ReturnsExpectedSoilProfile()
{
// Setup
const string bottomLayerName = "BottomLayer";
const string middleLayerName = "MiddleLayer";
const string topLayerName = "TopLayer";
SoilLayer1D bottomLayer = FactoryForSoilProfiles.CreateSoilLayer(-1.25, bottomLayerName);
SoilLayer1D middleLayer = FactoryForSoilProfiles.CreateSoilLayer(0, middleLayerName);
var profile = new SoilProfile1D();
profile.Layers.Add(bottomLayer);
profile.Layers.Add(middleLayer);
profile.BottomLevel = -10;
SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[]
{
new Point2D(0, 2.5),
new Point2D(5, -2.5),
new Point2D(10, 2.5)
});
var soilSurfaceProfile = new SoilSurfaceProfile
{
SoilProfile = profile,
SurfaceLine2 = surfaceLine,
DikeEmbankmentMaterial = new Soil
{
Name = topLayerName
}
};
// Call
SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D();
// Assert
IList soilLayer2Ds = soilProfile2D.Surfaces;
Assert.That(soilLayer2Ds, Has.Count.EqualTo(5));
SoilLayer2D[] topSoilLayerSurfaces = soilLayer2Ds.Where(l => string.Equals(l.Name, topLayerName)).ToArray();
Assert.That(topSoilLayerSurfaces.Length, Is.EqualTo(2));
foreach (SoilLayer2D surface in topSoilLayerSurfaces)
{
AssertDikeEmbankmentSoilLayerProperties(soilSurfaceProfile, surface);
}
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(0, 2.5), new Point2D(2.5, 0)),
new GeometryCurve(new Point2D(2.5, 0), new Point2D(0, 0)),
new GeometryCurve(new Point2D(0, 0), new Point2D(0, 2.5))
}, topSoilLayerSurfaces[0].GeometrySurface.OuterLoop.CurveList);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(7.5, 0), new Point2D(10, 2.5)),
new GeometryCurve(new Point2D(10, 2.5), new Point2D(10, 0)),
new GeometryCurve(new Point2D(10, 0), new Point2D(7.5, 0))
}, topSoilLayerSurfaces[1].GeometrySurface.OuterLoop.CurveList);
SoilLayer2D[] middleLayerSurfaces = soilLayer2Ds.Where(l => string.Equals(l.Name, middleLayerName)).ToArray();
Assert.That(middleLayerSurfaces.Length, Is.EqualTo(2));
foreach (SoilLayer2D surface in middleLayerSurfaces)
{
AssertSoilLayerProperties(middleLayer, surface);
}
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(0, 0), new Point2D(2.5, 0)),
new GeometryCurve(new Point2D(2.5, 0), new Point2D(3.75, -1.25)),
new GeometryCurve(new Point2D(3.75, -1.25), new Point2D(2.5, -1.25)),
new GeometryCurve(new Point2D(2.5, -1.25), new Point2D(0, -1.25)),
new GeometryCurve(new Point2D(0, -1.25), new Point2D(0, 0))
}, middleLayerSurfaces[0].GeometrySurface.OuterLoop.CurveList);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(7.5, 0), new Point2D(10, 0)),
new GeometryCurve(new Point2D(10, 0), new Point2D(10, -1.25)),
new GeometryCurve(new Point2D(10, -1.25), new Point2D(7.5, -1.25)),
new GeometryCurve(new Point2D(7.5, -1.25), new Point2D(6.25, -1.25)),
new GeometryCurve(new Point2D(6.25, -1.25), new Point2D(7.5, 0))
}, middleLayerSurfaces[1].GeometrySurface.OuterLoop.CurveList);
SoilLayer2D bottomLayerSurface = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName));
AssertSoilLayerProperties(bottomLayer, bottomLayerSurface);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(0, -1.25), new Point2D(2.5, -1.25)),
new GeometryCurve(new Point2D(2.5, -1.25), new Point2D(3.75, -1.25)),
new GeometryCurve(new Point2D(3.75, -1.25), new Point2D(5, -2.5)),
new GeometryCurve(new Point2D(5, -2.5), new Point2D(6.25, -1.25)),
new GeometryCurve(new Point2D(6.25, -1.25), new Point2D(7.5, -1.25)),
new GeometryCurve(new Point2D(7.5, -1.25), new Point2D(10, -1.25)),
new GeometryCurve(new Point2D(10, -1.25), new Point2D(10, -10)),
new GeometryCurve(new Point2D(10, -10), new Point2D(7.5, -10)),
new GeometryCurve(new Point2D(7.5, -10), new Point2D(6.25, -10)),
new GeometryCurve(new Point2D(6.25, -10), new Point2D(5, -10)),
new GeometryCurve(new Point2D(5, -10), new Point2D(3.75, -10)),
new GeometryCurve(new Point2D(3.75, -10), new Point2D(2.5, -10)),
new GeometryCurve(new Point2D(2.5, -10), new Point2D(0, -10)),
new GeometryCurve(new Point2D(0, -10), new Point2D(0, -1.25))
}, bottomLayerSurface.GeometrySurface.OuterLoop.CurveList);
}
[Test]
public void ConvertToSoilProfile2D_WithSurfaceLineIntersectingSoilLayerAndInflectionAtBottomIntersection_ReturnsExpectedSoilProfile()
{
// Setup
const string bottomLayerName = "BottomLayer";
const string middleLayerName = "MiddleLayer";
const string topLayerName = "TopLayer";
SoilLayer1D bottomLayer = FactoryForSoilProfiles.CreateSoilLayer(-2.5, bottomLayerName);
SoilLayer1D middleLayer = FactoryForSoilProfiles.CreateSoilLayer(0, middleLayerName);
var profile = new SoilProfile1D();
profile.Layers.Add(bottomLayer);
profile.Layers.Add(middleLayer);
profile.BottomLevel = -10;
SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[]
{
new Point2D(0, 2.5),
new Point2D(5, -2.5),
new Point2D(10, 2.5)
});
var soilSurfaceProfile = new SoilSurfaceProfile
{
SoilProfile = profile,
SurfaceLine2 = surfaceLine,
DikeEmbankmentMaterial = new Soil
{
Name = topLayerName
}
};
// Call
SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D();
// Assert
IList soilLayer2Ds = soilProfile2D.Surfaces;
Assert.That(soilLayer2Ds, Has.Count.EqualTo(5));
SoilLayer2D[] topSoilLayerSurfaces = soilLayer2Ds.Where(l => string.Equals(l.Name, topLayerName)).ToArray();
Assert.That(topSoilLayerSurfaces.Length, Is.EqualTo(2));
foreach (SoilLayer2D surface in topSoilLayerSurfaces)
{
AssertDikeEmbankmentSoilLayerProperties(soilSurfaceProfile, surface);
}
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(0, 2.5), new Point2D(2.5, 0)),
new GeometryCurve(new Point2D(2.5, 0), new Point2D(0, 0)),
new GeometryCurve(new Point2D(0, 0), new Point2D(0, 2.5))
}, topSoilLayerSurfaces[0].GeometrySurface.OuterLoop.CurveList);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(7.5, 0), new Point2D(10, 2.5)),
new GeometryCurve(new Point2D(10, 2.5), new Point2D(10, 0)),
new GeometryCurve(new Point2D(10, 0), new Point2D(7.5, 0))
}, topSoilLayerSurfaces[1].GeometrySurface.OuterLoop.CurveList);
SoilLayer2D[] middleLayerSurfaces = soilLayer2Ds.Where(l => string.Equals(l.Name, middleLayerName)).ToArray();
Assert.That(middleLayerSurfaces.Length, Is.EqualTo(2));
foreach (SoilLayer2D surface in middleLayerSurfaces)
{
AssertSoilLayerProperties(middleLayer, surface);
}
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(0, 0), new Point2D(2.5, 0)),
new GeometryCurve(new Point2D(2.5, 0), new Point2D(5, -2.5)),
new GeometryCurve(new Point2D(5, -2.5), new Point2D(2.5, -2.5)),
new GeometryCurve(new Point2D(2.5, -2.5), new Point2D(0, -2.5)),
new GeometryCurve(new Point2D(0, -2.5), new Point2D(0, 0))
}, middleLayerSurfaces[0].GeometrySurface.OuterLoop.CurveList);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(7.5, 0), new Point2D(10, 0)),
new GeometryCurve(new Point2D(10, 0), new Point2D(10, -2.5)),
new GeometryCurve(new Point2D(10, -2.5), new Point2D(7.5, -2.5)),
new GeometryCurve(new Point2D(7.5, -2.5), new Point2D(5, -2.5)),
new GeometryCurve(new Point2D(5, -2.5), new Point2D(7.5, 0))
}, middleLayerSurfaces[1].GeometrySurface.OuterLoop.CurveList);
SoilLayer2D bottomLayerSurface = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName));
AssertSoilLayerProperties(bottomLayer, bottomLayerSurface);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(0, -2.5), new Point2D(2.5, -2.5)),
new GeometryCurve(new Point2D(2.5, -2.5), new Point2D(5, -2.5)),
new GeometryCurve(new Point2D(5, -2.5), new Point2D(7.5, -2.5)),
new GeometryCurve(new Point2D(7.5, -2.5), new Point2D(10, -2.5)),
new GeometryCurve(new Point2D(10, -2.5), new Point2D(10, -10)),
new GeometryCurve(new Point2D(10, -10), new Point2D(7.5, -10)),
new GeometryCurve(new Point2D(7.5, -10), new Point2D(5, -10)),
new GeometryCurve(new Point2D(5, -10), new Point2D(2.5, -10)),
new GeometryCurve(new Point2D(2.5, -10), new Point2D(0, -10)),
new GeometryCurve(new Point2D(0, -10), new Point2D(0, -2.5))
}, bottomLayerSurface.GeometrySurface.OuterLoop.CurveList);
}
[Test]
public void ConvertToSoilProfile2D_WithSurfaceLineIntersectingSoilLayerAndHorizontalLineAtBottomIntersection_ReturnsExpectedSoilProfile()
{
// Setup
const string bottomLayerName = "BottomLayer";
const string middleLayerName = "MiddleLayer";
const string topLayerName = "TopLayer";
SoilLayer1D bottomLayer = FactoryForSoilProfiles.CreateSoilLayer(-2.5, bottomLayerName);
SoilLayer1D middleLayer = FactoryForSoilProfiles.CreateSoilLayer(0, middleLayerName);
var profile = new SoilProfile1D();
profile.Layers.Add(bottomLayer);
profile.Layers.Add(middleLayer);
profile.BottomLevel = -10;
SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[]
{
new Point2D(0, 2.5),
new Point2D(5, -2.5),
new Point2D(10, -2.5),
new Point2D(15, 2.5)
});
var soilSurfaceProfile = new SoilSurfaceProfile
{
SoilProfile = profile,
SurfaceLine2 = surfaceLine,
DikeEmbankmentMaterial = new Soil
{
Name = topLayerName
}
};
// Call
SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D();
// Assert
IList soilLayer2Ds = soilProfile2D.Surfaces;
Assert.That(soilLayer2Ds, Has.Count.EqualTo(5));
SoilLayer2D[] topSoilLayerSurfaces = soilLayer2Ds.Where(l => string.Equals(l.Name, topLayerName)).ToArray();
Assert.That(topSoilLayerSurfaces.Length, Is.EqualTo(2));
foreach (SoilLayer2D surface in topSoilLayerSurfaces)
{
AssertDikeEmbankmentSoilLayerProperties(soilSurfaceProfile, surface);
}
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(0, 2.5), new Point2D(2.5, 0)),
new GeometryCurve(new Point2D(2.5, 0), new Point2D(0, 0)),
new GeometryCurve(new Point2D(0, 0), new Point2D(0, 2.5))
}, topSoilLayerSurfaces[0].GeometrySurface.OuterLoop.CurveList);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(12.5, 0), new Point2D(15, 2.5)),
new GeometryCurve(new Point2D(15, 2.5), new Point2D(15, 0)),
new GeometryCurve(new Point2D(15, 0), new Point2D(12.5, 0))
}, topSoilLayerSurfaces[1].GeometrySurface.OuterLoop.CurveList);
SoilLayer2D[] middleLayerSurfaces = soilLayer2Ds.Where(l => string.Equals(l.Name, middleLayerName)).ToArray();
Assert.That(middleLayerSurfaces.Length, Is.EqualTo(2));
foreach (SoilLayer2D surface in middleLayerSurfaces)
{
AssertSoilLayerProperties(middleLayer, surface);
}
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(0, 0), new Point2D(2.5, 0)),
new GeometryCurve(new Point2D(2.5, 0), new Point2D(5, -2.5)),
new GeometryCurve(new Point2D(5, -2.5), new Point2D(2.5, -2.5)),
new GeometryCurve(new Point2D(2.5, -2.5), new Point2D(0, -2.5)),
new GeometryCurve(new Point2D(0, -2.5), new Point2D(0, 0))
}, middleLayerSurfaces[0].GeometrySurface.OuterLoop.CurveList);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(12.5, 0), new Point2D(15, 0)),
new GeometryCurve(new Point2D(15, 0), new Point2D(15, -2.5)),
new GeometryCurve(new Point2D(15, -2.5), new Point2D(12.5, -2.5)),
new GeometryCurve(new Point2D(12.5, -2.5), new Point2D(10, -2.5)),
new GeometryCurve(new Point2D(10, -2.5), new Point2D(12.5, 0))
}, middleLayerSurfaces[1].GeometrySurface.OuterLoop.CurveList);
SoilLayer2D bottomLayerSurface = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName));
AssertSoilLayerProperties(bottomLayer, bottomLayerSurface);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(0, -2.5), new Point2D(2.5, -2.5)),
new GeometryCurve(new Point2D(2.5, -2.5), new Point2D(5, -2.5)),
new GeometryCurve(new Point2D(5, -2.5), new Point2D(10, -2.5)),
new GeometryCurve(new Point2D(10, -2.5), new Point2D(12.5, -2.5)),
new GeometryCurve(new Point2D(12.5, -2.5), new Point2D(15, -2.5)),
new GeometryCurve(new Point2D(15, -2.5), new Point2D(15, -10)),
new GeometryCurve(new Point2D(15, -10), new Point2D(12.5, -10)),
new GeometryCurve(new Point2D(12.5, -10), new Point2D(10, -10)),
new GeometryCurve(new Point2D(10, -10), new Point2D(5, -10)),
new GeometryCurve(new Point2D(5, -10), new Point2D(2.5, -10)),
new GeometryCurve(new Point2D(2.5, -10), new Point2D(0, -10)),
new GeometryCurve(new Point2D(0, -10), new Point2D(0, -2.5))
}, bottomLayerSurface.GeometrySurface.OuterLoop.CurveList);
}
[Test]
public void ConvertToSoilProfile2D_WithSurfaceLineStartingHorizontallyAtBottomLayer_ReturnsExpectedSoilProfile()
{
// Setup
const string bottomLayerName = "BottomLayer";
const string middleLayerName = "MiddleLayer";
const string topLayerName = "TopLayer";
SoilLayer1D bottomLayer = FactoryForSoilProfiles.CreateSoilLayer(-2.5, bottomLayerName);
SoilLayer1D middleLayer = FactoryForSoilProfiles.CreateSoilLayer(0, middleLayerName);
var profile = new SoilProfile1D();
profile.Layers.Add(bottomLayer);
profile.Layers.Add(middleLayer);
profile.BottomLevel = -10;
SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[]
{
new Point2D(0, -2.5),
new Point2D(5, -2.5),
new Point2D(10, 2.5),
new Point2D(15, -2.5),
new Point2D(20, -2.5)
});
var soilSurfaceProfile = new SoilSurfaceProfile
{
SoilProfile = profile,
SurfaceLine2 = surfaceLine,
DikeEmbankmentMaterial = new Soil
{
Name = topLayerName
}
};
// Call
SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D();
// Assert
IList soilLayer2Ds = soilProfile2D.Surfaces;
SoilLayer2D topSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, topLayerName));
AssertDikeEmbankmentSoilLayerProperties(soilSurfaceProfile, topSoilLayer2D);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(7.5, 0), new Point2D(10, 2.5)),
new GeometryCurve(new Point2D(10, 2.5), new Point2D(12.5, 0)),
new GeometryCurve(new Point2D(12.5, 0), new Point2D(10, 0)),
new GeometryCurve(new Point2D(10, 0), new Point2D(7.5, 0))
}, topSoilLayer2D.GeometrySurface.OuterLoop.CurveList);
SoilLayer2D middleSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, middleLayerName));
AssertSoilLayerProperties(middleLayer, middleSoilLayer2D);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(5, -2.5), new Point2D(7.5, 0)),
new GeometryCurve(new Point2D(7.5, 0), new Point2D(10, 0)),
new GeometryCurve(new Point2D(10, 0), new Point2D(12.5, 0)),
new GeometryCurve(new Point2D(12.5, 0), new Point2D(15, -2.5)),
new GeometryCurve(new Point2D(15, -2.5), new Point2D(12.5, -2.5)),
new GeometryCurve(new Point2D(12.5, -2.5), new Point2D(10, -2.5)),
new GeometryCurve(new Point2D(10, -2.5), new Point2D(7.5, -2.5)),
new GeometryCurve(new Point2D(7.5, -2.5), new Point2D(5, -2.5))
}, middleSoilLayer2D.GeometrySurface.OuterLoop.CurveList);
SoilLayer2D bottomSoilLayer2D = soilLayer2Ds.Single(l => string.Equals(l.Name, bottomLayerName));
AssertSoilLayerProperties(bottomLayer, bottomSoilLayer2D);
AssertGeometry(new[]
{
new GeometryCurve(new Point2D(0, -2.5), new Point2D(5, -2.5)),
new GeometryCurve(new Point2D(5, -2.5), new Point2D(7.5, -2.5)),
new GeometryCurve(new Point2D(7.5, -2.5), new Point2D(10, -2.5)),
new GeometryCurve(new Point2D(10, -2.5), new Point2D(12.5, -2.5)),
new GeometryCurve(new Point2D(12.5, -2.5), new Point2D(15, -2.5)),
new GeometryCurve(new Point2D(15, -2.5), new Point2D(20, -2.5)),
new GeometryCurve(new Point2D(20, -2.5), new Point2D(20, -10)),
new GeometryCurve(new Point2D(20, -10), new Point2D(15, -10)),
new GeometryCurve(new Point2D(15, -10), new Point2D(12.5, -10)),
new GeometryCurve(new Point2D(12.5, -10), new Point2D(10, -10)),
new GeometryCurve(new Point2D(10, -10), new Point2D(7.5, -10)),
new GeometryCurve(new Point2D(7.5, -10), new Point2D(5, -10)),
new GeometryCurve(new Point2D(5, -10), new Point2D(0, -10)),
new GeometryCurve(new Point2D(0, -10), new Point2D(0, -2.5))
}, bottomSoilLayer2D.GeometrySurface.OuterLoop.CurveList);
}
///
/// This test reproduces the problem found in MWDAM-2514 where the ditch was incorrectly filled in.
/// This is due to the small vertical distance between the surface line point (32.125, -2.451) and the bottom level of
/// layer H_MDp_k (-2.45) which led to consider that the point was part of the layer and therefore to create a curve
/// closing the ditch.
/// Expected is that only 5 layers are created, not 6.
///
[Test]
public void GivenSurfaceLineWithDitch_WhenConvertingToSoilProfile2D_ReturnsExpectedSoilProfile()
{
// Setup
const string layer1Name = "H_MDp_k";
const string layer2Name = "H_MDg_zf";
const string layer3Name = "H_Vhv_vo";
SoilLayer1D layer1 = FactoryForSoilProfiles.CreateSoilLayer(-1.78, layer1Name);
SoilLayer1D layer2 = FactoryForSoilProfiles.CreateSoilLayer(-2.45, layer2Name);
SoilLayer1D layer3 = FactoryForSoilProfiles.CreateSoilLayer(-2.95, layer3Name);
var profile = new SoilProfile1D();
profile.Layers.Add(layer1);
profile.Layers.Add(layer2);
profile.Layers.Add(layer3);
profile.BottomLevel = -4.3;
SurfaceLine2 surfaceLine = FactoryForSoilProfiles.CreateSurfaceLine(new[]
{
new Point2D(0, -1.78),
new Point2D(26, -1.78),
new Point2D(31.775, -2.443),
new Point2D(32.125, -2.451),
new Point2D(34.575, -2.544),
new Point2D(35, -3.130),
new Point2D(37, -3.130),
new Point2D(38.775, -2.479),
new Point2D(39.125, -2.445),
new Point2D(48.575, -2.156)
});
var soilSurfaceProfile = new SoilSurfaceProfile
{
SoilProfile = profile,
SurfaceLine2 = surfaceLine,
DikeEmbankmentMaterial = new Soil()
};
// Call
SoilProfile2D soilProfile2D = soilSurfaceProfile.ConvertToSoilProfile2D();
// Assert
IList soilLayer2Ds = soilProfile2D.Surfaces;
Assert.That(soilLayer2Ds, Has.Count.EqualTo(5));
Assert.Multiple(() =>
{
Assert.That(soilLayer2Ds[0].SoilName, Is.EqualTo(layer1Name));
Assert.That(soilLayer2Ds[1].SoilName, Is.EqualTo(layer2Name));
Assert.That(soilLayer2Ds[2].SoilName, Is.EqualTo(layer1Name));
Assert.That(soilLayer2Ds[3].SoilName, Is.EqualTo(layer2Name));
Assert.That(soilLayer2Ds[4].SoilName, Is.EqualTo(layer3Name));
});
}
private static void AssertGeometry(IEnumerable expectedCurves, IEnumerable actualCurves)
{
int nrOfExpectedCurves = expectedCurves.Count();
Assert.That(actualCurves.Count(), Is.EqualTo(nrOfExpectedCurves));
IEnumerable actualCurveString = actualCurves.Select(c => $"Coordinate ({c.HeadPoint.X}, {c.HeadPoint.Z}) --> ({c.EndPoint.X}, {c.EndPoint.Z})");
foreach (GeometryCurve expectedCurve in expectedCurves)
{
Assert.That(actualCurves.Any(c => c.LocationEquals(expectedCurve)), Is.True,
$"Expected curve ({expectedCurve.HeadPoint.X}, {expectedCurve.HeadPoint.Z}) --> ({expectedCurve.EndPoint.X}, {expectedCurve.EndPoint.Z}) not found. " +
$"Actual curves {string.Join(", ", actualCurveString)}");
}
}
private static void AssertSoilLayerProperties(SoilLayer1D expectedLayer,
SoilLayer2D actualSoilLayer)
{
Assert.That(actualSoilLayer.IsAquifer, Is.EqualTo(expectedLayer.IsAquifer));
Assert.That(actualSoilLayer.WaterpressureInterpolationModel, Is.EqualTo(expectedLayer.WaterpressureInterpolationModel));
Assert.That(actualSoilLayer.Soil, Is.SameAs(expectedLayer.Soil));
}
private static void AssertDikeEmbankmentSoilLayerProperties(SoilSurfaceProfile expectedProfile,
SoilLayer2D actualSoilLayer)
{
Assert.That(actualSoilLayer.IsAquifer, Is.False);
Assert.That(actualSoilLayer.WaterpressureInterpolationModel, Is.EqualTo(WaterpressureInterpolationModel.Hydrostatic));
Assert.That(actualSoilLayer.Soil, Is.SameAs(expectedProfile.DikeEmbankmentMaterial));
}
}