Index: DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/SurfaceLineAdapter.cs =================================================================== diff -u -r4000 -r4052 --- DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/SurfaceLineAdapter.cs (.../SurfaceLineAdapter.cs) (revision 4000) +++ DamEngine/trunk/src/Deltares.DamEngine.Calculators/DikesDesign/SurfaceLineAdapter.cs (.../SurfaceLineAdapter.cs) (revision 4052) @@ -27,501 +27,500 @@ using Deltares.DamEngine.Data.Geometry; using Deltares.DamEngine.Data.Geotechnics; -namespace Deltares.DamEngine.Calculators.DikesDesign +namespace Deltares.DamEngine.Calculators.DikesDesign; + +/// +/// Definition of a ditch +/// +public struct DitchDefinition { + public double OriginalX { get; set; } + public double DistanceFromToe { get; set; } + public double DistanceToBottomDikeSide { get; set; } + public double DistanceToBottomPolderSide { get; set; } + public double DistanceToEndDitch { get; set; } + public double DepthBottomDikeSide { get; set; } + public double DepthBottomPolderSide { get; set; } +} + +/// +/// Base class for adapting the surfaceline +/// +public abstract class SurfaceLineAdapter +{ + const double offset = 100.0; + + protected readonly Location Location; + protected readonly SurfaceLine2 surfaceLine; + protected double trafficLoadOffsetXfromRiverside; + protected double trafficLoadOffsetXfromPolderside; + protected double trafficLoadWidth; + protected bool hasTrafficLoad; + protected bool isTrafficLoadOnCrest; + protected double polderLevel; + /// - /// Definition of a ditch + /// Constructor /// - public struct DitchDefinition + /// + /// + /// + protected SurfaceLineAdapter(SurfaceLine2 surfaceLine, Location location, double scenarioPolderLevel) { - public double OriginalX { get; set; } - public double DistanceFromToe { get; set; } - public double DistanceToBottomDikeSide { get; set; } - public double DistanceToBottomPolderSide { get; set; } - public double DistanceToEndDitch { get; set; } - public double DepthBottomDikeSide { get; set; } - public double DepthBottomPolderSide { get; set; } + ThrowWhenSurfaceLineIsNull(surfaceLine); + ThrowWhenSurfaceLineDoesNotSatisfyToSpecification(surfaceLine); + this.surfaceLine = surfaceLine.FullDeepClone(); + Location = location; + polderLevel = scenarioPolderLevel; + RetainTrafficLoad(); } /// - /// Base class for adapting the surfaceline + /// Create traffic load based on the retained traffic load parameters + /// See documentation in Issue [MWDAM-548] /// - public abstract class SurfaceLineAdapter + protected void RestoreTrafficLoad() { - const double offset = 100.0; - - protected readonly Location Location; - protected readonly SurfaceLine2 surfaceLine; - protected double trafficLoadOffsetXfromRiverside; - protected double trafficLoadOffsetXfromPolderside; - protected double trafficLoadWidth; - protected bool hasTrafficLoad; - protected bool isTrafficLoadOnCrest; - protected double polderLevel; - - /// - /// Constructor - /// - /// - /// - /// - protected SurfaceLineAdapter(SurfaceLine2 surfaceLine, Location location, double scenarioPolderLevel) + if (hasTrafficLoad) { - ThrowWhenSurfaceLineIsNull(surfaceLine); - ThrowWhenSurfaceLineDoesNotSatisfyToSpecification(surfaceLine); - this.surfaceLine = surfaceLine.FullDeepClone(); - Location = location; - polderLevel = scenarioPolderLevel; - RetainTrafficLoad(); - } - - /// - /// Create traffic load based on the retained traffic load parameters - /// See documentation in Issue [MWDAM-548] - /// - protected void RestoreTrafficLoad() - { - if (hasTrafficLoad) + GeometryPoint pointDikeTopAtRiver = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtRiver); + GeometryPoint pointDikeTopAtPolder = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder); + if (isTrafficLoadOnCrest) { - GeometryPoint pointDikeTopAtRiver = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtRiver); - GeometryPoint pointDikeTopAtPolder = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder); - if (isTrafficLoadOnCrest) + // The traffic load will be restored relative to the binnenkruinlijn. If the leftside of the traffic load passes the buitenkruinlijn, + // the leftside of the traffic load will be placed on the buitenkruinlijn. It is possible that the rightside of the traffic load + // passes the buitenkruinlijn. + surfaceLine.SortPoints(); // line need to be sorted to use GetZAtX + double xCoordinate = pointDikeTopAtPolder.X - trafficLoadOffsetXfromPolderside - trafficLoadWidth; + if (xCoordinate < pointDikeTopAtRiver.X) { - // The traffic load will be restored relative to the binnenkruinlijn. If the leftside of the traffic load passes the buitenkruinlijn, - // the leftside of the traffic load will be placed on the buitenkruinlijn. It is possible that the rightside of the traffic load - // passes the buitenkruinlijn. - surfaceLine.SortPoints(); // line need to be sorted to use GetZAtX - double xCoordinate = pointDikeTopAtPolder.X - trafficLoadOffsetXfromPolderside - trafficLoadWidth; - if (xCoordinate < pointDikeTopAtRiver.X) - { - xCoordinate = pointDikeTopAtRiver.X; - } + xCoordinate = pointDikeTopAtRiver.X; + } - double zCoordinate = surfaceLine.Geometry.GetZatX(xCoordinate); - surfaceLine.EnsurePointOfType(xCoordinate, zCoordinate, CharacteristicPointType.TrafficLoadOutside); + double zCoordinate = surfaceLine.Geometry.GetZatX(xCoordinate); + surfaceLine.EnsurePointOfType(xCoordinate, zCoordinate, CharacteristicPointType.TrafficLoadOutside); - surfaceLine.SortPoints(); // line need to be sorted to use GetZAtX - xCoordinate += trafficLoadWidth; - zCoordinate = surfaceLine.Geometry.GetZatX(xCoordinate); - surfaceLine.EnsurePointOfType(xCoordinate, zCoordinate, CharacteristicPointType.TrafficLoadInside); - } - else - { - // The traffic load will be restore relative to the buitenkruinlijn. - surfaceLine.SortPoints(); // line need to be sorted to use GetZAtX - double xCoordinate = pointDikeTopAtRiver.X + trafficLoadOffsetXfromRiverside; - double zCoordinate = surfaceLine.Geometry.GetZatX(xCoordinate); - surfaceLine.EnsurePointOfType(xCoordinate, zCoordinate, CharacteristicPointType.TrafficLoadOutside); + surfaceLine.SortPoints(); // line need to be sorted to use GetZAtX + xCoordinate += trafficLoadWidth; + zCoordinate = surfaceLine.Geometry.GetZatX(xCoordinate); + surfaceLine.EnsurePointOfType(xCoordinate, zCoordinate, CharacteristicPointType.TrafficLoadInside); + } + else + { + // The traffic load will be restore relative to the buitenkruinlijn. + surfaceLine.SortPoints(); // line need to be sorted to use GetZAtX + double xCoordinate = pointDikeTopAtRiver.X + trafficLoadOffsetXfromRiverside; + double zCoordinate = surfaceLine.Geometry.GetZatX(xCoordinate); + surfaceLine.EnsurePointOfType(xCoordinate, zCoordinate, CharacteristicPointType.TrafficLoadOutside); - surfaceLine.SortPoints(); // line need to be sorted to use GetZAtX - xCoordinate = pointDikeTopAtRiver.X + trafficLoadOffsetXfromRiverside + trafficLoadWidth; - zCoordinate = surfaceLine.Geometry.GetZatX(xCoordinate); - surfaceLine.EnsurePointOfType(xCoordinate, zCoordinate, CharacteristicPointType.TrafficLoadInside); - } + surfaceLine.SortPoints(); // line need to be sorted to use GetZAtX + xCoordinate = pointDikeTopAtRiver.X + trafficLoadOffsetXfromRiverside + trafficLoadWidth; + zCoordinate = surfaceLine.Geometry.GetZatX(xCoordinate); + surfaceLine.EnsurePointOfType(xCoordinate, zCoordinate, CharacteristicPointType.TrafficLoadInside); } } + } - /// - /// Replaces the inside slope by adding the new end point of the slope to the surfaceline. - /// - /// - /// - /// point equal to the ShoulderTopInside when the new slope ends on that point else null - protected GeometryPoint ReplaceBaseInsideForNewSlope(GeometryPoint startPoint, double slopeTangent) + /// + /// Replaces the inside slope by adding the new end point of the slope to the surfaceline. + /// + /// + /// + /// point equal to the ShoulderTopInside when the new slope ends on that point else null + protected GeometryPoint ReplaceBaseInsideForNewSlope(GeometryPoint startPoint, double slopeTangent) + { + GeometryPoint result = null; + var line = new Line { - GeometryPoint result = null; - var line = new Line + BeginPoint = new Point2D(startPoint.X, startPoint.Z), + EndPoint = + new Point2D(startPoint.X + offset, + startPoint.Z - offset * slopeTangent) + }; + // Find the intersectionpoint(s) of the new slope with the surface line + IList intersectionpoints = surfaceLine.Geometry.IntersectionPointsXzWithLineXz(line); + Point2D newSlopeEndPoint = null; + if (intersectionpoints.Count > 0) + { + newSlopeEndPoint = intersectionpoints.First(); + // One of the intersection points can be the dike top which should not be replaced + if (newSlopeEndPoint.X == surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder).X && + newSlopeEndPoint.Z == surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder).Z) { - BeginPoint = new Point2D(startPoint.X, startPoint.Z), - EndPoint = - new Point2D(startPoint.X + offset, - startPoint.Z - offset * slopeTangent) - }; - // Find the intersectionpoint(s) of the new slope with the surface line - IList intersectionpoints = surfaceLine.Geometry.IntersectionPointsXzWithLineXz(line); - Point2D newSlopeEndPoint = null; - if (intersectionpoints.Count > 0) - { - newSlopeEndPoint = intersectionpoints.First(); - // One of the intersection points can be the dike top which should not be replaced - if (newSlopeEndPoint.X == surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder).X && - newSlopeEndPoint.Z == surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder).Z) + newSlopeEndPoint = null; + if (intersectionpoints.Count > 1) { - newSlopeEndPoint = null; - if (intersectionpoints.Count > 1) - { - newSlopeEndPoint = intersectionpoints[1]; - } + newSlopeEndPoint = intersectionpoints[1]; } } + } - if (newSlopeEndPoint == null) - { - throw new SurfaceLineAdapterException(Resources.SlopeErrorNoIntersection); - } + if (newSlopeEndPoint == null) + { + throw new SurfaceLineAdapterException(Resources.SlopeErrorNoIntersection); + } - GeometryPoint dikeToeAtPolder = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder); - if (newSlopeEndPoint.X > dikeToeAtPolder.X) + GeometryPoint dikeToeAtPolder = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder); + if (newSlopeEndPoint.X > dikeToeAtPolder.X) + { + // The new point is beyond the old dike toe so adapt that point. + surfaceLine.EnsurePointOfType(newSlopeEndPoint.X, newSlopeEndPoint.Z, CharacteristicPointType.DikeToeAtPolder); + // Remove all points between top and dike toe, + surfaceLine.RemoveSegmentBetween( + surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder).X, + newSlopeEndPoint.X); + } + else + { + GeometryPoint shoulderTopInside = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.ShoulderTopInside); + GeometryPoint shoulderBaseInside = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.ShoulderBaseInside); + if (shoulderBaseInside != null && shoulderTopInside != null) { - // The new point is beyond the old dike toe so adapt that point. - surfaceLine.EnsurePointOfType(newSlopeEndPoint.X, newSlopeEndPoint.Z, CharacteristicPointType.DikeToeAtPolder); - // Remove all points between top and dike toe, - surfaceLine.RemoveSegmentBetween( - surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder).X, - newSlopeEndPoint.X); - } - else - { - GeometryPoint shoulderTopInside = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.ShoulderTopInside); - GeometryPoint shoulderBaseInside = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.ShoulderBaseInside); - if (shoulderBaseInside != null && shoulderTopInside != null) + if (newSlopeEndPoint.X > shoulderTopInside.X) { - if (newSlopeEndPoint.X > shoulderTopInside.X) + // The new point is in the slope part of the shoulder (between ShoulderTopInside and Dike toe). So add a normal point + // at the new location and remove all points between the top and the new point. + //surfaceLine.RemovePoint(CharacteristicPointType.); + surfaceLine.EnsurePoint(newSlopeEndPoint.X, newSlopeEndPoint.Z); + surfaceLine.RemoveSegmentBetween( + surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder).X, + newSlopeEndPoint.X); + } + else + { + if (newSlopeEndPoint.X < shoulderTopInside.X) { - // The new point is in the slope part of the shoulder (between ShoulderTopInside and Dike toe). So add a normal point - // at the new location and remove all points between the top and the new point. - //surfaceLine.RemovePoint(CharacteristicPointType.); - surfaceLine.EnsurePoint(newSlopeEndPoint.X, newSlopeEndPoint.Z); - surfaceLine.RemoveSegmentBetween( - surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder).X, - newSlopeEndPoint.X); + // The new point is in the horizontal part of the shoulder. Remove all points between the current + // shoulderbase inside and its new location, then move the base + surfaceLine.RemoveSegmentBetween(shoulderBaseInside.X, newSlopeEndPoint.X); + surfaceLine.EnsurePointOfType(newSlopeEndPoint.X, newSlopeEndPoint.Z, + CharacteristicPointType.ShoulderBaseInside); } else { - if (newSlopeEndPoint.X < shoulderTopInside.X) + // The new point is equal to ShoulderTopInside. So remove that, add a normal point at its location + // and remove all points between the top and the new point. + CharacteristicPoint toBeRemoved = surfaceLine.CharacteristicPoints.FirstOrDefault( + cp => cp.CharacteristicPointType == CharacteristicPointType.ShoulderTopInside); + if (toBeRemoved != null) { - // The new point is in the horizontal part of the shoulder. Remove all points between the current - // shoulderbase inside and its new location, then move the base - surfaceLine.RemoveSegmentBetween(shoulderBaseInside.X, newSlopeEndPoint.X); - surfaceLine.EnsurePointOfType(newSlopeEndPoint.X, newSlopeEndPoint.Z, - CharacteristicPointType.ShoulderBaseInside); + surfaceLine.CharacteristicPoints.Remove(toBeRemoved); } - else - { - // The new point is equal to ShoulderTopInside. So remove that, add a normal point at its location - // and remove all points between the top and the new point. - CharacteristicPoint toBeRemoved = surfaceLine.CharacteristicPoints.FirstOrDefault( - cp => cp.CharacteristicPointType == CharacteristicPointType.ShoulderTopInside); - if (toBeRemoved != null) - { - surfaceLine.CharacteristicPoints.Remove(toBeRemoved); - } - surfaceLine.EnsurePoint(newSlopeEndPoint.X, newSlopeEndPoint.Z); - surfaceLine.RemoveSegmentBetween( - surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder).X, - newSlopeEndPoint.X); - result = new GeometryPoint(newSlopeEndPoint.X, newSlopeEndPoint.Z); - } + surfaceLine.EnsurePoint(newSlopeEndPoint.X, newSlopeEndPoint.Z); + surfaceLine.RemoveSegmentBetween( + surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder).X, + newSlopeEndPoint.X); + result = new GeometryPoint(newSlopeEndPoint.X, newSlopeEndPoint.Z); } } - else - { - // if the newtoe equals the diketoe, then just skip, nothing has to be changed. Otherwise there is a mistake! - if (!newSlopeEndPoint.LocationEquals(new Point2D(dikeToeAtPolder.X, dikeToeAtPolder.Z))) - { - // There is no shoulder so the slope must be too steep. - throw new SurfaceLineAdapterException(Resources.SlopeErrorNoIntersection); - } - } } - - surfaceLine.SortPoints(); - return result; - } - - /// - /// Gets the ditch definition. - /// - /// - /// - protected DitchDefinition? GetDitchDefinition() - { - var ditchDefinition = new DitchDefinition(); - if (surfaceLine.HasDitch() && surfaceLine.IsDitchCorrect()) - { - GeometryPoint ditchDikeSide = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DitchDikeSide); - ditchDefinition.DistanceFromToe = ditchDikeSide.X - - surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).X; - if (ditchDefinition.DistanceFromToe >= 0) - { - ditchDefinition.OriginalX = ditchDikeSide.X; - ditchDefinition.DistanceToBottomDikeSide = - surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.BottomDitchDikeSide).X - - ditchDikeSide.X; - ditchDefinition.DistanceToBottomPolderSide = - surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.BottomDitchPolderSide).X - - ditchDikeSide.X; - ditchDefinition.DistanceToEndDitch = - surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DitchPolderSide).X - - ditchDikeSide.X; - ditchDefinition.DepthBottomDikeSide = ditchDikeSide.Z - - surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.BottomDitchDikeSide).Z; - ditchDefinition.DepthBottomPolderSide = ditchDikeSide.Z - - surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.BottomDitchPolderSide).Z; - return ditchDefinition; - } - } else { - if (surfaceLine.HasDitch()) + // if the newtoe equals the diketoe, then just skip, nothing has to be changed. Otherwise there is a mistake! + if (!newSlopeEndPoint.LocationEquals(new Point2D(dikeToeAtPolder.X, dikeToeAtPolder.Z))) { - // Incorrect ditch is an error here, this should have been checked already - throw new SurfaceLineAdapterException(Resources.SurfaceLineAdapterDikeDitchError); + // There is no shoulder so the slope must be too steep. + throw new SurfaceLineAdapterException(Resources.SlopeErrorNoIntersection); } } - - return null; } - /// - /// Removes the existing ditch. - /// - /// The ditch definition. - protected void RemoveExistingDitch(DitchDefinition? ditchDefinition) + surfaceLine.SortPoints(); + return result; + } + + /// + /// Gets the ditch definition. + /// + /// + /// + protected DitchDefinition? GetDitchDefinition() + { + var ditchDefinition = new DitchDefinition(); + if (surfaceLine.HasDitch() && surfaceLine.IsDitchCorrect()) { - if (ditchDefinition != null) + GeometryPoint ditchDikeSide = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DitchDikeSide); + ditchDefinition.DistanceFromToe = ditchDikeSide.X - + surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder).X; + if (ditchDefinition.DistanceFromToe >= 0) { - // It is possible that DikeToeAtPolder coinsides with DitchDikeSide or SurfaceLevelInside with DitchPolderSide - // If that is the case, those characteristic points should be restored - // So first save those characteristic points - GeometryPoint dikeToeAtPolder = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder); - GeometryPoint surfaceLevelInside = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelInside); - // The characteristic points DitchDikeSide and DitchPolderSide should be removed, but the points itself should be restored, - // else the surfaceline will get a new form. So save those points - GeometryPoint ditchDikeSide = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DitchDikeSide); - GeometryPoint ditchPolderSide = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DitchPolderSide); - surfaceLine.RemoveSegmentIncluding( - surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DitchDikeSide).X, - surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DitchPolderSide).X); - // Now restore characteristic points DikeToeAtPolder and SurfaceLevelInside if necessary - surfaceLine.EnsurePointOfType(dikeToeAtPolder.X, dikeToeAtPolder.Z, CharacteristicPointType.DikeToeAtPolder); - surfaceLine.EnsurePointOfType(surfaceLevelInside.X, surfaceLevelInside.Z, CharacteristicPointType.SurfaceLevelInside); - // Now restore points ditchDikeSide and ditchPolderSide - surfaceLine.EnsurePoint(ditchDikeSide.X, ditchDikeSide.Z); - surfaceLine.EnsurePoint(ditchPolderSide.X, ditchPolderSide.Z); - surfaceLine.SortPoints(); + ditchDefinition.OriginalX = ditchDikeSide.X; + ditchDefinition.DistanceToBottomDikeSide = + surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.BottomDitchDikeSide).X - + ditchDikeSide.X; + ditchDefinition.DistanceToBottomPolderSide = + surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.BottomDitchPolderSide).X - + ditchDikeSide.X; + ditchDefinition.DistanceToEndDitch = + surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DitchPolderSide).X - + ditchDikeSide.X; + ditchDefinition.DepthBottomDikeSide = ditchDikeSide.Z - + surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.BottomDitchDikeSide).Z; + ditchDefinition.DepthBottomPolderSide = ditchDikeSide.Z - + surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.BottomDitchPolderSide).Z; + return ditchDefinition; } } - - /// - /// Restores the ditch. - /// - /// The ditch definition. - /// - protected void RestoreDitch(DitchDefinition? ditchDefinition) + else { - if (ditchDefinition == null) + if (surfaceLine.HasDitch()) { - return; + // Incorrect ditch is an error here, this should have been checked already + throw new SurfaceLineAdapterException(Resources.SurfaceLineAdapterDikeDitchError); } + } + return null; + } + + /// + /// Removes the existing ditch. + /// + /// The ditch definition. + protected void RemoveExistingDitch(DitchDefinition? ditchDefinition) + { + if (ditchDefinition != null) + { + // It is possible that DikeToeAtPolder coinsides with DitchDikeSide or SurfaceLevelInside with DitchPolderSide + // If that is the case, those characteristic points should be restored + // So first save those characteristic points GeometryPoint dikeToeAtPolder = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder); - double distanceToNewToe = ditchDefinition.Value.OriginalX - dikeToeAtPolder.X; - double xDitchDikeSide; - DitchCoordinates coors; + GeometryPoint surfaceLevelInside = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelInside); + // The characteristic points DitchDikeSide and DitchPolderSide should be removed, but the points itself should be restored, + // else the surfaceline will get a new form. So save those points + GeometryPoint ditchDikeSide = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DitchDikeSide); + GeometryPoint ditchPolderSide = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DitchPolderSide); + surfaceLine.RemoveSegmentIncluding( + surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DitchDikeSide).X, + surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DitchPolderSide).X); + // Now restore characteristic points DikeToeAtPolder and SurfaceLevelInside if necessary + surfaceLine.EnsurePointOfType(dikeToeAtPolder.X, dikeToeAtPolder.Z, CharacteristicPointType.DikeToeAtPolder); + surfaceLine.EnsurePointOfType(surfaceLevelInside.X, surfaceLevelInside.Z, CharacteristicPointType.SurfaceLevelInside); + // Now restore points ditchDikeSide and ditchPolderSide + surfaceLine.EnsurePoint(ditchDikeSide.X, ditchDikeSide.Z); + surfaceLine.EnsurePoint(ditchPolderSide.X, ditchPolderSide.Z); surfaceLine.SortPoints(); + } + } - // TODO: #the Following code is not correct; you should also look at the setting of Location.UseNewMinDistanceDikeToeStartDitch - // First determine all coordinates - if (distanceToNewToe < Location.NewMinDistanceDikeToeStartDitch && distanceToNewToe != ditchDefinition.Value.DistanceFromToe) + /// + /// Restores the ditch. + /// + /// The ditch definition. + /// + protected void RestoreDitch(DitchDefinition? ditchDefinition) + { + if (ditchDefinition == null) + { + return; + } + + GeometryPoint dikeToeAtPolder = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeToeAtPolder); + double distanceToNewToe = ditchDefinition.Value.OriginalX - dikeToeAtPolder.X; + double xDitchDikeSide; + DitchCoordinates coors; + surfaceLine.SortPoints(); + + // TODO: #the Following code is not correct; you should also look at the setting of Location.UseNewMinDistanceDikeToeStartDitch + // First determine all coordinates + if (distanceToNewToe < Location.NewMinDistanceDikeToeStartDitch && distanceToNewToe != ditchDefinition.Value.DistanceFromToe) + { + // Ditch needs to be moved as it is less then the minimum required distance from the new toe + xDitchDikeSide = dikeToeAtPolder.X + + Location.NewMinDistanceDikeToeStartDitch; + if (Location.UseNewDitchDefinition) { - // Ditch needs to be moved as it is less then the minimum required distance from the new toe - xDitchDikeSide = dikeToeAtPolder.X + - Location.NewMinDistanceDikeToeStartDitch; - if (Location.UseNewDitchDefinition) - { - // Use the new definition instead of the old shape - coors = GetCoordinatesForNewShape(xDitchDikeSide); - } - else - { - // replace the ditch with the same shape. - coors = GetCoordinatesForOldShape(xDitchDikeSide, ditchDefinition.Value); - } + // Use the new definition instead of the old shape + coors = GetCoordinatesForNewShape(xDitchDikeSide); } else { - // replace the ditch with the same shape and same location. - xDitchDikeSide = dikeToeAtPolder.X + - distanceToNewToe; + // replace the ditch with the same shape. coors = GetCoordinatesForOldShape(xDitchDikeSide, ditchDefinition.Value); } - - // check if the new bottom is beneath the surface line. If not, the ditch must not be replaced at all - if (coors.ZBottom >= surfaceLine.Geometry.GetZatX(coors.XBottomAtDike) || - coors.ZBottom >= surfaceLine.Geometry.GetZatX(coors.XBottomAtPolder)) - { - return; - } - - double surfaceLevelInsideX = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelInside).X; - if (coors.XAtPolder > surfaceLevelInsideX) - { - throw new SurfaceLineAdapterException(Resources.SurfaceLineHeightAdapterDitchOutsideSurfaceLine); - } - - // Add the outside points of the new ditch - surfaceLine.EnsurePointOfType(coors.XAtDike, coors.ZAtDike, CharacteristicPointType.DitchDikeSide); - surfaceLine.EnsurePointOfType(coors.XAtPolder, coors.ZAtPolder, CharacteristicPointType.DitchPolderSide); - // Delete all existing points in the new ditch - surfaceLine.RemoveSegmentBetween(coors.XAtDike, coors.XAtPolder); - // Add the bottom of the ditch - surfaceLine.EnsurePointOfType(coors.XBottomAtDike, coors.ZBottom, CharacteristicPointType.BottomDitchDikeSide); - surfaceLine.EnsurePointOfType(coors.XBottomAtPolder, coors.ZBottom, CharacteristicPointType.BottomDitchPolderSide); - surfaceLine.SortPoints(); } + else + { + // replace the ditch with the same shape and same location. + xDitchDikeSide = dikeToeAtPolder.X + + distanceToNewToe; + coors = GetCoordinatesForOldShape(xDitchDikeSide, ditchDefinition.Value); + } - /// - /// Store the parameters with which the traffic load can be restored. - /// The traffic load will be retained relative to the buitenkruinlijn. - /// If the traffic load is completly inside area between buitenkruinlijn and binnenkruinlijn the following will be done: - /// - The traffic load will be retained relative to the binnenkruinlijn. If the leftside of the traffic load passes the buitenkruinlijn, - /// the leftside of the traffic load will be placed on the buitenkruinlijn. It is possible that the rightside of the traffic load - /// passes the buitenkruinlijn. - /// See documentation in Issue [MWDAM-548] - /// - private void RetainTrafficLoad() + // check if the new bottom is beneath the surface line. If not, the ditch must not be replaced at all + if (coors.ZBottom >= surfaceLine.Geometry.GetZatX(coors.XBottomAtDike) || + coors.ZBottom >= surfaceLine.Geometry.GetZatX(coors.XBottomAtPolder)) { - GeometryPoint pointTrafficLoadInside = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.TrafficLoadInside); - GeometryPoint pointTrafficLoadOutside = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.TrafficLoadOutside); - GeometryPoint pointDikeTopAtRiver = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtRiver); - GeometryPoint pointDikeTopAtPolder = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder); + return; + } - hasTrafficLoad = ((pointTrafficLoadInside != null) && (pointTrafficLoadOutside != null)); - if (hasTrafficLoad) - { - trafficLoadOffsetXfromRiverside = pointTrafficLoadOutside.X - pointDikeTopAtRiver.X; - trafficLoadOffsetXfromPolderside = pointDikeTopAtPolder.X - pointTrafficLoadInside.X; - trafficLoadWidth = pointTrafficLoadInside.X - pointTrafficLoadOutside.X; - isTrafficLoadOnCrest = (pointTrafficLoadOutside.X >= pointDikeTopAtRiver.X) && (pointTrafficLoadInside.X <= pointDikeTopAtPolder.X); - } + double surfaceLevelInsideX = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelInside).X; + if (coors.XAtPolder > surfaceLevelInsideX) + { + throw new SurfaceLineAdapterException(Resources.SurfaceLineHeightAdapterDitchOutsideSurfaceLine); } - /// - /// Throws an exception when the surface line does not comply to the specification - /// - /// - /// The specification is that there: - /// - There are should be at least 4 points in the surface line - /// - must be a dike - /// - that the point coords are non zero - /// - There is a surface line when a shoulder exists - /// - /// The candidate to test - private static void ThrowWhenSurfaceLineDoesNotSatisfyToSpecification(SurfaceLine2 surfaceLine) + // Add the outside points of the new ditch + surfaceLine.EnsurePointOfType(coors.XAtDike, coors.ZAtDike, CharacteristicPointType.DitchDikeSide); + surfaceLine.EnsurePointOfType(coors.XAtPolder, coors.ZAtPolder, CharacteristicPointType.DitchPolderSide); + // Delete all existing points in the new ditch + surfaceLine.RemoveSegmentBetween(coors.XAtDike, coors.XAtPolder); + // Add the bottom of the ditch + surfaceLine.EnsurePointOfType(coors.XBottomAtDike, coors.ZBottom, CharacteristicPointType.BottomDitchDikeSide); + surfaceLine.EnsurePointOfType(coors.XBottomAtPolder, coors.ZBottom, CharacteristicPointType.BottomDitchPolderSide); + surfaceLine.SortPoints(); + } + + /// + /// Store the parameters with which the traffic load can be restored. + /// The traffic load will be retained relative to the buitenkruinlijn. + /// If the traffic load is completly inside area between buitenkruinlijn and binnenkruinlijn the following will be done: + /// - The traffic load will be retained relative to the binnenkruinlijn. If the leftside of the traffic load passes the buitenkruinlijn, + /// the leftside of the traffic load will be placed on the buitenkruinlijn. It is possible that the rightside of the traffic load + /// passes the buitenkruinlijn. + /// See documentation in Issue [MWDAM-548] + /// + private void RetainTrafficLoad() + { + GeometryPoint pointTrafficLoadInside = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.TrafficLoadInside); + GeometryPoint pointTrafficLoadOutside = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.TrafficLoadOutside); + GeometryPoint pointDikeTopAtRiver = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtRiver); + GeometryPoint pointDikeTopAtPolder = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder); + + hasTrafficLoad = ((pointTrafficLoadInside != null) && (pointTrafficLoadOutside != null)); + if (hasTrafficLoad) { - ThrowWhenSurfaceLineHasNoOrLessThenFourPoints(surfaceLine.Geometry.Points); - ThrowWhenSurfaceHasNoDike(surfaceLine); - ThrowWhenSurfaceLineHasAShoulderInsideAndNoSurfaceLevel(surfaceLine, - surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelInside)); + trafficLoadOffsetXfromRiverside = pointTrafficLoadOutside.X - pointDikeTopAtRiver.X; + trafficLoadOffsetXfromPolderside = pointDikeTopAtPolder.X - pointTrafficLoadInside.X; + trafficLoadWidth = pointTrafficLoadInside.X - pointTrafficLoadOutside.X; + isTrafficLoadOnCrest = (pointTrafficLoadOutside.X >= pointDikeTopAtRiver.X) && (pointTrafficLoadInside.X <= pointDikeTopAtPolder.X); + } + } - GeometryPoint p1 = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtRiver); - GeometryPoint p2 = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder); + /// + /// Throws an exception when the surface line does not comply to the specification + /// + /// + /// The specification is that there: + /// - There are should be at least 4 points in the surface line + /// - must be a dike + /// - that the point coords are non zero + /// - There is a surface line when a shoulder exists + /// + /// The candidate to test + private static void ThrowWhenSurfaceLineDoesNotSatisfyToSpecification(SurfaceLine2 surfaceLine) + { + ThrowWhenSurfaceLineHasNoOrLessThenFourPoints(surfaceLine.Geometry.Points); + ThrowWhenSurfaceHasNoDike(surfaceLine); + ThrowWhenSurfaceLineHasAShoulderInsideAndNoSurfaceLevel(surfaceLine, + surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.SurfaceLevelInside)); - var zeroPoint = new GeometryPoint(); + GeometryPoint p1 = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtRiver); + GeometryPoint p2 = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.DikeTopAtPolder); - if (zeroPoint.LocationEquals(p1) || zeroPoint.LocationEquals(p2)) - { - throw new SurfaceLineAdapterException(Resources.SurfaceLineAdapterDikeHeightError); - } + var zeroPoint = new GeometryPoint(); - if (surfaceLine.HasShoulderInside()) - { - p1 = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.ShoulderTopInside); - p2 = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.ShoulderBaseInside); - if (zeroPoint.LocationEquals(p1) || zeroPoint.LocationEquals(p2)) - { - throw new SurfaceLineAdapterException(Resources.SurfaceLineAdapterShoulderHeightError); - } - } + if (zeroPoint.LocationEquals(p1) || zeroPoint.LocationEquals(p2)) + { + throw new SurfaceLineAdapterException(Resources.SurfaceLineAdapterDikeHeightError); } - private static void ThrowWhenSurfaceLineHasAShoulderInsideAndNoSurfaceLevel(SurfaceLine2 surfaceLine, GeometryPoint surfaceLevelPoint) + if (surfaceLine.HasShoulderInside()) { - if (surfaceLine.HasShoulderInside() && surfaceLevelPoint == null) + p1 = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.ShoulderTopInside); + p2 = surfaceLine.CharacteristicPoints.GetGeometryPoint(CharacteristicPointType.ShoulderBaseInside); + if (zeroPoint.LocationEquals(p1) || zeroPoint.LocationEquals(p2)) { - throw new SurfaceLineAdapterException(Resources.SurfaceLineAdapterSurfaceLevelError); + throw new SurfaceLineAdapterException(Resources.SurfaceLineAdapterShoulderHeightError); } } + } - private static void ThrowWhenSurfaceHasNoDike(SurfaceLine2 surfaceLine) + private static void ThrowWhenSurfaceLineHasAShoulderInsideAndNoSurfaceLevel(SurfaceLine2 surfaceLine, GeometryPoint surfaceLevelPoint) + { + if (surfaceLine.HasShoulderInside() && surfaceLevelPoint == null) { - if (!surfaceLine.HasDike()) - { - throw new SurfaceLineAdapterException(Resources.SurfaceLineAdapterInvalidDikeError); - } + throw new SurfaceLineAdapterException(Resources.SurfaceLineAdapterSurfaceLevelError); } + } - private static void ThrowWhenSurfaceLineIsNull(SurfaceLine2 surfaceLine) + private static void ThrowWhenSurfaceHasNoDike(SurfaceLine2 surfaceLine) + { + if (!surfaceLine.HasDike()) { - if (surfaceLine == null) - { - throw new ArgumentNullException(Resources.SurfaceLineAdapterNoDikeError); - } + throw new SurfaceLineAdapterException(Resources.SurfaceLineAdapterInvalidDikeError); } + } - private static void ThrowWhenSurfaceLineHasNoOrLessThenFourPoints(ICollection points) + private static void ThrowWhenSurfaceLineIsNull(SurfaceLine2 surfaceLine) + { + if (surfaceLine == null) { - if (points == null || points.Count < 4) - { - throw new SurfaceLineAdapterException(Resources.SurfaceLineAdapterNoDikePointsError); - } + throw new ArgumentNullException(Resources.SurfaceLineAdapterNoDikeError); } + } - private DitchCoordinates GetCoordinatesForOldShape(double xDitchDike, DitchDefinition ditchDefinition) + private static void ThrowWhenSurfaceLineHasNoOrLessThenFourPoints(ICollection points) + { + if (points == null || points.Count < 4) { - var res = new DitchCoordinates(); - res.XAtDike = xDitchDike; - res.ZAtDike = surfaceLine.Geometry.GetZatX(res.XAtDike); - res.XBottomAtDike = xDitchDike + ditchDefinition.DistanceToBottomDikeSide; - res.ZBottom = res.ZAtDike - ditchDefinition.DepthBottomDikeSide; - res.XBottomAtPolder = xDitchDike + ditchDefinition.DistanceToBottomPolderSide; - res.XAtPolder = xDitchDike + ditchDefinition.DistanceToEndDitch; - res.ZAtPolder = surfaceLine.Geometry.GetZatX(res.XAtPolder); - return res; + throw new SurfaceLineAdapterException(Resources.SurfaceLineAdapterNoDikePointsError); } + } - private DitchCoordinates GetCoordinatesForNewShape(double xDitchDike) - { - var res = new DitchCoordinates(); - res.XAtDike = xDitchDike; - res.ZAtDike = surfaceLine.Geometry.GetZatX(res.XAtDike); - // Depth of the ditch is defined towards PolderLevel - res.ZBottom = polderLevel - Location.NewDepthDitch; - res.XBottomAtDike = xDitchDike + (res.ZAtDike - res.ZBottom) * Location.NewSlopeAngleDitch; - res.XBottomAtPolder = res.XBottomAtDike + Location.NewWidthDitchBottom; - var line = new Line - { - BeginPoint = new Point2D(res.XBottomAtPolder, res.ZBottom), - EndPoint = new Point2D(res.XBottomAtPolder + offset, - res.ZBottom + offset * Location.NewSlopeAngleDitch) - }; - // Find the intersectionpoint(s) of the new ditch slope with the surface line - IList intersectionpoints = surfaceLine.Geometry.IntersectionPointsXzWithLineXz(line); - if (intersectionpoints.Count > 0) - { - res.XAtPolder = intersectionpoints[0].X; - res.ZAtPolder = intersectionpoints[0].Z; - } - else - { - //new slope of ditch does not intersect with surface line (most probably because the bottom is too high) - throw new SurfaceLineAdapterException(Resources.SurfaceLineAdapterDitchSlopeError); - } + private DitchCoordinates GetCoordinatesForOldShape(double xDitchDike, DitchDefinition ditchDefinition) + { + var res = new DitchCoordinates(); + res.XAtDike = xDitchDike; + res.ZAtDike = surfaceLine.Geometry.GetZatX(res.XAtDike); + res.XBottomAtDike = xDitchDike + ditchDefinition.DistanceToBottomDikeSide; + res.ZBottom = res.ZAtDike - ditchDefinition.DepthBottomDikeSide; + res.XBottomAtPolder = xDitchDike + ditchDefinition.DistanceToBottomPolderSide; + res.XAtPolder = xDitchDike + ditchDefinition.DistanceToEndDitch; + res.ZAtPolder = surfaceLine.Geometry.GetZatX(res.XAtPolder); + return res; + } - return res; + private DitchCoordinates GetCoordinatesForNewShape(double xDitchDike) + { + var res = new DitchCoordinates(); + res.XAtDike = xDitchDike; + res.ZAtDike = surfaceLine.Geometry.GetZatX(res.XAtDike); + // Depth of the ditch is defined towards PolderLevel + res.ZBottom = polderLevel - Location.NewDepthDitch; + res.XBottomAtDike = xDitchDike + (res.ZAtDike - res.ZBottom) * Location.NewSlopeAngleDitch; + res.XBottomAtPolder = res.XBottomAtDike + Location.NewWidthDitchBottom; + var line = new Line + { + BeginPoint = new Point2D(res.XBottomAtPolder, res.ZBottom), + EndPoint = new Point2D(res.XBottomAtPolder + offset, + res.ZBottom + offset * Location.NewSlopeAngleDitch) + }; + // Find the intersectionpoint(s) of the new ditch slope with the surface line + IList intersectionpoints = surfaceLine.Geometry.IntersectionPointsXzWithLineXz(line); + if (intersectionpoints.Count > 0) + { + res.XAtPolder = intersectionpoints[0].X; + res.ZAtPolder = intersectionpoints[0].Z; } - - private struct DitchCoordinates + else { - public double XAtDike; - public double ZAtDike; - public double XBottomAtDike; - public double ZBottom; - public double XBottomAtPolder; - public double XAtPolder; - public double ZAtPolder; + //new slope of ditch does not intersect with surface line (most probably because the bottom is too high) + throw new SurfaceLineAdapterException(Resources.SurfaceLineAdapterDitchSlopeError); } + + return res; } + + private struct DitchCoordinates + { + public double XAtDike; + public double ZAtDike; + public double XBottomAtDike; + public double ZBottom; + public double XBottomAtPolder; + public double XAtPolder; + public double ZAtPolder; + } } \ No newline at end of file