diff --git a/src/Advanced.Algorithms/Geometry/BentleyOttmann.cs b/src/Advanced.Algorithms/Geometry/BentleyOttmann.cs index 92069672..ed6b2cfd 100644 --- a/src/Advanced.Algorithms/Geometry/BentleyOttmann.cs +++ b/src/Advanced.Algorithms/Geometry/BentleyOttmann.cs @@ -13,7 +13,7 @@ public class BentleyOttmann private readonly PointComparer pointComparer; private HashSet verticalHorizontalLines; - private HashSet normalLines; + private HashSet otherLines; private BHeap eventQueue; private HashSet eventQueueLookUp; @@ -42,7 +42,7 @@ private void initialize(IEnumerable lineSegments) intersectionEvents = new Dictionary>>(pointComparer); verticalHorizontalLines = new HashSet(); - normalLines = new HashSet(); + otherLines = new HashSet(); rightLeftEventLookUp = lineSegments .Select(x => @@ -81,6 +81,7 @@ public Dictionary> FindIntersections(IEnumerable lineSeg { case EventType.Start: + //special case if (verticalHorizontalLines.Count > 0) { foreach (var line in verticalHorizontalLines) @@ -90,11 +91,12 @@ public Dictionary> FindIntersections(IEnumerable lineSeg } } + //special case if (currentEvent.Segment.IsVertical || currentEvent.Segment.IsHorizontal) { verticalHorizontalLines.Add(currentEvent); - foreach (var line in normalLines) + foreach (var line in otherLines) { var intersection = findIntersection(currentEvent, line); recordIntersection(currentEvent, line, intersection); @@ -103,7 +105,7 @@ public Dictionary> FindIntersections(IEnumerable lineSeg break; } - normalLines.Add(currentEvent); + otherLines.Add(currentEvent); currentlyTrackedLines.Insert(currentEvent); @@ -124,13 +126,14 @@ public Dictionary> FindIntersections(IEnumerable lineSeg currentEvent = rightLeftEventLookUp[currentEvent]; + //special case if (currentEvent.Segment.IsVertical || currentEvent.Segment.IsHorizontal) { verticalHorizontalLines.Remove(currentEvent); break; } - normalLines.Remove(currentEvent); + otherLines.Remove(currentEvent); lower = currentlyTrackedLines.NextLower(currentEvent); upper = currentlyTrackedLines.NextHigher(currentEvent); @@ -147,18 +150,25 @@ public Dictionary> FindIntersections(IEnumerable lineSeg var intersectionLines = intersectionEvents[currentEvent as Point]; - foreach (var item in intersectionLines) + foreach (var lines in intersectionLines) { - swapBstNodes(currentlyTrackedLines, item.Item1, item.Item2); + //special case + if (lines.Item1.Segment.IsHorizontal || lines.Item1.Segment.IsVertical + || lines.Item2.Segment.IsHorizontal || lines.Item2.Segment.IsVertical) + { + continue; + } + + swapBstNodes(currentlyTrackedLines, lines.Item1, lines.Item2); - var upperLine = item.Item1; + var upperLine = lines.Item1; var upperUpper = currentlyTrackedLines.NextHigher(upperLine); var newUpperIntersection = findIntersection(upperLine, upperUpper); recordIntersection(upperLine, upperUpper, newUpperIntersection); enqueueIntersectionEvent(currentEvent, newUpperIntersection); - var lowerLine = item.Item2; + var lowerLine = lines.Item2; var lowerLower = currentlyTrackedLines.NextLower(lowerLine); var newLowerIntersection = findIntersection(lowerLine, lowerLower); diff --git a/tests/Advanced.Algorithms.Tests/Geometry/BentleyOttmann_Tests.cs b/tests/Advanced.Algorithms.Tests/Geometry/BentleyOttmann_Tests.cs index 8e883b10..33100eda 100644 --- a/tests/Advanced.Algorithms.Tests/Geometry/BentleyOttmann_Tests.cs +++ b/tests/Advanced.Algorithms.Tests/Geometry/BentleyOttmann_Tests.cs @@ -83,6 +83,89 @@ public void BentleyOttmann_Horizontal_Lines_Test() Assert.AreEqual(expectedIntersections.Count, actualIntersections.Count); } + [TestMethod] + public void BentleyOttmann_Vertical_Horizontal_Lines_Test() + { + var lines = new List(); + + //vertical + lines.Add(new Line(new Point(100, 100), new Point(100, 200))); + lines.Add(new Line(new Point(125, 100), new Point(125, 200))); + lines.Add(new Line(new Point(150, 100), new Point(150, 200))); + lines.Add(new Line(new Point(175, 100), new Point(175, 200))); + lines.Add(new Line(new Point(200, 100), new Point(200, 200))); + + //horizontal + lines.Add(new Line(new Point(100, 100), new Point(200, 100))); + lines.Add(new Line(new Point(100, 125), new Point(200, 125))); + lines.Add(new Line(new Point(100, 150), new Point(200, 150))); + lines.Add(new Line(new Point(100, 175), new Point(200, 175))); + lines.Add(new Line(new Point(100, 200), new Point(200, 200))); + + var expectedIntersections = getExpectedIntersections(lines); + + var bentleyOttmannAlgorithm = new BentleyOttmann(); + + var actualIntersections = bentleyOttmannAlgorithm.FindIntersections(lines); + + Assert.AreEqual(expectedIntersections.Count, actualIntersections.Count); + } + + [TestMethod] + public void BentleyOttmann_Vertical_Horizontal_Other_Lines_Test_1() + { + var lines = new List(); + + //vertical + lines.Add(new Line(new Point(100, 100), new Point(100, 200))); + lines.Add(new Line(new Point(200, 100), new Point(200, 200))); + + //horizontal + lines.Add(new Line(new Point(100, 100), new Point(200, 100))); + lines.Add(new Line(new Point(100, 150), new Point(200, 150))); + lines.Add(new Line(new Point(100, 200), new Point(200, 200))); + + //other lines + lines.Add(new Line(new Point(100, 100), new Point(200, 200))); + lines.Add(new Line(new Point(100, 200), new Point(200, 100))); + + var expectedIntersections = getExpectedIntersections(lines); + + var bentleyOttmannAlgorithm = new BentleyOttmann(); + + var actualIntersections = bentleyOttmannAlgorithm.FindIntersections(lines); + + Assert.AreEqual(expectedIntersections.Count, actualIntersections.Count); + } + + + [TestMethod] + public void BentleyOttmann_Vertical_Horizontal_Other_Lines_Test_2() + { + var lines = new List(); + + //vertical + lines.Add(new Line(new Point(100, 100), new Point(100, 200))); + lines.Add(new Line(new Point(200, 100), new Point(200, 200))); + + //horizontal + lines.Add(new Line(new Point(100, 100), new Point(200, 100))); + lines.Add(new Line(new Point(100, 150), new Point(200, 150))); + lines.Add(new Line(new Point(100, 200), new Point(200, 200))); + + //other lines + lines.Add(new Line(new Point(110, 100), new Point(210, 200))); + lines.Add(new Line(new Point(90, 200), new Point(250, 100))); + + var expectedIntersections = getExpectedIntersections(lines); + + var bentleyOttmannAlgorithm = new BentleyOttmann(); + + var actualIntersections = bentleyOttmannAlgorithm.FindIntersections(lines); + + Assert.AreEqual(expectedIntersections.Count, actualIntersections.Count); + } + [TestMethod] public void BentleyOttmann_Stress_Test() { @@ -178,7 +261,7 @@ private static List horizontalLines() { var lines = new List(); - var s1 = new Line(new Point(200, 100), new Point(600, 100)); + var s1 = new Line(new Point(100, 100), new Point(600, 100)); var s2 = new Line(new Point(225, 100), new Point(625, 100)); var s3 = new Line(new Point(250, 100), new Point(475, 100)); var s4 = new Line(new Point(290, 100), new Point(675, 100));