Index: DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geometry/GeometryGeneratorTests.cs =================================================================== diff -u -r6004 -r6030 --- DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geometry/GeometryGeneratorTests.cs (.../GeometryGeneratorTests.cs) (revision 6004) +++ DamEngine/trunk/src/Deltares.DamEngine.Data.Tests/Geometry/GeometryGeneratorTests.cs (.../GeometryGeneratorTests.cs) (revision 6030) @@ -52,28 +52,6 @@ }); } - [TestCase(0.52, 0.51, false, true)] - [TestCase(0.51, 0.52, true, false)] - [TestCase(0.51, 0.51, true, false)] - [Test] - public void WhenDeterminePointClosestToAnotherPoint_ThenResultIsAsExpected(double x1, double x2, bool isPoint1Closest, bool isPoint2Closest) - { - // Given - var point1 = new Point2D(x1, 0.5); - var point2 = new Point2D(x2, 0.5); - var point3 = new Point2D(0.5, 0.5); - var isPoint1ClosestToPoint3 = true; - var isPoint2ClosestToPoint3 = true; - // When - GeometryGenerator.DeterminePointClosestToAnotherPoint(point1, point2, point3, ref isPoint1ClosestToPoint3, ref isPoint2ClosestToPoint3); - Assert.Multiple(() => - { - // Then - Assert.That(isPoint1ClosestToPoint3, Is.EqualTo(isPoint1Closest)); - Assert.That(isPoint2ClosestToPoint3, Is.EqualTo(isPoint2Closest)); - }); - } - [Test, TestCaseSource(nameof(CurvesToBeTestedForParallelCurves))] public void TestRegenerateParallelCurves(TestCaseCurvesToBeTestedForParallelCurves testCase) { @@ -805,6 +783,7 @@ ExpectedPoint6 = null }).SetName("Test 32: p1--p4--p2/p3 split c1(p1,p4) , keep c2(p3-p4)"); + var point33_1 = new Point2D(2.0, 2.0); var point33_2 = new Point2D(4.0, 4.0); var point33_3 = point33_2; @@ -824,7 +803,49 @@ ExpectedPoint4 = point33_4, ExpectedPoint5 = null, ExpectedPoint6 = null - }).SetName("Test 32: p4--p1--p2/p3 keep c1(p1,p2) , split c2(p1-p4)"); + }).SetName("Test 33: p4--p1--p2/p3 keep c1(p1,p2) , split c2(p1-p4)"); + + var point34_1 = new Point2D(39.580, 4.550); + var point34_2 = new Point2D(41.070, 4.540); + var point34_3 = point34_1; + var point34_4 = new Point2D(39.730, 4.549); + yield return new TestCaseData( + new TestCaseCurvesToBeTestedForParallelCurves + { + TestNumber = 1, + InputPoint1 = point34_1, + InputPoint2 = point34_2, + InputPoint3 = point34_3, + InputPoint4 = point34_4, + IsCurveInserted = false, + ExpectedPoint1 = point34_4, + ExpectedPoint2 = point34_2, + ExpectedPoint3 = point34_3, + ExpectedPoint4 = point34_4, + ExpectedPoint5 = null, + ExpectedPoint6 = null + }).SetName("Test 34: near parallel p1/p3--p4--p2 split c1 to c(p4--p2), keep c2 (p3-p4)"); + + var point35_1 = new Point2D(39.580, 4.550); + var point35_2 = new Point2D(39.730, 4.549); + var point35_3 =point35_1; + var point35_4 = new Point2D(41.070, 4.540); + yield return new TestCaseData( + new TestCaseCurvesToBeTestedForParallelCurves + { + TestNumber = 1, + InputPoint1 = point35_1, + InputPoint2 = point35_2, + InputPoint3 = point35_3, + InputPoint4 = point35_4, + IsCurveInserted = false, + ExpectedPoint1 = point35_1, + ExpectedPoint2 = point35_2, + ExpectedPoint3 = point35_2, + ExpectedPoint4 = point35_4, + ExpectedPoint5 = null, + ExpectedPoint6 = null + }).SetName("Test 35: near parallel p1/p3--p2--p4 keep c1, split c2 to c(p2--p4)"); } } } \ No newline at end of file Index: DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryGenerator.cs =================================================================== diff -u -r6025 -r6030 --- DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryGenerator.cs (.../GeometryGenerator.cs) (revision 6025) +++ DamEngine/trunk/src/Deltares.DamEngine.Data/Geometry/GeometryGenerator.cs (.../GeometryGenerator.cs) (revision 6030) @@ -1071,17 +1071,6 @@ } } - protected internal static void DeterminePointClosestToAnotherPoint(Point2D point1, Point2D point2, Point2D point3, - ref bool isPoint1ClosestToPoint3, ref bool isPoint2ClosestToPoint3) - { - double distance1 = Routines2D.Compute2DDistance(point1.X, point1.Z, point3.X, point3.Z); - double distance2 = Routines2D.Compute2DDistance(point2.X, point2.Z, point3.X, point3.Z); - if (distance1 > distance2) - isPoint1ClosestToPoint3 = false; - else - isPoint2ClosestToPoint3 = false; - } - /// /// Regenerates all the Parallel curves. /// @@ -1115,152 +1104,233 @@ return true; } - double slope1 = DetermineSlope(line1); - double slope2 = DetermineSlope(line2); + CheckForNearParallelLines(line1, line2, ref isPoint1OnLine2, ref isPoint2OnLine2, ref isPoint3OnLine1, + ref isPoint4OnLine1); - const double accuracyAngle = 5E-12; - if (Math.Abs(Math.Abs(slope1) - Math.Abs(slope2)) > accuracyAngle) + // check for parallel + if ((isPoint1OnLine2 && isPoint2OnLine2) || (isPoint3OnLine1 && isPoint4OnLine1) + || ((isPoint3OnLine1 || isPoint4OnLine1) && (isPoint1OnLine2 || isPoint2OnLine2))) { - // lines are not (exactly) parallel - if (isPoint1OnLine2 && isPoint2OnLine2) + if (CheckCasesWhereLine1AndLine2Overlap(line1, line2, ref isCurveInserted, isPoint3OnLine1, isPoint4OnLine1, + isPoint1SameAsPoint3, isPoint2SameAsPoint3, isPoint2OnLine2, + isPoint1SameAsPoint4, isPoint2SameAsPoint4)) { - DeterminePointClosestToLine(localPoint1, localPoint2, line2, ref isPoint1OnLine2, ref isPoint2OnLine2); + return true; } - if (isPoint3OnLine1 && isPoint4OnLine1) + + if (CheckCasesWhereLine2IsInLine1(line1, line2, ref isCurveInserted, isPoint3OnLine1, isPoint4OnLine1, + isPoint1SameAsPoint3, isPoint2SameAsPoint4, isPoint2SameAsPoint3, + isPoint1SameAsPoint4)) { - DeterminePointClosestToLine(localPoint3, localPoint4, line1, ref isPoint3OnLine1, ref isPoint4OnLine1); + return true; } - if (isPoint1SameAsPoint3 && isPoint2SameAsPoint3) + + if (CheckCasesWhereLine1IsInLine2(line1, line2, ref isCurveInserted, isPoint1OnLine2, isPoint2OnLine2, + isPoint1SameAsPoint3, isPoint2SameAsPoint4, isPoint2SameAsPoint3, + isPoint1SameAsPoint4)) { - DeterminePointClosestToAnotherPoint(localPoint1, localPoint2, localPoint3, ref isPoint1SameAsPoint3, ref isPoint2SameAsPoint3); + return true; } - if (isPoint1SameAsPoint4 && isPoint2SameAsPoint4) + + if (CheckCasesWhereLine2IsInLine1WithOnePointEqual(line1, line2, isPoint4OnLine1, isPoint3OnLine1, + isPoint1SameAsPoint3, isPoint2SameAsPoint3, isPoint2SameAsPoint4)) { - DeterminePointClosestToAnotherPoint(localPoint1, localPoint2, localPoint4, ref isPoint1SameAsPoint4, ref isPoint2SameAsPoint4); + return true; } + + if (CheckCasesWhereLine1IsInLine2WithOnePointEqual(line1, line2, isPoint1OnLine2, isPoint2OnLine2, + isPoint1SameAsPoint3, isPoint1SameAsPoint4, isPoint2SameAsPoint4)) + { + return true; + } } - // check for parallel - if ((isPoint1OnLine2 && isPoint2OnLine2) || (isPoint3OnLine1 && isPoint4OnLine1) - || ((isPoint3OnLine1 || isPoint4OnLine1) && (isPoint1OnLine2 || isPoint2OnLine2))) + return false; + } + + private bool CheckCasesWhereLine1IsInLine2(GeometryCurve line1, GeometryCurve line2, ref bool isCurveInserted, + bool isPoint1OnLine2, bool isPoint2OnLine2, bool isPoint1SameAsPoint3, + bool isPoint2SameAsPoint4, bool isPoint2SameAsPoint3, bool isPoint1SameAsPoint4) + { + GeometryCurve newLine; + // p3----p1------p2----p4 + if (isPoint1OnLine2 && isPoint2OnLine2 && !isPoint1SameAsPoint3 && !isPoint2SameAsPoint4 && + !isPoint2SameAsPoint3 && !isPoint1SameAsPoint4) { - GeometryCurve newLine; - - // p1----p3------p2----p4 - if (isPoint3OnLine1 && !isPoint4OnLine1 && !isPoint1SameAsPoint3 && !isPoint2SameAsPoint3) - { - newLine = SplitCurve(line1, line2.HeadPoint); + double distance1 = Routines2D.Compute2DDistance(line2.HeadPoint.X, line2.HeadPoint.Z, line1.HeadPoint.X, line1.HeadPoint.Z); + double distance2 = Routines2D.Compute2DDistance(line2.HeadPoint.X, line2.HeadPoint.Z, line1.EndPoint.X, line1.EndPoint.Z); - line2.HeadPoint = isPoint2OnLine2 ? newLine.EndPoint : line1.HeadPoint; - - isCurveInserted = true; - return true; + if (distance1 < distance2) + { + newLine = SplitCurve(line2, line1.HeadPoint); + newLine.HeadPoint = line1.EndPoint; } + else + { + newLine = SplitCurve(line2, line1.EndPoint); + newLine.HeadPoint = line1.HeadPoint; + } + + isCurveInserted = true; + return true; + } - // p1----p4------p2----p3 - if (isPoint4OnLine1 && !isPoint3OnLine1 && !isPoint1SameAsPoint4 && !isPoint2SameAsPoint4) + return false; + } + + private bool CheckCasesWhereLine2IsInLine1(GeometryCurve line1, GeometryCurve line2, ref bool isCurveInserted, + bool isPoint3OnLine1, bool isPoint4OnLine1, bool isPoint1SameAsPoint3, + bool isPoint2SameAsPoint4, bool isPoint2SameAsPoint3, bool isPoint1SameAsPoint4) + { + GeometryCurve newLine; + // p1----p3------p4----p2 + if (isPoint3OnLine1 && isPoint4OnLine1 && !isPoint1SameAsPoint3 && !isPoint2SameAsPoint4 && + !isPoint2SameAsPoint3 && !isPoint1SameAsPoint4) + { + double distance1 = Routines2D.Compute2DDistance(line1.HeadPoint.X, line1.HeadPoint.Z, line2.HeadPoint.X, + line2.HeadPoint.Z); + double distance2 = Routines2D.Compute2DDistance(line1.HeadPoint.X, line1.HeadPoint.Z, line2.EndPoint.X, + line2.EndPoint.Z); + + if (distance1 < distance2) { + newLine = SplitCurve(line1, line2.HeadPoint); + newLine.HeadPoint = line2.EndPoint; + } + else + { newLine = SplitCurve(line1, line2.EndPoint); - line2.EndPoint = isPoint2OnLine2 ? newLine.EndPoint : line1.HeadPoint; - - isCurveInserted = true; - return true; + newLine.HeadPoint = line2.HeadPoint; } + + isCurveInserted = true; + return true; + } - // p1----p3------p4----p2 - if (isPoint3OnLine1 && isPoint4OnLine1 && !isPoint1SameAsPoint3 && !isPoint2SameAsPoint4 && - !isPoint2SameAsPoint3 && !isPoint1SameAsPoint4) - { - double distance1 = Routines2D.Compute2DDistance(localPoint1.X, localPoint1.Z, localPoint3.X, localPoint3.Z); - double distance2 = Routines2D.Compute2DDistance(localPoint1.X, localPoint1.Z, localPoint4.X, localPoint4.Z); + return false; + } - if (distance1 < distance2) - { - newLine = SplitCurve(line1, line2.HeadPoint); - newLine.HeadPoint = line2.EndPoint; - } - else - { - newLine = SplitCurve(line1, line2.EndPoint); - newLine.HeadPoint = line2.HeadPoint; - } + private bool CheckCasesWhereLine1AndLine2Overlap(GeometryCurve line1, GeometryCurve line2, ref bool isCurveInserted, + bool isPoint3OnLine1, bool isPoint4OnLine1, bool isPoint1SameAsPoint3, + bool isPoint2SameAsPoint3, bool isPoint2OnLine2, bool isPoint1SameAsPoint4, + bool isPoint2SameAsPoint4) + { + GeometryCurve newLine; + // p1----p3------p2----p4 + if (isPoint3OnLine1 && !isPoint4OnLine1 && !isPoint1SameAsPoint3 && !isPoint2SameAsPoint3) + { + newLine = SplitCurve(line1, line2.HeadPoint); + + line2.HeadPoint = isPoint2OnLine2 ? newLine.EndPoint : line1.HeadPoint; - isCurveInserted = true; - return true; - } + isCurveInserted = true; + return true; + } - // p3----p1------p2----p4 - if (isPoint1OnLine2 && isPoint2OnLine2 && !isPoint1SameAsPoint3 && !isPoint2SameAsPoint4 && - !isPoint2SameAsPoint3 && !isPoint1SameAsPoint4) - { - double distance1 = Routines2D.Compute2DDistance(localPoint3.X, localPoint3.Z, localPoint1.X, localPoint1.Z); - double distance2 = Routines2D.Compute2DDistance(localPoint3.X, localPoint3.Z, localPoint2.X, localPoint2.Z); - - if (distance1 < distance2) - { - newLine = SplitCurve(line2, line1.HeadPoint); - newLine.HeadPoint = line1.EndPoint; - } - else - { - newLine = SplitCurve(line2, line1.EndPoint); - newLine.HeadPoint = line1.HeadPoint; - } + // p1----p4------p2----p3 + if (isPoint4OnLine1 && !isPoint3OnLine1 && !isPoint1SameAsPoint4 && !isPoint2SameAsPoint4) + { + newLine = SplitCurve(line1, line2.EndPoint); + line2.EndPoint = isPoint2OnLine2 ? newLine.EndPoint : line1.HeadPoint; - isCurveInserted = true; - return true; - } + isCurveInserted = true; + return true; + } - // vertices coincidence cases - Line2 on Line1 - if (isPoint4OnLine1 && isPoint3OnLine1) + return false; + } + + private static bool CheckCasesWhereLine2IsInLine1WithOnePointEqual(GeometryCurve line1, GeometryCurve line2, + bool isPoint4OnLine1, bool isPoint3OnLine1, + bool isPoint1SameAsPoint3, bool isPoint2SameAsPoint3, + bool isPoint2SameAsPoint4) + { + if (isPoint4OnLine1 && isPoint3OnLine1) + { + // Line2 on Line1 like p1--p3--p4--p2, p2--p3--p4--p1 etc. + if (isPoint1SameAsPoint3) { - if (isPoint1SameAsPoint3) - { - // p1/p3----p4----p2 --> c1(p4, p2) & c2(p3, p4) - line1.HeadPoint = line2.EndPoint; - } - else if (isPoint2SameAsPoint3) - { - // p2/p3----p4----p1 --> c1(p1, p4) & c2(p3, p4) - line1.EndPoint = line2.EndPoint; - } - else if (isPoint2SameAsPoint4) - { - line1.EndPoint = line2.HeadPoint; - } - else - { - line1.HeadPoint = line2.HeadPoint; - } - return true; + // p1/p3----p4----p2 --> c1(p4, p2) & c2(p3, p4) + line1.HeadPoint = line2.EndPoint; } + else if (isPoint2SameAsPoint3) + { + // p2/p3----p4----p1 --> c1(p1, p4) & c2(p3, p4) + line1.EndPoint = line2.EndPoint; + } + else if (isPoint2SameAsPoint4) + { + // p2/p4----p3----p1 --> c1(p1, p3) & c2(p3, p4) + line1.EndPoint = line2.HeadPoint; + } + else + { + // p1/p4----p3----p2 --> c1(p3, p2) & c2(p3, p4) + line1.HeadPoint = line2.HeadPoint; + } - // Line1 on Line2 - if (isPoint1OnLine2 && isPoint2OnLine2) + return true; + } + + return false; + } + + private static bool CheckCasesWhereLine1IsInLine2WithOnePointEqual(GeometryCurve line1, GeometryCurve line2, + bool isPoint1OnLine2, bool isPoint2OnLine2, + bool isPoint1SameAsPoint3, bool isPoint1SameAsPoint4, + bool isPoint2SameAsPoint4) + { + // Line1 on Line2 like p3--p1--p2--p4, p4--p1--p2--p3 etc. + if (isPoint1OnLine2 && isPoint2OnLine2) + { + if (isPoint1SameAsPoint3) { - if (isPoint1SameAsPoint3) - { - line2.HeadPoint = line1.EndPoint; - } - else if (isPoint1SameAsPoint4) - { - line2.EndPoint = line1.EndPoint; - } - else if (isPoint2SameAsPoint4) - { - line2.EndPoint = line1.HeadPoint; - } - else - { - line2.HeadPoint = line1.HeadPoint; - } - return true; + //p3/p1--p2--p4 + line2.HeadPoint = line1.EndPoint; } + else if (isPoint1SameAsPoint4) + { + //p4/p1--p2--p3 + line2.EndPoint = line1.EndPoint; + } + else if (isPoint2SameAsPoint4) + { + //p4/p2--p1--p3 + line2.EndPoint = line1.HeadPoint; + } + else + { + //p3/p2--p1--p4 + line2.HeadPoint = line1.HeadPoint; + } + + return true; } return false; } + private static void CheckForNearParallelLines(GeometryCurve line1, GeometryCurve line2, ref bool isPoint1OnLine2, + ref bool isPoint2OnLine2, ref bool isPoint3OnLine1, ref bool isPoint4OnLine1) + { + double slope1 = DetermineSlope(line1); + double slope2 = DetermineSlope(line2); + const double accuracyAngle = 5E-12; + if (Math.Abs(Math.Abs(slope1) - Math.Abs(slope2)) > accuracyAngle) + { + if (isPoint1OnLine2 && isPoint2OnLine2) + { + // lines are not (exactly) parallel but within the geometry accuracy off each other + DeterminePointClosestToLine(line1.HeadPoint, line1.EndPoint, line2, ref isPoint1OnLine2, ref isPoint2OnLine2); + } + if (isPoint3OnLine1 && isPoint4OnLine1) + { + // lines are not (exactly) parallel but within the geometry accuracy off each other + DeterminePointClosestToLine(line2.HeadPoint, line2.EndPoint, line1, ref isPoint3OnLine1, ref isPoint4OnLine1); + } + } + } + private GeometryCurve SplitCurve(GeometryCurve srcCurve, Point2D pointOnCurve) { if (pointOnCurve.LocationEquals(srcCurve.HeadPoint) || pointOnCurve.LocationEquals(srcCurve.EndPoint))