// 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; } } } }