Index: DamEngine/trunk/src/Deltares.DamEngine.Data/GeometryExport/GeometryExporter.cs =================================================================== diff -u -r5387 -r5460 --- DamEngine/trunk/src/Deltares.DamEngine.Data/GeometryExport/GeometryExporter.cs (.../GeometryExporter.cs) (revision 5387) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/GeometryExport/GeometryExporter.cs (.../GeometryExporter.cs) (revision 5460) @@ -33,9 +33,9 @@ /// /// Next constants are used for debugging purposes /// - public const string VisualizationFolder = @"C:\Dam\DamTools\GeometryVisualizer\"; //#John, for debugging purposes + // public const string VisualizationFolder = @"C:\Dam\DamTools\GeometryVisualizer\"; //#John, for debugging purposes //public const string GeometryExporter.VisualizationFolder = @"D:\src\dam\DamTools\GeometryVisualizer\"; //#Tom - public const string ExportJasonFile = "GeometryWithSurf.json"; //for debugging purposes + public const string ExportJasonFile = "GeometryAndSurfaceLinePlot.json"; //for debugging purposes /// /// Export the geometry to a json file @@ -140,4 +140,75 @@ writer.WriteLine("[END CALC POINTS]"); } } + + /// + /// Export all geometry items to a file including newly created points and curves and inner loops + /// + /// + /// + public static void ExportFullGeometryToFile(GeometryData geometry, string fileName) + { + using (var writer = new StreamWriter(fileName)) + { + // Export newly effected points + writer.WriteLine("[BEGIN NEWLY EFFECTED POINTS]"); + foreach (Point2D point in geometry.NewlyEffectedPoints) + { + writer.WriteLine($"{point.X}, {point.Z}"); + } + writer.WriteLine("[END NEWLY EFFECTED POINTS]"); + + // Export newly effected curves + writer.WriteLine("[BEGIN NEWLY EFFECTED CURVES]"); + foreach (GeometryCurve curve in geometry.NewlyEffectedCurves) + { + writer.WriteLine($"Curve: ({curve.HeadPoint.X}, {curve.HeadPoint.Z}) - ({curve.EndPoint.X}, {curve.EndPoint.Z})"); + } + writer.WriteLine("[END NEWLY EFFECTED CURVES]"); + + // Export points + writer.WriteLine("[BEGIN POINTS]"); + foreach (Point2D point in geometry.Points) + { + writer.WriteLine($"{point.X}, {point.Z}"); + } + writer.WriteLine("[END POINTS]"); + + // Export curves + writer.WriteLine("[BEGIN CURVES]"); + foreach (GeometryCurve curve in geometry.Curves) + { + writer.WriteLine($"Curve: ({curve.HeadPoint.X}, {curve.HeadPoint.Z}) - ({curve.EndPoint.X}, {curve.EndPoint.Z})"); + } + writer.WriteLine("[END CURVES]"); + + // Export surfaces + writer.WriteLine("[BEGIN SURFACES]"); + foreach (GeometrySurface surface in geometry.Surfaces) + { + // Outerloop + writer.WriteLine($"Surface: {surface.Name}"); + writer.WriteLine($"OuterLoop: {surface.OuterLoop.Name}"); + foreach (GeometryCurve curve in surface.OuterLoop.CurveList) + { + writer.WriteLine($"({curve.HeadPoint.X}, {curve.HeadPoint.Z}) - ({curve.EndPoint.X}, {curve.EndPoint.Z})"); + } + + writer.WriteLine(""); + + // Innerloops + foreach (GeometryLoop innerLoop in surface.InnerLoops) + { + writer.WriteLine($"InnerLoop: {innerLoop.Name}"); + foreach (GeometryCurve curve in innerLoop.CurveList) + { + writer.WriteLine($"Curve: ({curve.HeadPoint.X}, {curve.HeadPoint.Z}) - ({curve.EndPoint.X}, {curve.EndPoint.Z})"); + } + + writer.WriteLine(""); + } + } + writer.WriteLine("[END SURFACES]"); + } + } } \ No newline at end of file Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Standard/ObjectExtensions.cs =================================================================== diff -u -r4540 -r5460 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Standard/ObjectExtensions.cs (.../ObjectExtensions.cs) (revision 4540) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Standard/ObjectExtensions.cs (.../ObjectExtensions.cs) (revision 5460) @@ -270,8 +270,8 @@ /// public static void CloneProperties(this T1 origin, T2 destination, params string[] excludedProperties) { - // Instantiate if necessary - if (destination == null) + // Destination must be instantiated + if (destination.Equals(default(T2))) { throw new ArgumentNullException("destination", "Destination object must first be instantiated."); } Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryCurve.cs =================================================================== diff -u -r5073 -r5460 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryCurve.cs (.../GeometryCurve.cs) (revision 5073) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryCurve.cs (.../GeometryCurve.cs) (revision 5460) @@ -75,29 +75,24 @@ { get { - if (!string.IsNullOrEmpty(base.Name)) + if (string.IsNullOrEmpty(base.Name)) { - return base.Name; - } + var text = ""; + if (HeadPoint != null) + { + text += HeadPoint.ToString()?.Trim(); + } - var text = ""; - if (HeadPoint != null) - { - text += HeadPoint.ToString().Trim(); + text += "-"; + if (EndPoint != null) + { + text += EndPoint.ToString()?.Trim(); + } + base.Name = text; } - - text += "-"; - if (EndPoint != null) - { - text += EndPoint.ToString().Trim(); - } - - return text; + return base.Name; } - set - { - base.Name = value; - } + set => base.Name = value; } /// @@ -237,10 +232,15 @@ /// public void AssignSurfacesFromCurve(GeometryCurve aCurve) { - if (aCurve.SurfaceAtLeft == SurfaceAtLeft && aCurve.SurfaceAtRight == SurfaceAtRight) - return; - SurfaceAtRight = aCurve.SurfaceAtRight; - SurfaceAtLeft = aCurve.SurfaceAtLeft; + if (aCurve.SurfaceAtLeft != SurfaceAtLeft) + { + SurfaceAtLeft = aCurve.SurfaceAtLeft; + } + + if (aCurve.SurfaceAtRight != SurfaceAtRight) + { + SurfaceAtRight = aCurve.SurfaceAtRight; + } } /// Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryGenerator.cs =================================================================== diff -u -r5222 -r5460 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryGenerator.cs (.../GeometryGenerator.cs) (revision 5222) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryGenerator.cs (.../GeometryGenerator.cs) (revision 5460) @@ -40,6 +40,8 @@ private readonly List newlyDetectedSurfaceList = new List(); + private bool isRegenerationOn; + /// /// Regenerates the geometry. /// @@ -58,7 +60,7 @@ SetupCurveSurfaceAssociations(); var firstRegeneration = true; - + isRegenerationOn = true; while (true) { // break up all curves at intersections @@ -97,6 +99,7 @@ firstRegeneration = false; } + isRegenerationOn = false; } /// @@ -302,6 +305,18 @@ curve.EndPoint = doublePoints[doublePoint]; } } + foreach (GeometryCurve curve in geometryData.NewlyEffectedCurves) + { + if (curve.HeadPoint == doublePoint) + { + curve.HeadPoint = doublePoints[doublePoint]; + } + + if (curve.EndPoint == doublePoint) + { + curve.EndPoint = doublePoints[doublePoint]; + } + } } // remove curves which have the same head as end point @@ -345,7 +360,7 @@ geometryData.NewlyEffectedPoints.Remove(point); if (!geometryData.NewlyEffectedPoints.Contains(doublePoints[point])) { - geometryData.NewlyEffectedPoints.Add(doublePoints[point]); + geometryData.NewlyEffectedPoints.Add(doublePoints[point]); //#Bka why should this be needed? point is already in geometry } } } @@ -979,15 +994,15 @@ Point2D pointXz2 = geometryCurve1.EndPoint; Point2D pointXz3 = geometryCurve2.HeadPoint; Point2D pointXz4 = geometryCurve2.EndPoint; - if (geometryCurve1 != geometryCurve2 && + if (!geometryCurve1.LocationEquals(geometryCurve2) && // geometryCurve1 != geometryCurve2 && !RegenerateParallelCurves(geometryCurve2, geometryCurve1, ref isCurveInserted) && Routines2D.DetermineIf2DLinesIntersectStrickly(pointXz1, pointXz2, pointXz3, pointXz4, out Point2D intersectionPoint) == LineIntersection.Intersects) { if (!Routines2D.DetermineIfPointsCoincide(pointXz1.X, pointXz1.Z, intersectionPoint.X, intersectionPoint.Z, 0.001) && !Routines2D.DetermineIfPointsCoincide(pointXz2.X, pointXz2.Z, intersectionPoint.X, intersectionPoint.Z, 0.001)) { - Point2D point = this.geometryData.CreatePoint(new Point2D(intersectionPoint.X, intersectionPoint.Z), true); + Point2D point = geometryData.CreatePoint(new Point2D(intersectionPoint.X, intersectionPoint.Z), true); SplitCurve(geometryCurve1, point); flag = true; } @@ -1268,8 +1283,8 @@ private GeometryCurve SplitCurve(GeometryCurve curve, Point2D aPointOnCurve) { if (aPointOnCurve.LocationEquals(curve.HeadPoint) || aPointOnCurve.LocationEquals(curve.EndPoint)) - return (GeometryCurve) null; - GeometryCurve curve1 = geometryData.CreateCurve((List) null, aPointOnCurve, curve.EndPoint); + return null; + GeometryCurve curve1 = geometryData.CreateCurve(aPointOnCurve, curve.EndPoint); curve.EndPoint = curve1.HeadPoint; curve1.AssignSurfacesFromCurve(curve); this.CheckAndAddToIntersectedCurveList(curve); @@ -1317,20 +1332,27 @@ foreach (GeometryCurve aCurve in list) geometryData.DeleteCurve(aCurve, true); list.Clear(); + List intList = new List(); for (int index1 = 0; index1 < geometryData.Curves.Count; ++index1) { GeometryCurve curve1 = geometryData.Curves[index1]; for (int index2 = index1 + 1; index2 < geometryData.Curves.Count; ++index2) { GeometryCurve curve2 = geometryData.Curves[index2]; if (curve1.HeadPoint == curve2.HeadPoint && curve1.EndPoint == curve2.EndPoint) + { list.Add(curve2); + intList.Add(index2); + } else if (curve1.HeadPoint == curve2.EndPoint && curve1.EndPoint == curve2.HeadPoint) + { list.Add(curve2); + intList.Add(index2); + } } } foreach (GeometryCurve aCurve in list) - geometryData.DeleteCurve(aCurve, true); + geometryData.DeleteCurve(aCurve, true); //#Bka was true, moet ook true zijn } private void CheckAndAddToIntersectedCurveList(GeometryCurve aCurve) @@ -1351,4 +1373,17 @@ SplitCurve(aCoincidentCurves[index], aPoint); } + /// + /// Gets a value indicating whether this instance is regeneration on. + /// + /// + /// true if this instance is regeneration on; otherwise, false. + /// + public bool IsRegenerationOn + { + get + { + return isRegenerationOn; + } + } } \ No newline at end of file Index: DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/MacroStabilityInwardsTests.cs =================================================================== diff -u -r5451 -r5460 --- DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/MacroStabilityInwardsTests.cs (.../MacroStabilityInwardsTests.cs) (revision 5451) +++ DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/MacroStabilityInwardsTests.cs (.../MacroStabilityInwardsTests.cs) (revision 5460) @@ -381,7 +381,7 @@ Assert.Multiple(() => { // No Zone - Assert.That(result.StabilityDesignResults.SafetyFactor, Is.EqualTo(1.365).Within(tolerance)); + Assert.That(result.StabilityDesignResults.SafetyFactor, Is.EqualTo(1.363).Within(tolerance)); Assert.That(result.LocationName, Is.EqualTo("DWP_10_1")); Assert.That(result.ProfileName, Is.EqualTo("DWP_10.stix")); Assert.That(ConversionHelper.ConvertToCalculationResult(result.CalculationResult), Is.EqualTo(CalculationResult.Succeeded)); @@ -391,7 +391,7 @@ Assert.Multiple(() => { // Forbidden Zone, factor = 0.2 - Assert.That(result.StabilityDesignResults.SafetyFactor, Is.EqualTo(1.899).Within(tolerance)); + Assert.That(result.StabilityDesignResults.SafetyFactor, Is.EqualTo(1.895).Within(tolerance)); Assert.That(result.LocationName, Is.EqualTo("DWP_10_4")); Assert.That(result.ProfileName, Is.EqualTo("DWP_10.stix")); Assert.That(ConversionHelper.ConvertToCalculationResult(result.CalculationResult), Is.EqualTo(CalculationResult.Succeeded)); @@ -486,7 +486,7 @@ Assert.That(output.Results.CalculationResults.First().StabilityDesignResults.SafetyFactor, Is.EqualTo(1.366).Within(tolerance)); } - [TestCase("SlopeAdaptionBeforeShoulderAdaption", 1.4, 1.513, 5)] + [TestCase("SlopeAdaptionBeforeShoulderAdaption", 1.4, 1.511, 5)] [TestCase("OptimizedSlopeAndShoulderAdaption", 1.4, 1.426, 3)] public void GivenTutorialDesignDwp1_WhenRunWithGeometryAdaption_ThenGivesExpectedResults(string designMethod, double requiredSafetyFactor, double actualSafetyFactor, int iterationCount) @@ -536,9 +536,9 @@ // Set UseNewMinDistanceDikeToeStartDitch(Use new allowed distance toe-ditch) = true (to force value to be written to XML) // // Parameters: CalcDir - StabilityModel - DesignStrategy - CalculationResult - FoS - EntryPointX - ExitPointX - DikeLength - ShoulderHeight - Iterations - ResultMessage - [TestCase("TestStabInwardsBishopDesignSequential", "Bishop", "SlopeAdaptionBeforeShoulderAdaption", CalculationResult.Succeeded, 1.459, 45.387, 2.799, 5, "")] + [TestCase("TestStabInwardsBishopDesignSequential", "Bishop", "SlopeAdaptionBeforeShoulderAdaption", CalculationResult.Succeeded, 1.458, 45.387, 2.799, 5, "")] [TestCase("TestStabInwardsBishopDesignOptimized", "Bishop", "OptimizedSlopeAndShoulderAdaption", CalculationResult.Succeeded, 1.509, 43.760, 3.889, 4, "")] - [TestCase("TestStabInwardsUpliftVanDesignSequential", "UpliftVan", "SlopeAdaptionBeforeShoulderAdaption", CalculationResult.Succeeded, 1.514, 50.285, 3.465, 7, "")] + [TestCase("TestStabInwardsUpliftVanDesignSequential", "UpliftVan", "SlopeAdaptionBeforeShoulderAdaption", CalculationResult.Succeeded, 1.513, 50.285, 3.465, 7, "")] //ToDo MWDAM-2474 UpliftVan Optimized does not give expected result // [TestCase("TestStabInwardsUpliftVanDesignOptimized", "UpliftVan", "OptimizedSlopeAndShoulderAdaption", CalculationResult.RunFailed, 1.214, 0.0, 0.0, 4, "The new shoulder height with topslope exceeds the allowed maximum height.")] public void CanPerformStabilityInwardsDesignTutorialDesignOptimizedSlopeAndShoulderAdaption_OneLocation( Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryPointString.cs =================================================================== diff -u -r5209 -r5460 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryPointString.cs (.../GeometryPointString.cs) (revision 5209) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryPointString.cs (.../GeometryPointString.cs) (revision 5460) @@ -721,7 +721,7 @@ } /// - /// Synchronizes the calculation points. + /// Synchronizes the calculation points based on the Points. /// public void SyncCalcPoints() { @@ -738,7 +738,7 @@ } /// - /// Synchronizes the points. + /// Synchronizes the points based on the CalcPoints. /// public void SyncPoints() { Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryData.cs =================================================================== diff -u -r5287 -r5460 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryData.cs (.../GeometryData.cs) (revision 5287) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryData.cs (.../GeometryData.cs) (revision 5460) @@ -909,12 +909,10 @@ if (Points.Remove(point)) { // TODO: MWDAM-2132, check if code below is still needed - // if (aValidate) - // { - // HandleDelete(objectlist); - // } - // - // DataEventPublisher.DataListModified(pointDataList, point); + if (validate) + { + HandleDelete(objectlist); + } removeFromList = true; } } @@ -925,16 +923,14 @@ if (Curves.IndexOf(geometryCurve) > -1) { // TODO: MWDAM-2132, check if code below is still needed - // if (aValidate) - // { - // HandleDelete(objectlist); - // } + if (validate) + { + HandleDelete(objectlist); + } if (Curves.Remove(geometryCurve)) { RemoveDeletedCurveFromIsUsedCurveLists(geometryCurve); removeFromList = true; - // TODO: MWDAM-2132, check if code below is still needed - // DataEventPublisher.DataListModified(curveDataList, geometryCurve); } } } @@ -945,12 +941,10 @@ if (Loops.Remove(geometryLoop)) { // TODO: MWDAM-2132, check if code below is still needed - // DataEventPublisher.DataListModified(loopDataList, geometryLoop); - // - // if (aValidate) - // { - // HandleDelete(objectlist); - // } + if (validate) + { + HandleDelete(objectlist); + } removeFromList = true; } } @@ -961,14 +955,9 @@ if (Surfaces.Remove(geometrySurface)) { removeFromList = true; - // TODO: MWDAM-2132, check if code below is still needed - // DataEventPublisher.DataListModified(surfaceDataList, geometrySurface); } } - - // TODO: MWDAM-2132, check if code below is still needed - // DataEventPublisher.AfterChange(this); - + return removeFromList; } @@ -1059,60 +1048,58 @@ public Point2D CreatePoint(Point2D requestedPoint, bool snapToExistingPoint) { - Point2D newPoint = DetermineNewPointAndFlags(requestedPoint, snapToExistingPoint, out bool flag1, out bool flag2); - if (!flag2 && snapToExistingPoint) - { - int count = Curves.Count; - for (int index = 0; index < count; ++index) - { - GeometryCurve curve = Curves[index]; - if (Routines2D.DoesPointExistInLine(curve.HeadPoint, curve.EndPoint, newPoint, 0.25)) - { - Routines2D.GetPointOnLineClosestTo(newPoint.X, newPoint.Z, curve.HeadPoint.X, curve.HeadPoint.Z, - curve.EndPoint.X, curve.EndPoint.Z, out Point2D aResultPoint); - - newPoint.X = aResultPoint.X; - newPoint.Z = aResultPoint.Z; - break; - } - } - } - if (!NewlyEffectedPoints.Contains(newPoint) && !flag1) - NewlyEffectedPoints.Add(newPoint); - return newPoint; + Point2D newPoint = DetermineNewPointAndFlags(requestedPoint, out bool flag1, out bool flag2); + if (!flag2 && snapToExistingPoint) + { + int count = Curves.Count; + for (int index = 0; index < count; ++index) + { + GeometryCurve curve = Curves[index]; + if (Routines2D.DoesPointExistInLine(curve.HeadPoint, curve.EndPoint, newPoint, GeometryConstants.Accuracy)) + { + Routines2D.GetPointOnLineClosestTo(newPoint.X, newPoint.Z, curve.HeadPoint.X, curve.HeadPoint.Z, + curve.EndPoint.X, curve.EndPoint.Z, out Point2D aResultPoint); + + newPoint.X = aResultPoint.X; + newPoint.Z = aResultPoint.Z; + break; + } + } + } + if (!NewlyEffectedPoints.Contains(newPoint) && !flag1) + NewlyEffectedPoints.Add(newPoint); + return newPoint; } - private Point2D DetermineNewPointAndFlags(Point2D requestedPoint, bool snapToExistingPoint, out bool flag1, out bool flag2) + private Point2D DetermineNewPointAndFlags(Point2D requestedPoint, out bool isExistingPoint, out bool flag2) { - Point2D newPoint = null; - flag1 = false; + isExistingPoint = false; flag2 = false; - if (snapToExistingPoint) - newPoint = GetPoint(requestedPoint, 0.001); + // try to find the point in Points + Point2D newPoint = GetPoint(requestedPoint, GeometryConstants.Accuracy); + if (newPoint != null) { requestedPoint.X = newPoint.X; requestedPoint.Z = newPoint.Z; if (!Points.Contains(requestedPoint)) newPoint = null; else - flag1 = true; + isExistingPoint = true; } if (newPoint == null) { newPoint = new Point2D(requestedPoint.X, requestedPoint.Z); - Create((IGeometryObject) newPoint); + Create(newPoint); } else flag2 = true; return newPoint; } - public IGeometryObject Create(IGeometryObject aData) + private void Create(IGeometryObject aData) { - if (aData == null) - return (IGeometryObject) null; if (aData.GetType() == typeof (Point2D)) { Point2D point = (Point2D) aData; @@ -1127,10 +1114,15 @@ Loops.Add((GeometryLoop) aData); else if (aData.GetType() == typeof (GeometrySurface)) Surfaces.Add((GeometrySurface) aData); - return aData; } - public Point2D GetPoint(Point2D point2D, double snapDistance) + /// + /// Checks whether the given point already exists in Points within the requested snap distance. + /// + /// + /// + /// the existing point if found else null + private Point2D GetPoint(Point2D point2D, double snapDistance) { for (int index = 0; index < Points.Count; ++index) { @@ -1196,115 +1188,26 @@ } } - public GeometryCurve CreateCurve(List points, Point2D aPoint1, Point2D aPoint2) + public GeometryCurve CreateCurve(Point2D aPoint1, Point2D aPoint2) { - if (HandleEmptyPointsGeometryCurve(points, aPoint1, aPoint2, out GeometryCurve geometryCurve1)) - { - return geometryCurve1; - } - - foreach (GeometryCurve curve in this.Curves) - { - if (curve.HeadPoint == aPoint1 && curve.EndPoint == aPoint2 || curve.HeadPoint == aPoint2 && curve.EndPoint == aPoint1) + foreach (GeometryCurve curve in Curves) { - return curve; + if (curve.HeadPoint == aPoint1 && curve.EndPoint == aPoint2 || curve.HeadPoint == aPoint2 && curve.EndPoint == aPoint1) + { + return curve; + } } - } - GeometryCurve curve1 = new GeometryCurve(); - geometryGenerator.SetIsUsed(curve1, CurveDirection.Forward, false); - geometryGenerator.SetIsUsed(curve1, CurveDirection.Reverse, false); - curve1.HeadPoint = aPoint1; - curve1.EndPoint = aPoint2; - Create((IGeometryObject) curve1); - NewlyEffectedCurves.Add(curve1); - return curve1; + GeometryCurve curve1 = new GeometryCurve(); + geometryGenerator.SetIsUsed(curve1, CurveDirection.Forward, false); + geometryGenerator.SetIsUsed(curve1, CurveDirection.Reverse, false); + curve1.HeadPoint = aPoint1; + curve1.EndPoint = aPoint2; + Create(curve1); + NewlyEffectedCurves.Add(curve1); + return curve1; } - private bool HandleEmptyPointsGeometryCurve(List points, Point2D aPoint1, Point2D aPoint2, out GeometryCurve geometryCurve1) - { - if (aPoint1 == null && aPoint2 == null) - { - if (points.Count < 1) - { - geometryCurve1 = null; - return true; - } - - Point2D geometryPoint1 = null; - if (points.Count == 1) - { - Point2D point = points[0]; - Point2D aPoint = new Point2D(point.X, point.Z); - List aCurveList = new List(); - GetCurvesCoincidingInputPoint(aPoint, ref aCurveList); - if (aCurveList.Count <= 0) - { - geometryCurve1 = null; - return true; - } - - geometryGenerator.SplitCurvesAtCoincidentPoint(CreatePoint(point, true), aCurveList); - } - else - { - HandleEmptyPointsGeometryCurveNewWithMoreThanOnePointMethod(points, geometryPoint1); - } - // #Bka: this is a direct call instead of a delayed invoke. Can lead to problems (endless spinning) - // Possibly check the isgeneratinggeometry flag - RegenerateGeometry(); - geometryCurve1 = Curves.Count > 0 ? Curves[0] : (GeometryCurve) null; - return true; - } - geometryCurve1 = null; - return false; - } - - private void HandleEmptyPointsGeometryCurveNewWithMoreThanOnePointMethod(List points, Point2D geometryPoint1) - { - for (int index = 0; index < points.Count - 1; ++index) - { - Point2D geometryPoint2 = index != 0 ? geometryPoint1 : CreatePoint(points[index], true); - geometryPoint1 = CreatePoint(points[index + 1], true); - bool flag = false; - foreach (GeometryCurve curve in Curves) - { - if (curve.HeadPoint == geometryPoint2 && curve.EndPoint == geometryPoint1 || - curve.HeadPoint == geometryPoint1 && curve.EndPoint == geometryPoint2) - { - flag = true; - } - } - if (!flag) - { - GeometryCurve geometryCurve = new GeometryCurve(); - geometryGenerator.SetIsUsed(geometryCurve, CurveDirection.Forward, false); - geometryGenerator.SetIsUsed(geometryCurve, CurveDirection.Reverse, false); - geometryCurve.HeadPoint = geometryPoint2; - geometryCurve.EndPoint = geometryPoint1; - Create((IGeometryObject) geometryCurve); - NewlyEffectedCurves.Add(geometryCurve); - } - } - } - /// - /// Returns a list of curves that contain the input point. - /// - /// - /// - public void GetCurvesCoincidingInputPoint(Point2D aPoint, ref List aCurveList) - { - aCurveList.Clear(); - int count = Curves.Count; - for (int index = 0; index < count; ++index) - { - GeometryCurve curve = Curves[index]; - if (Routines2D.DoesPointExistInLine(curve.HeadPoint, curve.EndPoint, aPoint, 0.001)) - aCurveList.Add(curve); - } - } - - /// /// Clones the geometry data. /// /// Returns a clone @@ -1349,5 +1252,105 @@ // This will ensure that a new generator for this geometry using this geometry will be used. clonedGeometryData.geometryGenerator = null; return clonedGeometryData; - } + } + + public bool HandleDelete(List aList) + { + bool regenerationResult = false; + + //SaveGeometryState(); + + foreach (var anObject in aList) + { + bool tobeRegenerated; + if (anObject.GetType() == typeof(GeometryPoint)) + { + var selectedPoint = (Point2D) anObject; + //if (Points.Contains(selectedPoint)) + { + tobeRegenerated = DeletePoint(selectedPoint); + if (!regenerationResult) + { + regenerationResult = tobeRegenerated; + } + //DataEventPublisher.DataListModified(Points); + } + } + else if (anObject.GetType() == typeof(GeometryCurve)) + { + var selectedCurve = (GeometryCurve) anObject; + + tobeRegenerated = DeleteCurve(selectedCurve, true); + if (!regenerationResult) + { + regenerationResult = tobeRegenerated; + } + + // if (curveDataList.Contains(selectedCurve)) + // { + // DataEventPublisher.DataListModified(curveDataList); + // } + } + else if (anObject.GetType() == typeof(GeometrySurface)) + { + var selectedSurface = (GeometrySurface) anObject; + DeleteSurface(selectedSurface, true); + //DataEventPublisher.DataListModified(surfaceDataList); + } + } + if (regenerationResult) + { + RegenerateGeometry(); + } + + return regenerationResult; + } + + /// + /// Deletes the given IGeometrySurface if aValidate is true. + /// + /// + /// + public void DeleteSurface(GeometrySurface aSurface, bool aValidate) + { + aValidate = aValidate && !geometryGenerator.IsRegenerationOn; + var surface = aSurface; + + GeometryLoop outerLoop = aSurface.OuterLoop; + + if (aValidate) + { + // Delete all curves which are part of the surface + //DataEventPublisher.BeforeChange(Curves); + //DataEventPublisher.BeforeChange(Points); + + var curvesToBeDeleted = new List(); + foreach (var curve in outerLoop.CurveList) + { + bool allowDelete = curve.SurfaceAtLeft == null || curve.SurfaceAtLeft == surface; + allowDelete &= curve.SurfaceAtRight == null || curve.SurfaceAtRight == surface; + + if (allowDelete) + { + curvesToBeDeleted.Add(curve); + } + else + { + NewlyEffectedCurves.Add(curve); + } + } + + foreach (var delCurve in curvesToBeDeleted) + { + DeleteCurve(delCurve, true); + } + Remove(outerLoop, false); + Remove(aSurface, false); + } + else + { + Remove(outerLoop, false); + Remove(surface, false); + } + } } \ No newline at end of file Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilProfile2DSurfaceLineHelper.cs =================================================================== diff -u -r5408 -r5460 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilProfile2DSurfaceLineHelper.cs (.../SoilProfile2DSurfaceLineHelper.cs) (revision 5408) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geotechnics/SoilProfile2DSurfaceLineHelper.cs (.../SoilProfile2DSurfaceLineHelper.cs) (revision 5460) @@ -32,6 +32,7 @@ /// public static class SoilProfile2DSurfaceLineHelper { + /// /// Determines if the surface line is inside the soil profile. /// @@ -77,12 +78,11 @@ if (surfaceLine == null || surfaceLine.Points.Count == 0) return null; - var result = new SoilProfile2D(); SoilProfile2D clonedProfile = soilProfile2D.Clone(); GeometryPointString clonedSurfaceLine = surfaceLine.Clone(); RoundCoordinates(clonedSurfaceLine, clonedProfile); shift = GeometryObject.RoundValue(shift); - if (Math.Abs(shift) >= 0.0) + if (Math.Abs(shift) >= GeometryConstants.Accuracy) { foreach (Point2D point in clonedProfile.Geometry.Points) point.X += shift; @@ -96,10 +96,14 @@ // As the original profile may have been moved as cloned profile, a new clone is needed to perform all reset actions with. // The cloned profile is used to determine the original surfaces and preconsolidations. SoilProfile2D soilProfile2D2 = clonedProfile.Clone(); + var oldSurfaces = new List(); oldSurfaces.AddRange((IEnumerable) soilProfile2D2.Surfaces); AddGeometryIntersectionsToSurfaceLine(clonedProfile.Geometry, ref clonedSurfaceLine); + + var result = new SoilProfile2D(); BuildGeometryModel(clonedSurfaceLine, clonedProfile, ref result); + RemoveGeometryDataOfSoilProfileAboveSurfaceLine(clonedSurfaceLine, ref result); ReconstructSurfaces(ref result, clonedProfile, oldSurfaces, defaultSoil); ReconstructPreConsolidations(ref result, clonedProfile, shift); @@ -166,10 +170,16 @@ if (result.Geometry.Curves == null || result.Geometry.Curves.Count < 3) return; result.Geometry.Rebox(); - if (surfaceLine == null || surfaceLine.Points.Count <= 1) + if (surfaceLine == null || surfaceLine.Points.Count <= 2) return; + if (result.Geometry.NewlyEffectedCurves.Count > 0 || result.Geometry.NewlyEffectedPoints.Count > 0) + { + return; + } + AdaptGeometryToSurfaceLineLimits(surfaceLine, ref result); AddLeadingSurfaceLineToGeometry(surfaceLine, ref result); + result.Geometry.NewlyEffectedPoints.AddRange((IEnumerable) result.Geometry.Points); result.Geometry.NewlyEffectedCurves.AddRange((IEnumerable) result.Geometry.Curves); result.Geometry.Surfaces.Clear(); @@ -200,6 +210,8 @@ private static void AddLeadingSurfaceLineToGeometry(GeometryPointString surfaceLine, ref SoilProfile2D result) { + result.Geometry.NewlyEffectedCurves.Clear(); + result.Geometry.NewlyEffectedPoints.Clear(); surfaceLine.SyncCalcPoints(); IList points = surfaceLine.CalcPoints; GeometryData geometry = result.Geometry; @@ -211,6 +223,8 @@ geometry.NewlyEffectedPoints.Add(current1); if (leftPoints[^1].Z < current1.Z) { + // When the first point of the surface line is above the geometry (leftpoits) add a curve to the geometry + // from the last (= top) point of the leftpoints to the first point of the surface line. GeometryCurve newLeftCurve = new GeometryCurve(leftPoints[^1], current1); result.Geometry.NewlyEffectedCurves.Add(newLeftCurve); } Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryHelper.cs =================================================================== diff -u -r5256 -r5460 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryHelper.cs (.../GeometryHelper.cs) (revision 5256) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryHelper.cs (.../GeometryHelper.cs) (revision 5460) @@ -351,69 +351,4 @@ return null; } - public static void ExportFullGeometryToFile(GeometryData geometry, string fileName) - { - using (var writer = new StreamWriter(fileName)) - { - // Export newly effected points - writer.WriteLine("[BEGIN NEWLY EFFECTED POINTS]"); - foreach (Point2D point in geometry.NewlyEffectedPoints) - { - writer.WriteLine($"{point.X}, {point.Z}"); - } - writer.WriteLine("[END NEWLY EFFECTED POINTS]"); - - // Export newly effected curves - writer.WriteLine("[BEGIN NEWLY EFFECTED CURVES]"); - foreach (GeometryCurve curve in geometry.Curves) - { - writer.WriteLine($"Curve: ({curve.HeadPoint.X}, {curve.HeadPoint.Z}) - ({curve.EndPoint.X}, {curve.EndPoint.Z})"); - } - writer.WriteLine("[END NEWLY EFFECTED CURVES]"); - - // Export points - writer.WriteLine("[BEGIN POINTS]"); - foreach (Point2D point in geometry.Points) - { - writer.WriteLine($"{point.X}, {point.Z}"); - } - writer.WriteLine("[END POINTS]"); - - // Export curves - writer.WriteLine("[BEGIN CURVES]"); - foreach (GeometryCurve curve in geometry.Curves) - { - writer.WriteLine($"Curve: ({curve.HeadPoint.X}, {curve.HeadPoint.Z}) - ({curve.EndPoint.X}, {curve.EndPoint.Z})"); - } - writer.WriteLine("[END CURVES]"); - - // Export surfaces - writer.WriteLine("[BEGIN SURFACES]"); - foreach (GeometrySurface surface in geometry.Surfaces) - { - // Outerloop - writer.WriteLine($"Surface: {surface.Name}"); - writer.WriteLine($"OuterLoop: {surface.OuterLoop.Name}"); - foreach (GeometryCurve curve in surface.OuterLoop.CurveList) - { - writer.WriteLine($"({curve.HeadPoint.X}, {curve.HeadPoint.Z}) - ({curve.EndPoint.X}, {curve.EndPoint.Z})"); - } - - writer.WriteLine(""); - - // Innerloops - foreach (GeometryLoop innerLoop in surface.InnerLoops) - { - writer.WriteLine($"InnerLoop: {innerLoop.Name}"); - foreach (GeometryCurve curve in innerLoop.CurveList) - { - writer.WriteLine($"Curve: ({curve.HeadPoint.X}, {curve.HeadPoint.Z}) - ({curve.EndPoint.X}, {curve.EndPoint.Z})"); - } - - writer.WriteLine(""); - } - } - writer.WriteLine("[END SURFACES]"); - } - } } \ No newline at end of file Index: DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/IssuesTests.cs =================================================================== diff -u -r5423 -r5460 --- DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/IssuesTests.cs (.../IssuesTests.cs) (revision 5423) +++ DamEngine/trunk/src/Deltares.DamEngine.IntegrationTests/IntegrationTests/IssuesTests.cs (.../IssuesTests.cs) (revision 5460) @@ -23,6 +23,7 @@ using System.IO; using System.Threading; using Deltares.DamEngine.Data.Geometry; +using Deltares.DamEngine.Data.GeometryExport; using Deltares.DamEngine.Data.Geotechnics; using Deltares.DamEngine.Interface; using Deltares.DamEngine.TestHelpers; @@ -33,43 +34,50 @@ [TestFixture] public class IssuesTests { - private const string mapTestFiles = @"TestFiles\"; private const string tutorialStability2D = @"TestFiles\InputTutorialStability2D.xml"; - //const string visualizationFolder = @"C:\Dam\DamTools\GeometryVisualizer\"; //#John, for debugging purposes - + [Test] - public void TestGeometryAndResultForIssueMWDAM_2349() + [TestCase("DWP_2", 1,15, 97, 83, 1.435)] + [TestCase("DWP_8", 7,26, 129, 104, 1.110)] + [TestCase("DWP_20", 19,23, 113, 91, 1.668)] + public void TestGeometryAndResultForIssueWithDwpsFromTutorial(string location, int segmentIndex, int surfaceCount, int curveCount, int pointCount, double safetyFactor) { string inputString = File.ReadAllText(tutorialStability2D); - string[] locations = ["DWP_2"]; + string[] locations = [location]; inputString = XmlAdapter.SelectLocations(inputString, locations); - - Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture; - const string outputName = "OutputForDebugging.xml"; + var outputName = "OutputFor" + location + ".xml"; var engineInterface = new EngineInterface(inputString); - GeometryData geometry = engineInterface.DamProjectData.Segments[1].SoilProfileProbabilities[0].SoilProfile2D.Geometry; + //GeometryData geometry = engineInterface.DamProjectData.Segments[segmentIndex].SoilProfileProbabilities[0].SoilProfile2D.Geometry; SurfaceLine2 surfaceLine = engineInterface.DamProjectData.Dike.Locations[0].SurfaceLine; + + //GeometryExporter.ExportToFile(geometry, GeometryExporter.VisualizationFolder + "Geometry.txt"); + //GeometryExporter.ExportWithSurfaceLineToJsonFile(GeometryExporter.VisualizationFolder + + // GeometryExporter.ExportJasonFile, geometry, surfaceLine.Geometry); - Soil soil = engineInterface.DamProjectData.Dike.SoilList.Soils[0]; + string soilName = engineInterface.DamProjectData.Dike.Locations[0].DikeEmbankmentMaterial; + Soil soil = engineInterface.DamProjectData.Dike.SoilList.GetSoilByName(soilName); // To be able to check the geometry, create it here. SoilProfile2D soilProfile2D = SoilProfile2DSurfaceLineHelper.CombineSurfaceLineWithSoilProfile2D(surfaceLine.Geometry, - engineInterface.DamProjectData.Segments[1].SoilProfileProbabilities[0].SoilProfile2D, soil, 0.0); - //geometry = sp2.Geometry; // For debugging purposes based on the visualization of the geometry (tool Tom) - //GeometryExporter.ExportToFile(geometry, visualizationFolder + "Geometry.txt"); - //GeometryExporter.ExportToJsonFile(geometry, visualizationFolder + "Geometry.json"); + engineInterface.DamProjectData.Segments[segmentIndex].SoilProfileProbabilities[0].SoilProfile2D, soil, 0.0); + // For debugging purposes + // geometry = soilProfile2D.Geometry; + // GeometryExporter.ExportToFile(geometry, GeometryExporter.VisualizationFolder + "Geometry.txt"); + // GeometryExporter.ExportWithSurfaceLineToJsonFile(GeometryExporter.VisualizationFolder + + // GeometryExporter.ExportJasonFile, geometry, surfaceLine.Geometry); + Assert.Multiple(() => { - Assert.That(soilProfile2D.Geometry.Surfaces, Has.Count.EqualTo(15)); - Assert.That(soilProfile2D.Geometry.Curves, Has.Count.EqualTo(97)); - Assert.That(soilProfile2D.Geometry.Points, Has.Count.EqualTo(83)); + Assert.That(soilProfile2D.Geometry.Surfaces, Has.Count.EqualTo(surfaceCount)); + Assert.That(soilProfile2D.Geometry.Curves, Has.Count.EqualTo(curveCount)); + Assert.That(soilProfile2D.Geometry.Points, Has.Count.EqualTo(pointCount)); }); GeneralHelper.RunAfterInputValidation(engineInterface, true, outputName); int errorCount = GeneralHelper.DetermineNumberOfCalculationErrors(engineInterface.DamProjectData.CalculationMessages); Assert.Multiple(() => { Assert.That(errorCount, Is.EqualTo(0), "There should be no errors during the calculation."); - Assert.That(engineInterface.DamProjectData.DesignCalculations, Has.Count.EqualTo(1), "There should be one design calculation."); - Assert.That(engineInterface.DamProjectData.DesignCalculations[0].SafetyFactor, Is.EqualTo(1.435).Within(0.001), "The safety factor should be 1.435."); + Assert.That(engineInterface.DamProjectData.DesignCalculations.Count, Is.EqualTo(1), "There should be one design calculation."); + Assert.That(engineInterface.DamProjectData.DesignCalculations[0].SafetyFactor, Is.EqualTo(safetyFactor).Within(0.001), "The safety factor should be 1.110."); }); } } \ No newline at end of file