// Copyright (C) Stichting Deltares 2019. 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; namespace Deltares.DamEngine.Data.Geometry { /// /// Class for geometry surfaces. /// /// [Serializable] public class GeometrySurface : GeometryObject { private readonly List innerLoops = new List(); private GeometryLoop outerLoop = new GeometryLoop(); /// /// Empty constructor /// public GeometrySurface() { } /// /// Initializes a new instance of the class. /// /// The loop. public GeometrySurface(GeometryLoop loop) { outerLoop = loop; } /// /// The circumference of the surface. /// public GeometryLoop OuterLoop { get { return outerLoop; } set { outerLoop = value; } } /// /// All internal loops encompassed by . /// public List InnerLoops { get { return innerLoops; } } /// /// determine top of geometry surface outerloop as GeometryPointString /// /// public GeometryPointString DetermineTopGeometrySurface() { return DetermineTopCurves(); } /// /// determine bottom of geometry surface outerloop as GeometryPointString /// /// public GeometryPointString DetermineBottomGeometrySurface() { return DetermineBottomCurves(); } /// /// Gets the geometry bounds. /// /// public override GeometryBounds GetGeometryBounds() { return OuterLoop.GetGeometryBounds(); } /// /// Determine points at the top side of the geometry surface /// /// private GeometryPointString DetermineTopCurves() { //TODO: Lot of similar code to DetermineBottomCurves; Refactoring recommended. var minXPoints = OuterLoop.GetPointsAtX(OuterLoop.GetMinX()); var maxXPoints = OuterLoop.GetPointsAtX(OuterLoop.GetMaxX()); //verticals at start are omitted Point2D startTopPoint = minXPoints.OrderByDescending(p => p.Z).First(); //verticals at end are omitted Point2D endTopPoint = maxXPoints.OrderByDescending(p => p.Z).First(); var topPoints = new GeometryPointString(); int currentIndex = OuterLoop.CalcPoints.IndexOf(startTopPoint); while (!topPoints.CalcPoints.Contains(endTopPoint)) { topPoints.CalcPoints.Add(OuterLoop.CalcPoints[currentIndex++]); if (currentIndex >= OuterLoop.CalcPoints.Count) { currentIndex = 0; } } // Replace the points by clones for (int i = 0; i < topPoints.CalcPoints.Count; i++) { topPoints.CalcPoints[i] = new Point2D(topPoints.CalcPoints[i].X, topPoints.CalcPoints[i].Z); } return topPoints; } /// /// determine curves at the bottom side of the geometry surface /// /// private GeometryPointString DetermineBottomCurves() { //TODO: Lot of similar code to DetermineTopCurves; Refactoring recommended. //create copy, leave original var minXPoints = OuterLoop.GetPointsAtX(OuterLoop.GetMinX()); var maxXPoints = OuterLoop.GetPointsAtX(OuterLoop.GetMaxX()); //verticals at start are omitted var startBottomPoint = minXPoints.OrderBy(p => p.Z).First(); //verticals at end are omitted var endBottomPoint = maxXPoints.OrderBy(p => p.Z).First(); var bottomPoints = new GeometryPointString(); int currentIndex = OuterLoop.CalcPoints.IndexOf(endBottomPoint); while (!bottomPoints.CalcPoints.Contains(startBottomPoint)) { bottomPoints.CalcPoints.Add(OuterLoop.CalcPoints[currentIndex++]); if (currentIndex >= OuterLoop.CalcPoints.Count) { currentIndex = 0; } } // Replace the points by clones for (int i = 0; i < bottomPoints.CalcPoints.Count; i++) { bottomPoints.CalcPoints[i] = new Point2D(bottomPoints.CalcPoints[i].X, bottomPoints.CalcPoints[i].Z); } // As the curves are sorted clockwise, the bottomcurves are always orientated from right to left // while this result of this method must be from left to right so reverse the curves bottomPoints.CalcPoints.Reverse(); return bottomPoints; } } }