using System; using Deltares.Geometry; using Deltares.Geotechnics.SurfaceLines; namespace Deltares.Dam.Data { public class NonWaterRetainingObjectInSurfaceLine { public NonWaterRetainingObject NonWaterRetainingObject { get; set; } public SurfaceLine2 SurfaceLine { get; set; } public MStabGridPosition GridPosition { get; set; } public double StepSizeX { get; set; } const double MinimumDistanceToEdgeDitch = 0.1000; /// /// /// /// /// public double DetermineStartLocationForNonWaterRetainingObject(bool skipDitch) { // initialise at an invalid return value (i.e. a location outside the surfaceline) double result = SurfaceLine.Geometry.Points[SurfaceLine.Geometry.Count - 1].X + 100; const int distanceToEdgeSurfaceLine = 1; if (NonWaterRetainingObject != null) { if (GridPosition == MStabGridPosition.Left) { result = Math.Max(SurfaceLine.Geometry.Points[0].X + distanceToEdgeSurfaceLine, SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtRiver).X - NonWaterRetainingObject.MaxDistanceFromToe); } else { result = Math.Min(SurfaceLine.Geometry.Points[SurfaceLine.Geometry.Count - 1].X - distanceToEdgeSurfaceLine - NonWaterRetainingObject.Btotal(), SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).X + NonWaterRetainingObject.MaxDistanceFromToe - NonWaterRetainingObject.Btotal()); } if ((skipDitch) && (DoesPositionXFitInSurfaceLine(result))) { // the ditch is only at the polder side so only a problem when the Gridposition is right. // So if the NWO does coincide with the ditch, the nwo has to be repositioned to the left of the ditch. NonWaterRetainingObject.Point1 = new GeometryPoint(); NonWaterRetainingObject.Point1.X = result; NonWaterRetainingObject.Point4 = new GeometryPoint(); NonWaterRetainingObject.Point4.X = result + NonWaterRetainingObject.Btotal(); if (DoesNonWaterRetainingObjectCoincideWithDitch()) { result = SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DitchDikeSide).X - NonWaterRetainingObject.Btotal() - MinimumDistanceToEdgeDitch; } } } return result; } public bool DoesPositionXFitInSurfaceLine(double fitPositionX) { return (fitPositionX >= SurfaceLine.Geometry.Points[0].X) && (fitPositionX <= SurfaceLine.Geometry.Points[SurfaceLine.Geometry.Count - 1].X); } /// /// /// /// /// /// public double DetermineNewFitPostionX(double fitPositionX, bool skipDitch) { double result; if (GridPosition == MStabGridPosition.Left) { result = fitPositionX + StepSizeX; } else { result = fitPositionX - StepSizeX; } if (skipDitch) { NonWaterRetainingObject.Point1 = new GeometryPoint(); NonWaterRetainingObject.Point1.X = result; NonWaterRetainingObject.Point4 = new GeometryPoint(); NonWaterRetainingObject.Point4.X = result + NonWaterRetainingObject.Btotal(); if (DoesNonWaterRetainingObjectCoincideWithDitch()) { result = SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DitchDikeSide).X - NonWaterRetainingObject.Btotal() - MinimumDistanceToEdgeDitch; } } return result; } public double DistanceToToe(double fitPositionX) { double result = 0; if (GridPosition == MStabGridPosition.Left) { if ((NonWaterRetainingObject.Point1 != null) && (NonWaterRetainingObject.Point4 != null)) { result = SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtRiver).X - (fitPositionX + (NonWaterRetainingObject.Point4.X - NonWaterRetainingObject.Point1.X)); } } else { result = fitPositionX - SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).X; } return result; } /// /// Create a new instance of , based on /// , and fits the /// non water retaining object in that surface line. /// /// The fit position x. /// public SurfaceLine2 FitNonWaterRetainingObjectInSurfaceLine(double fitPositionX) { // check to see if new position is still valid if (IsStillValid(fitPositionX)) { SurfaceLine2 newSurfaceLine = SurfaceLine.FullDeepClone(); if (NonWaterRetainingObject != null) { GeometryPoint point1 = new GeometryPoint(); point1.X = fitPositionX; point1.Z = newSurfaceLine.Geometry.GetZAtX(fitPositionX); // see if last point of NWO at z1 is above, on, or beneath the surface line. If on, then finished, otherwise turn NWO untill it is. GeometryPoint point4 = new GeometryPoint(); point4.X = fitPositionX + NonWaterRetainingObject.Btotal(); point4.Z = point1.Z; var position = newSurfaceLine.Geometry.PositionXzOfPointRelatedToExtrapolatedLine(point4); var oldposition = position; var rotationangle = 5.0; var summedRotationAngle = 0.0; if (position == RelativeXzPosition.OnGeometricLine) { // if point 4 already is on surfaceline, make sure that points 2 and 3 are not rotated rotationangle = 0; } while (position != RelativeXzPosition.OnGeometricLine) { if (position == RelativeXzPosition.AboveGeometricLine) { point4 = RotatePoint(point1, point4, -rotationangle); summedRotationAngle -= rotationangle; } else { point4 = RotatePoint(point1, point4, rotationangle); summedRotationAngle += rotationangle; } position = newSurfaceLine.Geometry.PositionXzOfPointRelatedToExtrapolatedLine(point4); if (position != oldposition && position != RelativeXzPosition.OnGeometricLine) { rotationangle = rotationangle * 0.5; oldposition = position; } } // now np4 is on the surface line. Delete all existing surfaceline points between fitPositionX and np4.x, then add the NWO lines. newSurfaceLine.RemoveSegmentIncluding(point1.X, point4.X); GeometryPoint point2 = new GeometryPoint(); point2.X = point1.X + NonWaterRetainingObject.H1*NonWaterRetainingObject.N1; point2.Z = point1.Z - NonWaterRetainingObject.H1; GeometryPoint point3 = new GeometryPoint(); point3.X = point2.X + Math.Sqrt( (NonWaterRetainingObject.B * NonWaterRetainingObject.B) - ( Math.Pow((NonWaterRetainingObject.H2 - NonWaterRetainingObject.H1), 2))); point3.Z = point1.Z - NonWaterRetainingObject.H2;; point2 = RotatePoint(point1, point2, summedRotationAngle); NonWaterRetainingObject.Point1 = newSurfaceLine.Geometry.GetPointAt(point1.X, 0, point1.Z); if (NonWaterRetainingObject.Point1 == null) { NonWaterRetainingObject.Point1 = new GeometryPoint(); NonWaterRetainingObject.Point1.X = point1.X; NonWaterRetainingObject.Point1.Z = point1.Z; newSurfaceLine.AddCharacteristicPoint(NonWaterRetainingObject.Point1); } NonWaterRetainingObject.Point2 = newSurfaceLine.Geometry.GetPointAt(point2.X, 0, point2.Z); if (NonWaterRetainingObject.Point2 == null) { NonWaterRetainingObject.Point2 = new GeometryPoint(); NonWaterRetainingObject.Point2.X = point2.X; NonWaterRetainingObject.Point2.Z = point2.Z; newSurfaceLine.AddCharacteristicPoint(NonWaterRetainingObject.Point2); } point3 = RotatePoint(NonWaterRetainingObject.Point1, point3, summedRotationAngle); NonWaterRetainingObject.Point3 = newSurfaceLine.Geometry.GetPointAt(point3.X, 0, point3.Z); if (NonWaterRetainingObject.Point3 == null) { NonWaterRetainingObject.Point3 = new GeometryPoint(); NonWaterRetainingObject.Point3.X = point3.X; NonWaterRetainingObject.Point3.Z = point3.Z; newSurfaceLine.AddCharacteristicPoint(NonWaterRetainingObject.Point3); } NonWaterRetainingObject.Point4 = newSurfaceLine.Geometry.GetPointAt(point4.X, 0, point4.Z); if (NonWaterRetainingObject.Point4 == null) { NonWaterRetainingObject.Point4 = new GeometryPoint(); NonWaterRetainingObject.Point4.X = point4.X; NonWaterRetainingObject.Point4.Z = point4.Z; newSurfaceLine.AddCharacteristicPoint(NonWaterRetainingObject.Point4); } int nonWater1Index = -1, nonWater2Index = -1, nonWater3Index = -1, nonWater4Index = -1; // the phreaticline needs adaption, identify the NWO points as characteristic points so the PlLinesCreator can handle that. for (int i = 0; i < newSurfaceLine.CharacteristicPoints.Count; i++) { if (ReferenceEquals(newSurfaceLine.CharacteristicPoints[i].GeometryPoint, NonWaterRetainingObject.Point1)) { nonWater1Index = i; } if (ReferenceEquals(newSurfaceLine.CharacteristicPoints[i].GeometryPoint, NonWaterRetainingObject.Point2)) { nonWater2Index = i; } if (ReferenceEquals(newSurfaceLine.CharacteristicPoints[i].GeometryPoint, NonWaterRetainingObject.Point3)) { nonWater3Index = i; } if (ReferenceEquals(newSurfaceLine.CharacteristicPoints[i].GeometryPoint, NonWaterRetainingObject.Point4)) { nonWater4Index = i; } } newSurfaceLine.CharacteristicPoints.Annotate(nonWater1Index, CharacteristicPointType.NonWaterRetainingObjectPoint1); newSurfaceLine.CharacteristicPoints.Annotate(nonWater2Index, CharacteristicPointType.NonWaterRetainingObjectPoint2); newSurfaceLine.CharacteristicPoints.Annotate(nonWater3Index, CharacteristicPointType.NonWaterRetainingObjectPoint3); newSurfaceLine.CharacteristicPoints.Annotate(nonWater4Index, CharacteristicPointType.NonWaterRetainingObjectPoint4); newSurfaceLine.SortPoints(); } return newSurfaceLine; } return null; } private GeometryPoint RotatePoint(GeometryPoint centerPoint, GeometryPoint point, double rotationangle) { //a positive angle forces a anti clockwise rotation, a negative angle a clockwise rotation var radangle = rotationangle * Math.PI / 180; var dX = point.X - centerPoint.X; var dZ = point.Z - centerPoint.Z; point.X = (dX * Math.Cos(radangle)) - (dZ * Math.Sin(radangle)) + centerPoint.X; point.Z = (dX * Math.Sin(radangle)) + (dZ * Math.Cos(radangle)) + centerPoint.Z; return point; } /// /// /// /// /// private bool IsStillValid(double fitPositionX) { bool result; if (GridPosition == MStabGridPosition.Left) { result = (fitPositionX + NonWaterRetainingObject.Btotal() <= SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtRiver).X); } else { result = (fitPositionX >= SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).X); } return result; } private bool DoesNonWaterRetainingObjectCoincideWithDitch() { var result = true; // start by checking whether there is a ditch. var ditchDikeSide = SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DitchDikeSide); var ditchPolderSide = SurfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DitchPolderSide); if (ditchDikeSide != null && ditchPolderSide != null) { // nwo does not coincide if both point1 and point 4 are either left or right from ditch. Note that the ditch can only exist at the Polder Side! var ditchLeftX = ditchDikeSide.X; var ditchRightX = ditchPolderSide.X; result = (NonWaterRetainingObject.Point4.X < ditchLeftX) || (NonWaterRetainingObject.Point1.X > ditchRightX); } return !result; } } }