// 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.Collections.ObjectModel;
using System.Linq;
using Core.Common.Base.Geometry;
using Core.Common.Geometry;
using Ringtoets.MacroStabilityInwards.Primitives;
namespace Ringtoets.MacroStabilityInwards.Data
{
///
/// Class for constructing soil profiles for which the geometry of the layers lay under a surface line.
///
public static class SoilProfileUnderSurfaceLineFactory
{
///
/// Creates a new .
///
/// The soil profile containing layers under the .
/// The surface line for which determines the top of the .
/// A new containing geometries from the
/// under the .
/// Thrown when any parameter is null.
public static SoilProfileUnderSurfaceLine Create(MacroStabilityInwardsSoilProfile1D soilProfile, MacroStabilityInwardsSurfaceLine surfaceLine)
{
if (soilProfile == null)
{
throw new ArgumentNullException(nameof(soilProfile));
}
if (surfaceLine == null)
{
throw new ArgumentNullException(nameof(surfaceLine));
}
Point2D[] localizedSurfaceLine = surfaceLine.LocalGeometry.ToArray();
double geometryBottom = Math.Min(soilProfile.Bottom, localizedSurfaceLine.Min(p => p.Y)) - 1;
IEnumerable surfaceLineGeometry = AdvancedMath2D.CompleteLineToPolygon(localizedSurfaceLine, geometryBottom);
IEnumerable layerGeometries = soilProfile.Layers.Select(
layer => As2DGeometry(
layer,
soilProfile,
localizedSurfaceLine.First().X,
localizedSurfaceLine.Last().X));
return GeometriesToIntersections(layerGeometries, surfaceLineGeometry);
}
///
/// Creates a new .
///
/// The soil profile containing layers.
/// A new containing geometries from the
/// .
/// Thrown when is null.
public static SoilProfileUnderSurfaceLine Create(MacroStabilityInwardsSoilProfile2D soilProfile)
{
if (soilProfile == null)
{
throw new ArgumentNullException(nameof(soilProfile));
}
IEnumerable layersUnderSurfaceLine = soilProfile.Layers.Select(
layer => new SoilLayerUnderSurfaceLine(
RingToPoints(layer.OuterRing),
layer.Holes.Select(RingToPoints),
layer.Properties));
return new SoilProfileUnderSurfaceLine(layersUnderSurfaceLine);
}
private static Point2D[] RingToPoints(Ring ring)
{
return ring.Points.ToArray();
}
private static SoilProfileUnderSurfaceLine GeometriesToIntersections(IEnumerable layerGeometries, IEnumerable surfaceLineGeometry)
{
var collection = new Collection();
IEnumerable surfaceLineGeometryArray = surfaceLineGeometry.ToArray();
foreach (TempSoilLayerGeometry layer in layerGeometries)
{
foreach (Point2D[] soilLayerArea in GetSoilLayerWithSurfaceLineIntersection(surfaceLineGeometryArray, layer.OuterLoop))
{
collection.Add(new SoilLayerUnderSurfaceLine(soilLayerArea, layer.Properties));
}
}
return new SoilProfileUnderSurfaceLine(collection);
}
private static TempSoilLayerGeometry As2DGeometry(MacroStabilityInwardsSoilLayer1D layer, MacroStabilityInwardsSoilProfile1D soilProfile, double minX, double maxX)
{
double top = layer.Top;
double bottom = top - soilProfile.GetLayerThickness(layer);
return new TempSoilLayerGeometry(new[]
{
new Point2D(minX, top),
new Point2D(maxX, top),
new Point2D(maxX, bottom),
new Point2D(minX, bottom)
}, layer.Properties);
}
private static IEnumerable GetSoilLayerWithSurfaceLineIntersection(IEnumerable surfaceLineGeometry, IEnumerable soilLayerGeometry)
{
return AdvancedMath2D.PolygonIntersectionWithPolygon(surfaceLineGeometry, soilLayerGeometry).Where(arr => arr.Length > 2);
}
private class TempSoilLayerGeometry
{
public TempSoilLayerGeometry(Point2D[] outerLoop, SoilLayerProperties properties)
{
OuterLoop = outerLoop;
Properties = properties;
InnerLoops = Enumerable.Empty();
}
public Point2D[] OuterLoop { get; }
public SoilLayerProperties Properties { get; }
public IEnumerable InnerLoops { get; }
}
}
}