// 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;
using System.Collections.Generic;
using System.Linq;
using Deltares.DamEngine.Data.General;
using Deltares.DamEngine.Data.Geometry;
using Deltares.DamEngine.Data.Geotechnics;
using Deltares.DamEngine.Data.Standard;
namespace Deltares.DamEngine.TestHelpers.Factories;
///
/// To indicate the position of the surface line to the soil profile.
///
public enum PositionToSoilProfile2D
{
LeftOfSoilProfile,
RightOfSoilProfile,
OnSoilProfile,
InsideOfSoilProfile
}
public static class FactoryForSoilProfiles
{
///
/// Create simple soil profile
///
/// soil profile
public static SoilProfile1D CreateSimpleProfile()
{
var soilProfile = new SoilProfile1D();
var layer = new SoilLayer1D();
layer.TopLevel = 10.0;
layer.Soil = new Soil("Clay", 16.0, 12.0);
layer.IsAquifer = false;
soilProfile.Layers.Add(layer);
soilProfile.BottomLevel = -20.0;
return soilProfile;
}
///
/// Create two layer soilprofile
///
/// soil profile
public static SoilProfile1D CreateTwoLayerProfile()
{
var soilProfile = new SoilProfile1D();
var layer = new SoilLayer1D();
layer.TopLevel = 10.0;
layer.Soil = new Soil("HW-OBO", 12.0, 10.0);
layer.IsAquifer = false;
layer.WaterpressureInterpolationModel = WaterpressureInterpolationModel.Automatic;
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D();
layer.TopLevel = 2.0;
layer.Soil = new Soil("Alg-zand (0-30)", 22.0, 20.0);
layer.IsAquifer = true;
layer.WaterpressureInterpolationModel = WaterpressureInterpolationModel.Hydrostatic;
soilProfile.Layers.Add(layer);
soilProfile.BottomLevel = -10.0;
return soilProfile;
}
///
/// Create two layer soil profile with pleistocene sand layer only
///
/// soil profile
public static SoilProfile1D CreateClaySandProfile(out SoilList soilList, double topLevelClayLayer = 10, double topLevelSandLayer = -5)
{
var soilProfile = new SoilProfile1D();
var soil1 = new Soil("HW-OBO", 12.0, 10.0);
var soil2 = new Soil("Alg-zand (0-30)", 22.0, 20.0);
soilList = new SoilList();
soilList.Add(soil1);
soilList.Add(soil2);
var layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = topLevelClayLayer;
layer.Soil = soil1;
layer.IsAquifer = false;
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = topLevelSandLayer;
layer.Soil = soil2;
layer.IsAquifer = true;
soilProfile.Layers.Add(layer);
soilProfile.BottomLevel = -10.0;
return soilProfile;
}
///
/// Gammadry and Gammywet are both set to 1 for testing purposes
///
/// soil profile
public static SoilProfile1D CreateClaySandClaySandProfileForPipingBligh()
{
SoilProfile1D soilProfile = CreateClaySandClaySandProfile();
foreach (SoilLayer1D layer in soilProfile.Layers)
{
layer.Soil.BelowPhreaticLevel = 1;
layer.Soil.AbovePhreaticLevel = 1;
layer.Soil.DiameterD70 = 0.00018;
}
return soilProfile;
}
///
/// Creates the clay sand profile for piping bligh.
///
/// soil profile
public static SoilProfile1D CreateClaySandProfileForPipingBligh(out SoilList soilList)
{
SoilProfile1D soilProfile = CreateClaySandProfile(out soilList);
foreach (SoilLayer1D layer in soilProfile.Layers)
{
layer.Soil.BelowPhreaticLevel = 1;
layer.Soil.AbovePhreaticLevel = 1;
layer.Soil.DiameterD70 = 0.00018;
}
return soilProfile;
}
///
/// Create four layer soil profile with pleistocene and intermediate sand layer
///
/// soil profile
public static SoilProfile1D CreateClaySandClaySandProfile(double topClay1 = 10.0, double topSand1 = 1.0, double topClay2 = -1.5, double topSand2 = -5.0)
{
var soilProfile = new SoilProfile1D();
var layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = topClay1;
layer.Soil = new Soil("HW-OBO", 12.0, 10.0);
layer.IsAquifer = false;
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = topSand1;
layer.Soil = new Soil("Alg-zand (0-30)", 22.0, 20.0);
layer.IsAquifer = true;
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = topClay2;
layer.Soil = new Soil("HW-DUN", 16.8, 15.8);
layer.IsAquifer = false;
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = topSand2;
layer.Soil = new Soil("Alg-zand (0-30)", 22.0, 20.0);
layer.IsAquifer = true;
soilProfile.Layers.Add(layer);
soilProfile.BottomLevel = -10.0;
return soilProfile;
}
///
/// Create six layer soil profile with 3 aquifers
///
/// soil profile
public static SoilProfile1D CreateClaySandClaySandClaySandProfile(double level1 = 10, double level2 = 1, double level3 = -1.5, double level4 = -5, double level5 = -7, double level6 = -5)
{
var soilProfile = new SoilProfile1D();
var layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = level1;
layer.Soil = new Soil("HW-OBO", 12.0, 10.0);
layer.IsAquifer = false;
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = level2;
layer.Soil = new Soil("Alg-zand (0-30)", 22.0, 20.0);
layer.IsAquifer = true;
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = level3;
layer.Soil = new Soil("HW-DUN", 16.8, 15.8);
layer.IsAquifer = false;
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = level4;
layer.Soil = new Soil("Alg-zand (0-30)", 22.0, 20.0);
layer.IsAquifer = true;
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = level5;
layer.Soil = new Soil("HW-DUN", 16.8, 15.8);
layer.IsAquifer = false;
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = level6;
layer.Soil = new Soil("Alg-zand (0-30)", 22.0, 20.0);
layer.IsAquifer = true;
soilProfile.Layers.Add(layer);
soilProfile.BottomLevel = level6 - 10;
return soilProfile;
}
///
/// Create 4 layers soil profile with 1 aquifer at the bottom
///
/// soil profile
public static SoilProfile1D Create4LayersProfileWith1BottomAquifer(double level1 = 0.0, double level2 = -5.0, double level3 = -10.0, double level4 = -15.0, double bottomLevel5 = -20.0, bool isInBetweenAquiferPresent = false)
{
var soilProfile = new SoilProfile1D();
var layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile),
TopLevel = level1,
IsAquifer = false
};
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile),
TopLevel = level2,
IsAquifer = isInBetweenAquiferPresent
};
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile),
TopLevel = level3,
IsAquifer = false
};
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile),
TopLevel = level4,
IsAquifer = true
};
soilProfile.Layers.Add(layer);
soilProfile.BottomLevel = bottomLevel5;
return soilProfile;
}
///
/// Create four layer soil profile with pleistocene and intermediate sand layer with multiple infiltration layers
///
/// soil profile
public static SoilProfile1D CreateMultiInfiltrationLayerProfile()
{
var soilProfile = new SoilProfile1D();
var layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = 10.0;
layer.Soil = new Soil("HW-OBO", 12.0, 10.0);
layer.IsAquifer = false;
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = 1.0;
layer.Soil = new Soil("Alg-zand (0-30)", 22.0, 20.0);
layer.IsAquifer = true;
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = -1.5;
layer.Soil = new Soil("HW-DUN", 16.8, 15.8);
layer.IsAquifer = false;
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = -2.3;
layer.Soil = new Soil("HW-OBO", 12.0, 10.0);
layer.IsAquifer = false;
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = -3.2;
layer.Soil = new Soil("HW-DUN", 16.8, 15.8);
layer.IsAquifer = false;
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = -4.1;
layer.Soil = new Soil("HW-OBO", 12.0, 10.0);
layer.IsAquifer = false;
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = -5.0;
layer.Soil = new Soil("Alg-zand (0-30)", 22.0, 20.0);
layer.IsAquifer = true;
soilProfile.Layers.Add(layer);
soilProfile.BottomLevel = -10.0;
return soilProfile;
}
///
/// Create complex soilprofile
///
/// soil profile
public static SoilProfile1D CreateComplexProfile()
{
var soilProfile = new SoilProfile1D();
var layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = 10.0;
layer.Soil = new Soil("HW-OBO", 16.8, 15.8);
layer.IsAquifer = false;
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = -0.6;
layer.Soil = new Soil("HW-DUN", 16.8, 15.8);
layer.IsAquifer = false;
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = -1.8;
layer.Soil = new Soil("HW-DUOzand", 18.7, 17.7);
layer.IsAquifer = true;
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = -2.8;
layer.Soil = new Soil("HW-HVN", 11.4, 10.4);
layer.IsAquifer = false;
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = -4.0;
layer.Soil = new Soil("HW-HVN", 11.40, 10.40);
layer.IsAquifer = false;
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile)
};
layer.TopLevel = -5.0;
layer.Soil = new Soil("Alg-zand (0-30)", 19.0, 18.0);
layer.IsAquifer = true;
soilProfile.Layers.Add(layer);
soilProfile.BottomLevel = -10.0;
return soilProfile;
}
///
/// Create two layer soil profile with pleistocene sand layer (no intermediate layer)
///
/// soil profile
public static SoilProfile1D CreatePipingSellmeijerProfileWithOneSandLayer(out SoilList soilList)
{
var soilProfile = new SoilProfile1D();
var topMaterial = new Soil("Topmaterial", 14, 11)
{
PermeabKx = 0.0003,
DiameterD70 = Physics.FactorMicroMeterToMeter * 300.0
};
var sand = new Soil("Sand", 22.0, 20.0)
{
PermeabKx = 0.0001,
DiameterD70 = Physics.FactorMicroMeterToMeter * 200.0
};
soilList = new SoilList();
soilList.Add(topMaterial);
soilList.Add(sand);
var layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile),
TopLevel = 10.0,
Soil = topMaterial,
IsAquifer = false
};
soilProfile.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = GetNewUniqueLayerId(soilProfile),
TopLevel = -2.0,
Soil = sand,
IsAquifer = true
};
soilProfile.Layers.Add(layer);
soilProfile.BottomLevel = -10.0;
return soilProfile;
}
///
/// Create a soil layer with the given top level and soil name
///
/// The toplevel.
/// The soil name
///
public static SoilLayer1D CreateSoilLayer(double topLevel, string soilName)
{
var random = new Random(soilName.GetHashCode());
Array values = Enum.GetValues(typeof(WaterpressureInterpolationModel));
var model = (WaterpressureInterpolationModel) values.GetValue(random.Next(values.Length));
return new SoilLayer1D
{
TopLevel = topLevel,
Soil = new Soil(soilName),
IsAquifer = Convert.ToBoolean(random.Next(0, 2)),
WaterpressureInterpolationModel = model
};
}
///
/// Create a surface line with the given coordinates
///
///
///
public static SurfaceLine2 CreateSurfaceLine(IEnumerable coordinates)
{
var surfaceLine = new SurfaceLine2();
surfaceLine.Geometry.Points.AddRange(coordinates);
return surfaceLine;
}
///
/// Create a soil profile 2D with two layers
///
/// The 2D Soil Profile
public static SoilProfile2D CreateSoilProfile2DWithTwoLayers()
{
const string layerName = "Layer";
const string topLayerName = "TopLayer";
SoilLayer1D soilLayer = CreateSoilLayer(-5, layerName);
var profile = new SoilProfile1D
{
BottomLevel = -10
};
profile.Layers.Add(soilLayer);
SurfaceLine2 surfaceLine = CreateSurfaceLine(new[]
{
new Point2D(0, 0),
new Point2D(5, 10),
new Point2D(10, 10)
});
SoilProfile2D soilProfile2D = CreateSoilProfile2DBasedOnSoilProfile1D(profile, surfaceLine);
return soilProfile2D;
}
///
/// Creates 2D SoilProfile with three layers
///
/// The 2D Soil Profile
public static SoilProfile2D CreateSoilProfile2DWithThreeLayers()
{
const string layer1Name = "Layer1";
const string layer2Name = "Layer2";
const string topLayerName = "TopLayer";
SoilLayer1D soilLayer1 = CreateSoilLayer(-8, layer1Name);
SoilLayer1D soilLayer2 = CreateSoilLayer(-5, layer2Name);
var profile = new SoilProfile1D
{
BottomLevel = -10
};
profile.Layers.Add(soilLayer1);
profile.Layers.Add(soilLayer2);
SurfaceLine2 surfaceLine = CreateSurfaceLine(new[]
{
new Point2D(0, 0),
new Point2D(5, 10),
new Point2D(10, 10)
});
SoilProfile2D soilProfile2D = CreateSoilProfile2DBasedOnSoilProfile1D(profile, surfaceLine);
// Make one boundary not horizontal
soilProfile2D.Geometry.Points[4].Z = 0.0;
return soilProfile2D;
}
///
/// -50 -30 -10 10 40 50
/// |---------------------------------------------------| Level 10 m
/// | surface 1 |
/// | |---------------| |---------------| | Level 0 m
/// | | surface 2 | | surface 3 | |
/// | |-------------- | |---------------| | Level -10 m
/// | surface 1 |
/// |---------------------------------------------------| Level -20 m
///
public static SoilProfile2D CreateSoilProfile2DWithThreeLayersOfWhichTwoAreInnerLoops()
{
var soilProfile2D = new SoilProfile2D
{
Geometry = new GeometryData
{
Left = -50,
Right = 50,
Bottom = -20
}
};
var soil1 = new Soil("Soil1", 11, 12);
var soil2 = new Soil("Soil2", 13, 14);
var soil3 = new Soil("Soil3", 13.1, 14.1);
SoilLayer2D soilLayer1 = CreateRectangularSoilLayer2D(10, -20, -50, 50, soilProfile2D, soil1);
SoilLayer2D soilLayer2 = CreateRectangularSoilLayer2D(0, -10, -30, -10, soilProfile2D, soil2);
SoilLayer2D soilLayer3 = CreateRectangularSoilLayer2D(0, -10, 10, 40, soilProfile2D, soil3);
soilProfile2D.Surfaces.Add(soilLayer1);
soilProfile2D.Surfaces.Add(soilLayer2);
soilProfile2D.Surfaces.Add(soilLayer3);
soilProfile2D.Geometry.Loops.Add(soilLayer1.GeometrySurface.OuterLoop);
soilProfile2D.Geometry.Surfaces.Add(soilLayer1.GeometrySurface);
soilProfile2D.Geometry.Loops.Add(soilLayer2.GeometrySurface.OuterLoop);
soilProfile2D.Geometry.Surfaces.Add(soilLayer2.GeometrySurface);
soilProfile2D.Geometry.Loops.Add(soilLayer3.GeometrySurface.OuterLoop);
soilProfile2D.Geometry.Surfaces.Add(soilLayer3.GeometrySurface);
soilProfile2D.Geometry.Surfaces[0].InnerLoops.Add(soilLayer2.GeometrySurface.OuterLoop);
soilProfile2D.Geometry.Surfaces[0].InnerLoops.Add(soilLayer3.GeometrySurface.OuterLoop);
return soilProfile2D;
}
///
/// -50 -40 -30 0 10 30 40 50
/// |-----------------------------------------------| Level 10 m
/// | surface 1 |
/// | |---------------|---------------| | Level 0 m
/// | | surface 2 | surface 3 | |
/// | |------------------|------------------| | Level -10 m
/// | surface 1 |
/// |-----------------------------------------------| Level -20 m
///
public static SoilProfile2D CreateSoilProfile2DWithThreeLayersOfWhichTwoAreConnectedInnerLoops()
{
var soilProfile2D = new SoilProfile2D
{
Geometry = new GeometryData
{
Left = -50,
Right = 50,
Bottom = -20
}
};
var soil1 = new Soil("Soil1", 11, 12);
var soil2 = new Soil("Soil2", 13, 14);
var soil3 = new Soil("Soil3", 13.1, 14.1);
SoilLayer2D soilLayer1 = CreateRectangularSoilLayer2D(10, -20, -50, 50, soilProfile2D, soil1);
SoilLayer2D soilLayer2 = CreateRectangularSoilLayer2D(0, -10, -40, 0, soilProfile2D, soil2);
SoilLayer2D soilLayer3 = CreateRectangularSoilLayer2D(0, -10, 0, 40, soilProfile2D, soil3);
soilProfile2D.Geometry.GetPointAtLocation(new Point2D(-40, 0)).X = -30;
soilProfile2D.Geometry.GetPointAtLocation(new Point2D(40, 0)).X = 30;
soilProfile2D.Surfaces.Add(soilLayer1);
soilProfile2D.Surfaces.Add(soilLayer2);
soilProfile2D.Surfaces.Add(soilLayer3);
soilProfile2D.Geometry.Loops.Add(soilLayer1.GeometrySurface.OuterLoop);
soilProfile2D.Geometry.Surfaces.Add(soilLayer1.GeometrySurface);
soilProfile2D.Geometry.Loops.Add(soilLayer2.GeometrySurface.OuterLoop);
soilProfile2D.Geometry.Surfaces.Add(soilLayer2.GeometrySurface);
soilProfile2D.Geometry.Loops.Add(soilLayer3.GeometrySurface.OuterLoop);
soilProfile2D.Geometry.Surfaces.Add(soilLayer3.GeometrySurface);
soilProfile2D.Geometry.Surfaces[0].InnerLoops.Add(soilLayer2.GeometrySurface.OuterLoop);
soilProfile2D.Geometry.Surfaces[0].InnerLoops.Add(soilLayer3.GeometrySurface.OuterLoop);
return soilProfile2D;
}
///
/// -50 -20 -10 0 35 60
/// |-----------------|--------------|-----------------------------| Level 10 m
/// | surface 1 | surface 2 | surface 3 |
/// |-----------------|------|-------|--------------|--------------| Level 0 m
/// | surface 4 | surface 5 | surface |
/// | | | 6 |
/// |------------------------|----------------------|--------------| Level -15 m
///
public static SoilProfile2D CreateSoilProfile2DWithSixSurfacesFormingTwoLayers(double xLeft = -50)
{
var soilProfile2D = new SoilProfile2D
{
Geometry = new GeometryData
{
Left = xLeft,
Right = xLeft + 110,
Bottom = -15
}
};
var soil1 = new Soil("Soil1");
SoilLayer2D soilLayer1 = CreateRectangularSoilLayer2D(10, 0, xLeft, xLeft + 30, soilProfile2D, soil1);
var soil2 = new Soil("Soil2");
SoilLayer2D soilLayer2 = CreatePentagonSoilLayer2D(new Point2D(xLeft + 30, 10), new Point2D(xLeft + 50, 10), new Point2D(xLeft + 50, 0), new Point2D(xLeft + 40, 0), new Point2D(xLeft + 30, 0), soilProfile2D, soil2);
var soil3 = new Soil("Soil3");
SoilLayer2D soilLayer3 = CreatePentagonSoilLayer2D(new Point2D(xLeft + 50, 10), new Point2D(xLeft + 110, 10), new Point2D(xLeft + 110, 0), new Point2D(xLeft + 85, 0), new Point2D(xLeft + 50, 0), soilProfile2D, soil3);
var soil4 = new Soil("Soil4");
SoilLayer2D soilLayer4 = CreatePentagonSoilLayer2D(new Point2D(xLeft, 0), new Point2D(xLeft + 30, 0), new Point2D(xLeft + 40, 0), new Point2D(xLeft + 40, -15), new Point2D(xLeft, -15), soilProfile2D, soil4);
var soil5 = new Soil("Soil5");
SoilLayer2D soilLayer5 = CreatePentagonSoilLayer2D(new Point2D(xLeft + 40, 0), new Point2D(xLeft + 50, 0), new Point2D(xLeft + 85, 0), new Point2D(xLeft + 85, -15), new Point2D(xLeft + 40, -15), soilProfile2D, soil5);
var soil6 = new Soil("Soil6");
SoilLayer2D soilLayer6 = CreateRectangularSoilLayer2D(0, -15, xLeft + 85, xLeft + 110, soilProfile2D, soil6, true);
soilProfile2D.Surfaces.Add(soilLayer1);
soilProfile2D.Surfaces.Add(soilLayer2);
soilProfile2D.Surfaces.Add(soilLayer3);
soilProfile2D.Surfaces.Add(soilLayer4);
soilProfile2D.Surfaces.Add(soilLayer5);
soilProfile2D.Surfaces.Add(soilLayer6);
soilProfile2D.Geometry.Loops.Add(soilLayer1.GeometrySurface.OuterLoop);
soilProfile2D.Geometry.Surfaces.Add(soilLayer1.GeometrySurface);
soilProfile2D.Geometry.Loops.Add(soilLayer2.GeometrySurface.OuterLoop);
soilProfile2D.Geometry.Surfaces.Add(soilLayer2.GeometrySurface);
soilProfile2D.Geometry.Loops.Add(soilLayer3.GeometrySurface.OuterLoop);
soilProfile2D.Geometry.Surfaces.Add(soilLayer3.GeometrySurface);
soilProfile2D.Geometry.Loops.Add(soilLayer4.GeometrySurface.OuterLoop);
soilProfile2D.Geometry.Surfaces.Add(soilLayer4.GeometrySurface);
soilProfile2D.Geometry.Loops.Add(soilLayer5.GeometrySurface.OuterLoop);
soilProfile2D.Geometry.Surfaces.Add(soilLayer5.GeometrySurface);
soilProfile2D.Geometry.Loops.Add(soilLayer6.GeometrySurface.OuterLoop);
soilProfile2D.Geometry.Surfaces.Add(soilLayer6.GeometrySurface);
return soilProfile2D;
}
///
/// -50 -20/-19.999/-19.998 -10
/// |-----------------|-|-|---------------| Level 10 m
/// | surface 1 |2|3| surface 4 |
/// |-----------------|-|-|---------------| Level 0 m
/// | surface 5 |6| surface 7 |
/// | | | |
/// |-------------------|-|---------------| Level -15 m
///
public static SoilProfile2D CreateSoilProfile2DWithFourSurfacesAndThreeVerticalSeparationDistantFrom1Mm(bool areConsecutiveSoilsIdentical)
{
var soilProfile2D = new SoilProfile2D
{
Geometry = new GeometryData
{
Left = -50,
Right = -10,
Bottom = -15
}
};
var soil1 = new Soil("Soil1", 11, 12);
Soil soil2 = areConsecutiveSoilsIdentical ? soil1 : new Soil("Soil2", 13, 14);
Soil soil3 = areConsecutiveSoilsIdentical ? soil1 : new Soil("Soil3", 13.1, 14.1);
Soil soil4 = areConsecutiveSoilsIdentical ? soil1 : new Soil("Soil4", 13.2, 14.2);
var soil5 = new Soil("Soil5", 15, 16);
Soil soil6 = areConsecutiveSoilsIdentical ? soil5 : new Soil("Soil6", 17, 18);
Soil soil7 = areConsecutiveSoilsIdentical ? soil5 : new Soil("Soil7", 17.1, 18.1);
SoilLayer2D soilLayer1 = CreateRectangularSoilLayer2D(10, 0, -50, -20, soilProfile2D, soil1);
SoilLayer2D soilLayer2 = CreateRectangularSoilLayer2D(10, 0, -20, -19.999, soilProfile2D, soil2);
SoilLayer2D soilLayer3 = CreateRectangularSoilLayer2D(10, 0, -19.999, -19.998, soilProfile2D, soil3);
SoilLayer2D soilLayer4 = CreateRectangularSoilLayer2D(10, 0, -19.998, -10, soilProfile2D, soil4);
SoilLayer2D soilLayer5 = CreatePentagonSoilLayer2D(new Point2D(-50, 0), new Point2D(-20, 0), new Point2D(-19.999, 0), new Point2D(-19.999, -15), new Point2D(-50, -15), soilProfile2D, soil5);
SoilLayer2D soilLayer6 = CreateRectangularSoilLayer2D(0, -15, -19.999, -19.998, soilProfile2D, soil6);
SoilLayer2D soilLayer7 = CreateRectangularSoilLayer2D(0, -15, -19.998, -10, soilProfile2D, soil7);
soilProfile2D.Surfaces.Add(soilLayer1);
soilProfile2D.Surfaces.Add(soilLayer2);
soilProfile2D.Surfaces.Add(soilLayer3);
soilProfile2D.Surfaces.Add(soilLayer4);
soilProfile2D.Surfaces.Add(soilLayer5);
soilProfile2D.Surfaces.Add(soilLayer6);
soilProfile2D.Surfaces.Add(soilLayer7);
soilProfile2D.Geometry.Loops.Add(soilLayer1.GeometrySurface.OuterLoop);
soilProfile2D.Geometry.Surfaces.Add(soilLayer1.GeometrySurface);
soilProfile2D.Geometry.Loops.Add(soilLayer2.GeometrySurface.OuterLoop);
soilProfile2D.Geometry.Surfaces.Add(soilLayer2.GeometrySurface);
soilProfile2D.Geometry.Loops.Add(soilLayer3.GeometrySurface.OuterLoop);
soilProfile2D.Geometry.Surfaces.Add(soilLayer3.GeometrySurface);
soilProfile2D.Geometry.Loops.Add(soilLayer4.GeometrySurface.OuterLoop);
soilProfile2D.Geometry.Surfaces.Add(soilLayer4.GeometrySurface);
soilProfile2D.Geometry.Loops.Add(soilLayer5.GeometrySurface.OuterLoop);
soilProfile2D.Geometry.Surfaces.Add(soilLayer5.GeometrySurface);
soilProfile2D.Geometry.Loops.Add(soilLayer6.GeometrySurface.OuterLoop);
soilProfile2D.Geometry.Surfaces.Add(soilLayer6.GeometrySurface);
soilProfile2D.Geometry.Loops.Add(soilLayer7.GeometrySurface.OuterLoop);
soilProfile2D.Geometry.Surfaces.Add(soilLayer7.GeometrySurface);
return soilProfile2D;
}
public static SoilProfile1D CreateSoilProfile1DWithTwoClustersOfInBetweenAquifers(out SurfaceLine2 surfaceLine)
{
const double topLevel = 1.212;
surfaceLine = new SurfaceLine2();
surfaceLine.EnsurePointOfType(0, topLevel, CharacteristicPointType.SurfaceLevelOutside);
surfaceLine.EnsurePointOfType(25, topLevel, CharacteristicPointType.DikeTopAtRiver);
surfaceLine.EnsurePointOfType(50, topLevel, CharacteristicPointType.DikeTopAtPolder);
surfaceLine.EnsurePointOfType(75, topLevel, CharacteristicPointType.DikeToeAtPolder);
surfaceLine.EnsurePointOfType(100, topLevel, CharacteristicPointType.SurfaceLevelInside);
var soilProfile1D = new SoilProfile1D
{
BottomLevel = -30.0
};
var layer = new SoilLayer1D
{
Name = "L1a",
TopLevel = topLevel,
IsAquifer = true // aquifer at top
};
soilProfile1D.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = "L1b",
TopLevel = 0,
IsAquifer = false
};
soilProfile1D.Layers.Add(layer);
layer = new SoilLayer1D
{
Name = "L2a",
TopLevel = -2.111, // top of highest 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, // top of lowest in-between aquifer
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;
}
///
/// /------\
/// / \
/// _____________/ \______________________________ Level 10 m
/// Aquitard
/// _______________________________________________________ Level 6 m
/// In between aquifer
/// _______________________________________________________ Level 2 m
/// Aquitard
/// _______________________________________________________ Level -2 m
/// In between aquifer
/// ______________ Level -3 m
/// ____________/ \___________________________ Level -4 m
/// Aquitard
/// _______________________________________________________ Level -6 m
/// Bottom aquifer
/// _______________________________________________________ Level -10 m
///
public static SoilProfile2D CreateSoilProfile2DWithNonHorizontalBottomAquitard(out SurfaceLine2 surfaceLine)
{
const double almostEqual = 1e-09;
surfaceLine = FactoryForSurfaceLines.CreateSurfaceLineDike(10);
SoilProfile1D soilProfile1D = CreateClaySandClaySandClaySandProfile(10, 6, 2, -2, -4, -6);
soilProfile1D.BottomLevel = -10;
SoilProfile2D soilProfile2D = FactoryForSoilProfiles.CreateSoilProfile2DBasedOnSoilProfile1D(soilProfile1D, surfaceLine);
Point2D point1 = soilProfile2D.Geometry.Points.First(p => Math.Abs(p.X - 34.5) < almostEqual && Math.Abs(p.Z + 4) < almostEqual);
point1.Z = -3;
Point2D point2 = soilProfile2D.Geometry.Points.First(p => Math.Abs(p.X - 40.5) < almostEqual && Math.Abs(p.Z + 4) < almostEqual);
point2.Z = -3;
return soilProfile2D;
}
public static SoilLayer2D CreateRectangularSoilLayer2D(double topCoord, double bottomCoord, double leftCoord,
double rightCoord, SoilProfile2D soilProfile2D, Soil soil = null, bool isAquifer = false)
{
var topLeftPoint = new Point2D(leftCoord, topCoord);
var topRightPoint = new Point2D(rightCoord, topCoord);
var bottomRightPoint = new Point2D(rightCoord, bottomCoord);
var bottomLeftPoint = new Point2D(leftCoord, bottomCoord);
var curve1 = new GeometryCurve(topLeftPoint, topRightPoint);
var curve2 = new GeometryCurve(topRightPoint, bottomRightPoint);
var curve3 = new GeometryCurve(bottomRightPoint, bottomLeftPoint);
var curve4 = new GeometryCurve(bottomLeftPoint, topLeftPoint);
if (soilProfile2D != null)
{
AddPointIfNotYetPresentInGeometry(soilProfile2D, topLeftPoint);
AddPointIfNotYetPresentInGeometry(soilProfile2D, topRightPoint);
AddPointIfNotYetPresentInGeometry(soilProfile2D, bottomRightPoint);
AddPointIfNotYetPresentInGeometry(soilProfile2D, bottomLeftPoint);
AddCurveIfNotYetPresentInGeometry(soilProfile2D, curve1);
AddCurveIfNotYetPresentInGeometry(soilProfile2D, curve2);
AddCurveIfNotYetPresentInGeometry(soilProfile2D, curve3);
AddCurveIfNotYetPresentInGeometry(soilProfile2D, curve4);
}
var soilLayer2D = new SoilLayer2D
{
GeometrySurface = new GeometrySurface
{
OuterLoop = new GeometryLoop
{
CurveList =
{
curve1,
curve2,
curve3,
curve4
}
}
},
Soil = soil,
IsAquifer = isAquifer
};
return soilLayer2D;
}
public static SoilLayer2D CreateTriangularSoilLayer2D(Point2D point1, Point2D point2, Point2D point3, SoilProfile2D soilProfile2D, Soil soil = null, bool isAquifer = false)
{
return CreatePolygoneSoilLayer2D([
..new[]
{
point1,
point2,
point3
}
], soil, soilProfile2D, isAquifer);
}
public static SoilLayer2D CreateQuadrilateralSoilLayer2D(Point2D point1, Point2D point2, Point2D point3, Point2D point4, SoilProfile2D soilProfile2D, Soil soil = null, bool isAquifer = false)
{
return CreatePolygoneSoilLayer2D([
..new[]
{
point1,
point2,
point3,
point4
}
], soil, soilProfile2D, isAquifer);
}
public static SoilLayer2D CreatePentagonSoilLayer2D(Point2D point1, Point2D point2, Point2D point3, Point2D point4,
Point2D point5, SoilProfile2D soilProfile2D, Soil soil = null, bool isAquifer = false)
{
return CreatePolygoneSoilLayer2D([
..new[]
{
point1,
point2,
point3,
point4,
point5
}
], soil, soilProfile2D, isAquifer);
}
public static SoilLayer2D CreateHexagonSoilLayer2D(Point2D point1, Point2D point2, Point2D point3, Point2D point4, Point2D point5, Point2D point6, SoilProfile2D soilProfile2D, Soil soil = null, bool isAquifer = false)
{
return CreatePolygoneSoilLayer2D([
..new[]
{
point1,
point2,
point3,
point4,
point5,
point6
}
], soil, soilProfile2D, isAquifer);
}
public static SoilLayer2D CreateHeptagonSoilLayer2D(Point2D point1, Point2D point2, Point2D point3, Point2D point4, Point2D point5, Point2D point6, Point2D point7, SoilProfile2D soilProfile2D, Soil soil = null, bool isAquifer = false)
{
return CreatePolygoneSoilLayer2D([
..new[]
{
point1,
point2,
point3,
point4,
point5,
point6,
point7
}
], soil, soilProfile2D, isAquifer);
}
public static SoilLayer2D CreatePolygoneSoilLayer2D(List points, Soil soil, SoilProfile2D soilProfile2D, bool isAquifer = false)
{
var soilLayer2D = new SoilLayer2D
{
GeometrySurface = new GeometrySurface
{
OuterLoop = new GeometryLoop()
},
Soil = soil,
IsAquifer = isAquifer
};
var curves = new List();
for (var i = 0; i < points.Count - 1; i++)
{
var curve = new GeometryCurve(points[i], points[i + 1]);
curves.Add(curve);
soilLayer2D.GeometrySurface.OuterLoop.CurveList.Add(curve);
}
var endCurve = new GeometryCurve(points[^1], points[0]);
curves.Add(endCurve);
soilLayer2D.GeometrySurface.OuterLoop.CurveList.Add(endCurve);
if (soilProfile2D != null)
{
foreach (Point2D point in points)
{
AddPointIfNotYetPresentInGeometry(soilProfile2D, point);
}
foreach (GeometryCurve curve in curves)
{
AddCurveIfNotYetPresentInGeometry(soilProfile2D, curve);
}
}
return soilLayer2D;
}
///
/// Creates a surface line for a soil profile 2D at the requested position.
///
///
///
///
public static SurfaceLine2 CreateSurfaceLineForSoilProfile2D(SoilProfile2D soilProfile2D, PositionToSoilProfile2D positionToSoilProfile2D)
{
Point2D geometryPoint = soilProfile2D.Geometry.SurfaceLine.Points.First();
var leftPoint = new Point2D(geometryPoint.X, geometryPoint.Z);
geometryPoint = soilProfile2D.Geometry.SurfaceLine.Points.Last();
var rightPoint = new Point2D(geometryPoint.X, geometryPoint.Z);
var middlePoint = new Point2D((leftPoint.X + rightPoint.X) / 2, (leftPoint.Z + rightPoint.Z) / 2);
switch (positionToSoilProfile2D)
{
case PositionToSoilProfile2D.LeftOfSoilProfile:
leftPoint.X -= 1;
break;
case PositionToSoilProfile2D.RightOfSoilProfile:
rightPoint.X += 1;
break;
case PositionToSoilProfile2D.OnSoilProfile:
break;
case PositionToSoilProfile2D.InsideOfSoilProfile:
leftPoint.X += 1;
rightPoint.X -= 1;
break;
}
SurfaceLine2 surfaceLine = CreateSurfaceLine(new[]
{
leftPoint,
middlePoint,
rightPoint
});
surfaceLine.CharacteristicPoints.Add(new CharacteristicPoint(surfaceLine.CharacteristicPoints, leftPoint));
surfaceLine.CharacteristicPoints.Annotate(0, CharacteristicPointType.SurfaceLevelOutside);
surfaceLine.CharacteristicPoints.Add(new CharacteristicPoint(surfaceLine.CharacteristicPoints, rightPoint));
surfaceLine.CharacteristicPoints.Annotate(1, CharacteristicPointType.SurfaceLevelInside);
return surfaceLine;
}
public static SoilProfile2D CreateSoilProfile2DBasedOnSoilProfile1D(SoilProfile1D soilProfile1D, SurfaceLine2 surfaceLine)
{
var soilSurfaceProfile = new SoilSurfaceProfile
{
SoilProfile = soilProfile1D,
SurfaceLine2 = surfaceLine,
DikeEmbankmentMaterial = soilProfile1D.Layers.OrderBy(l => l.TopLevel).First().Soil,
Name = "Test"
};
return soilSurfaceProfile.ConvertToSoilProfile2D();
}
private static string GetNewUniqueLayerId(SoilProfile1D soilProfile1D)
{
var num = 0;
string id;
do
{
id = "L" + num++;
} while (soilProfile1D.GetLayerWithName(id) != null);
return id;
}
private static void AddPointIfNotYetPresentInGeometry(SoilProfile2D soilProfile, Point2D point)
{
if (!soilProfile.Geometry.Points.Any(p => p.X.IsNearEqual(point.X) && p.Z.IsNearEqual(point.Z)))
{
soilProfile.Geometry.Points.Add(point);
}
}
private static void AddCurveIfNotYetPresentInGeometry(SoilProfile2D soilProfile, GeometryCurve curve)
{
if (!soilProfile.Geometry.Curves.Any(c => (c.HeadPoint.X.IsNearEqual(curve.HeadPoint.X) && c.HeadPoint.Z.IsNearEqual(curve.HeadPoint.Z)
&& c.EndPoint.X.IsNearEqual(curve.EndPoint.X) && c.EndPoint.Z.IsNearEqual(curve.EndPoint.Z)) ||
(c.EndPoint.X.IsNearEqual(curve.HeadPoint.X) && c.EndPoint.Z.IsNearEqual(curve.HeadPoint.Z) &&
c.HeadPoint.X.IsNearEqual(curve.EndPoint.X) && c.HeadPoint.Z.IsNearEqual(curve.EndPoint.Z))))
{
soilProfile.Geometry.Curves.Add(curve);
}
}
}