// Copyright (C) Stichting Deltares 2021. 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 Deltares.DamEngine.Data.General; using Deltares.DamEngine.Data.Geometry; using Deltares.DamEngine.Data.Geotechnics; namespace Deltares.DamEngine.Calculators.DikesDesign { /// /// Class for adapting the height of the crest of a surfaceline /// public class SurfaceLineHeightAdapter : SurfaceLineAdapter { /// /// Initializes a new instance of the class. /// /// /// /// public SurfaceLineHeightAdapter(SurfaceLine2 surfaceLine, Location location, double scenarioPolderLevel) : base(surfaceLine, location, scenarioPolderLevel) { } /// /// Constructs a new surface line with a new height /// /// /// There are a few scenarios of that will be handled: /// - one without a shoulder inside /// - one with a shoulder inside but the adaption will remove the shoulder completly /// - one with a shoulder but a part of the shoulder remains intact /// - one where the new top falls completely above the old top /// /// The new height /// The adapted surface line /// public SurfaceLine2 ConstructNewSurfaceLine(double newDikeHeight) { //Input data GeometryPoint pointAtTopRiver = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtRiver); GeometryPoint pointAtTopPolder = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder); GeometryPoint pointDikeToeInward = surfaceLine.GetDikeToeInward(); GeometryPoint startingPoint = surfaceLine.GetStartingPoint(); surfaceLine.RemoveSegmentBetween(startingPoint.X, pointAtTopRiver.X); GeometryPoint newPointAtTopRiver; GeometryPoint oldPointAtTopRiver = null; if (Location.UseNewDikeSlopeOutside) { var newOutsideSlopePoint = new GeometryPoint { X = pointAtTopRiver.X + 100, Z = pointAtTopRiver.Z + 100*Location.NewDikeSlopeOutside }; newPointAtTopRiver = LineHelper.GetIntersectionPointWithExtrapolation(pointAtTopRiver, newOutsideSlopePoint, new GeometryPoint(pointAtTopRiver.X, newDikeHeight), new GeometryPoint(pointAtTopPolder.X, newDikeHeight)); oldPointAtTopRiver = new GeometryPoint {X = pointAtTopRiver.X, Z = pointAtTopRiver.Z}; } else { newPointAtTopRiver = LineHelper.GetIntersectionPointWithExtrapolation(startingPoint,pointAtTopRiver, new GeometryPoint(pointAtTopRiver.X, newDikeHeight), new GeometryPoint(pointAtTopPolder.X, newDikeHeight)); } // Determine the new point at DIKE TOP RIVER double dikeTopWidth = pointAtTopPolder.X - pointAtTopRiver.X; if (Location.UseNewDikeTopWidth) { dikeTopWidth = Location.NewDikeTopWidth; } // Determine the new point at DIKE TOP POLDER GeometryPoint newPointAtTopPolder = new GeometryPoint(newPointAtTopRiver.X + dikeTopWidth, newDikeHeight); var slopeTangentInside = (pointAtTopPolder.Z - pointDikeToeInward.Z) / (pointDikeToeInward.X - pointAtTopPolder.X); if (Location.UseNewDikeSlopeInside) { slopeTangentInside = Location.NewDikeSlopeInside; } // check case where the new top falls completely above the old top var intersectionPointDikeTop = IntersectionpointWithOldDikeTop(newPointAtTopPolder, slopeTangentInside); if (intersectionPointDikeTop != null) { // Remove all points between old dike top river and old dike top polder surfaceLine.RemoveSegmentBetween(pointAtTopRiver.X, pointAtTopPolder.X); // Add new dike top river, new dike top polder surfaceLine.AddCharacteristicPoint(newPointAtTopRiver, CharacteristicPointType.DikeTopAtRiver); surfaceLine.AddCharacteristicPoint(newPointAtTopPolder, CharacteristicPointType.DikeTopAtPolder); // check if intersection point equals old dike top polder, if so the ready else add intersection point as normal point if (!pointAtTopPolder.LocationEquals(intersectionPointDikeTop)) { surfaceLine.EnsurePoint(intersectionPointDikeTop.X, intersectionPointDikeTop.Z); } surfaceLine.SortPoints(); return surfaceLine; } // Remove points on inside slope surfaceLine.RemoveSegmentBetween(pointAtTopPolder.X, pointDikeToeInward.X); // Store the ditch (if any) var ditchDefinition = GetDitchDefinition(); // Delete the ditch from the surfaceline (if any) RemoveExistingDitch(ditchDefinition); // Adjust for the new slope var slopePoint = ReplaceBaseInsideForNewSlope(newPointAtTopPolder, slopeTangentInside); // Reset pointDikeToeInward for new position pointDikeToeInward = surfaceLine.GetDikeToeInward(); // Remove all points between "old" dike top river side and new toe inward surfaceLine.RemoveSegmentBetween(pointAtTopRiver.X, pointDikeToeInward.X); if (slopePoint != null) { // if the slope point exists (new end point of slope coincides with shouldertopinside), it has to be // re-added as "normal" point because it was deleted in the former RemoveSegmentBetween. surfaceLine.AddCharacteristicPoint(slopePoint, CharacteristicPointType.None); } // Adjust position of "old" dike top river surfaceLine.EnsurePointOfType(newPointAtTopRiver.X, newPointAtTopRiver.Z, CharacteristicPointType.DikeTopAtRiver); if (Location.UseNewDikeSlopeOutside) { // Re-add the old dike top river as "normal" point surfaceLine.AddCharacteristicPoint(oldPointAtTopRiver, CharacteristicPointType.None); } // Add the new dike top at polder side surfaceLine.EnsurePointOfType(newPointAtTopPolder.X, newPointAtTopPolder.Z, CharacteristicPointType.DikeTopAtPolder); // Restore Ditch (if any) RestoreDitch(ditchDefinition); // Restore traffic load RestoreTrafficLoad(); surfaceLine.SortPoints(); return surfaceLine; } /// /// Tries to find the intersection point between the old dike top and the new inside slope starting at the new /// dike top at polder side. /// /// /// /// The intersection point when found else null private GeometryPoint IntersectionpointWithOldDikeTop(GeometryPoint newPointAtTopPolder, double slopeTangent) { GeometryPoint res = null; var newPoint = new GeometryPoint { X = newPointAtTopPolder.X + 100, Z = newPointAtTopPolder.Z - 100*slopeTangent }; GeometryPoint dikeTopAtPolder = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder); var ip = LineHelper.GetIntersectionPointWithExtrapolation(newPointAtTopPolder, newPoint, surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtRiver), dikeTopAtPolder); if (ip != null && ip.X <= dikeTopAtPolder.X) { res = ip; } return res; } } }