// Copyright (C) Stichting Deltares 2017. All rights reserved.
//
// This file is part of Ringtoets.
//
// Ringtoets is free software: you can redistribute it and/or modify
// it under the terms of the GNU 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 General Public License for more details.
//
// You should have received a copy of the GNU 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.WTIStability.Data.Geo;
using Deltares.WTIStability.Data.Standard;
using Ringtoets.MacroStabilityInwards.KernelWrapper.Calculators.Input;
using Point2D = Core.Common.Base.Geometry.Point2D;
using WtiStabilityPoint2D = Deltares.WTIStability.Data.Geo.Point2D;
namespace Ringtoets.MacroStabilityInwards.KernelWrapper.Creators.Input
{
///
/// Creates instances which are required in a calculation.
///
internal static class SoilProfileCreator
{
///
/// Creates a based on and
/// .
///
/// The preconsolidation stresses to use in the .
/// The layer data to use in the .
/// A new .
/// Thrown when any parameter is null.
public static SoilProfile2D Create(IEnumerable preconsolidationStresses,
IEnumerable layersWithSoil)
{
if (preconsolidationStresses == null)
{
throw new ArgumentNullException(nameof(preconsolidationStresses));
}
if (layersWithSoil == null)
{
throw new ArgumentNullException(nameof(layersWithSoil));
}
var profile = new SoilProfile2D();
profile.PreconsolidationStresses.AddRange(CreatePreconsolidationStresses(preconsolidationStresses));
var alreadyCreatedPoints = new List();
var alreadyCreatedCurves = new List();
var alreadyCreatedLoops = new List();
foreach (LayerWithSoil layerWithSoil in layersWithSoil)
{
profile.Surfaces.Add(new SoilLayer2D
{
IsAquifer = layerWithSoil.IsAquifer,
Soil = layerWithSoil.Soil,
GeometrySurface = CreateGeometrySurface(layerWithSoil, alreadyCreatedPoints, alreadyCreatedCurves, alreadyCreatedLoops),
WaterpressureInterpolationModel = layerWithSoil.WaterPressureInterpolationModel
});
}
profile.Geometry = CreateGeometryData(profile);
return profile;
}
private static IEnumerable CreatePreconsolidationStresses(IEnumerable preconsolidationStresses)
{
return preconsolidationStresses.Select(preconsolidationStress => new PreConsolidationStress
{
StressValue = preconsolidationStress.Stress,
X = preconsolidationStress.Coordinate.X,
Z = preconsolidationStress.Coordinate.Y
}).ToArray();
}
private static GeometrySurface CreateGeometrySurface(LayerWithSoil layer, List alreadyCreatedPoints, List alreadyCreatedCurves, List alreadyCreatedLoops)
{
var surface = new GeometrySurface
{
OuterLoop = CreateGeometryLoop(layer.OuterRing, alreadyCreatedPoints, alreadyCreatedCurves, alreadyCreatedLoops)
};
surface.InnerLoops.AddRange(layer.InnerRings.Select(ir => CreateGeometryLoop(ir, alreadyCreatedPoints, alreadyCreatedCurves, alreadyCreatedLoops)).ToArray());
return surface;
}
private static GeometryLoop CreateGeometryLoop(Point2D[] points, List alreadyCreatedPoints, List alreadyCreatedCurves, List alreadyCreatedLoops)
{
GeometryLoop loop = alreadyCreatedLoops.FirstOrDefault(l => l.CurveList.Select(cl => cl.HeadPoint.X).SequenceEqual(points.Select(p => p.X))
&& l.CurveList.Select(cl => cl.HeadPoint.Z).SequenceEqual(points.Select(p => p.Y)));
if (loop == null)
{
loop = new GeometryLoop();
loop.CurveList.AddRange(CreateGeometryCurves(points, alreadyCreatedPoints, alreadyCreatedCurves));
alreadyCreatedLoops.Add(loop);
}
return loop;
}
private static GeometryCurve[] CreateGeometryCurves(Point2D[] points, List alreadyCreatedPoints, List alreadyCreatedCurves)
{
var curves = new List();
WtiStabilityPoint2D[] stabilityPoints = points.Select(p => GetPoint(p, alreadyCreatedPoints)).ToArray();
int stabilityPointsLength = stabilityPoints.Length;
for (var i = 0; i < stabilityPointsLength; i++)
{
curves.Add(GetCurve(stabilityPoints[i],
i == stabilityPointsLength - 1
? stabilityPoints[0]
: stabilityPoints[i + 1],
alreadyCreatedCurves));
}
return curves.ToArray();
}
private static WtiStabilityPoint2D GetPoint(Point2D point2D, List alreadyCreatedPoints)
{
WtiStabilityPoint2D stabilityPoint = alreadyCreatedPoints.FirstOrDefault(p => p.X.Equals(point2D.X) && p.Z.Equals(point2D.Y));
if (stabilityPoint == null)
{
stabilityPoint = new WtiStabilityPoint2D(point2D.X, point2D.Y);
alreadyCreatedPoints.Add(stabilityPoint);
}
return stabilityPoint;
}
private static GeometryCurve GetCurve(WtiStabilityPoint2D headPoint, WtiStabilityPoint2D endPoint, List alreadyCreatedCurves)
{
GeometryCurve curve = alreadyCreatedCurves.FirstOrDefault(c => ReferenceEquals(c.HeadPoint, headPoint) && ReferenceEquals(c.EndPoint, endPoint)
|| ReferenceEquals(c.HeadPoint, endPoint) && ReferenceEquals(c.EndPoint, headPoint));
if (curve == null)
{
curve = new GeometryCurve
{
HeadPoint = headPoint,
EndPoint = endPoint
};
alreadyCreatedCurves.Add(curve);
}
return curve;
}
private static GeometryData CreateGeometryData(SoilProfile2D profile)
{
var geometryData = new GeometryData();
geometryData.Surfaces.AddRange(profile.Surfaces
.Select(s => s.GeometrySurface));
geometryData.Loops.AddRange(geometryData.Surfaces
.Select(gs => gs.OuterLoop));
geometryData.Curves.AddRange(geometryData.Loops
.SelectMany(l => l.CurveList)
.Distinct());
geometryData.Points.AddRange(geometryData.Curves
.SelectMany(c => new[]
{
c.HeadPoint,
c.EndPoint
}).Distinct());
geometryData.Rebox();
return geometryData;
}
}
}