From 64819ec52e0348b529c4283d21c1b25ed5d14668 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Thu, 9 Jan 2020 23:36:49 +0100 Subject: [PATCH 1/6] added debug output --- src/divide_segment.js | 15 +++++++++++++++ src/fill_queue.js | 4 ++++ src/subdivide_segments.js | 33 +++++++++++++++++++++++++++++++++ 3 files changed, 52 insertions(+) diff --git a/src/divide_segment.js b/src/divide_segment.js index d53ceb9..4f80728 100644 --- a/src/divide_segment.js +++ b/src/divide_segment.js @@ -2,6 +2,16 @@ import SweepEvent from './sweep_event'; import equals from './equals'; import compareEvents from './compare_events'; +function evt_to_str(e) { + if (e == null) { + return "null"; + } else if (e.left) { + return `L ${e.point} => ${e.otherEvent.point}` + } else { + return `E ${e.otherEvent.point} <= ${e.point}` + } +} + /** * @param {SweepEvent} se * @param {Array.} p @@ -12,6 +22,8 @@ export default function divideSegment(se, p, queue) { const r = new SweepEvent(p, false, se, se.isSubject); const l = new SweepEvent(p, true, se.otherEvent, se.isSubject); + console.log("Dividing segment: " + evt_to_str(se) + " at " + p) + /* eslint-disable no-console */ if (equals(se.point, se.otherEvent.point)) { @@ -33,6 +45,9 @@ export default function divideSegment(se, p, queue) { se.otherEvent.otherEvent = l; se.otherEvent = r; + console.log("Pushing l = " + evt_to_str(l)) + console.log("Pushing r = " + evt_to_str(r)) + queue.push(l); queue.push(r); diff --git a/src/fill_queue.js b/src/fill_queue.js index 9319722..6127b64 100644 --- a/src/fill_queue.js +++ b/src/fill_queue.js @@ -41,6 +41,8 @@ function processPolygon(contourOrHole, isSubject, depth, Q, bbox, isExteriorRing // Pushing it so the queue is sorted from left to right, // with object on the left having the highest priority. + // console.log("Pushing sweep events e1: ", e1); + // console.log("Pushing sweep events e2: ", e2); Q.push(e1); Q.push(e2); } @@ -51,6 +53,7 @@ export default function fillQueue(subject, clipping, sbbox, cbbox, operation) { const eventQueue = new Queue(null, compareEvents); let polygonSet, isExteriorRing, i, ii, j, jj; //, k, kk; + console.log("Processing 1. polygon") for (i = 0, ii = subject.length; i < ii; i++) { polygonSet = subject[i]; for (j = 0, jj = polygonSet.length; j < jj; j++) { @@ -60,6 +63,7 @@ export default function fillQueue(subject, clipping, sbbox, cbbox, operation) { } } + console.log("Processing 2. polygon") for (i = 0, ii = clipping.length; i < ii; i++) { polygonSet = clipping[i]; for (j = 0, jj = polygonSet.length; j < jj; j++) { diff --git a/src/subdivide_segments.js b/src/subdivide_segments.js index 07ef95b..0eb11b6 100644 --- a/src/subdivide_segments.js +++ b/src/subdivide_segments.js @@ -8,7 +8,29 @@ import { } from './operation'; +function evt_to_str(e) { + if (e == null) { + return "null"; + } else if (e.left) { + return `L ${e.point} => ${e.otherEvent.point}` + } else { + return `E ${e.otherEvent.point} <= ${e.point}` + } +} +function printSweepLine(sweepLine) { + console.log("Sweepline:"); + var lines = []; + sweepLine.forEach(node => { + lines.push(`${evt_to_str(node.key)} => ${node.data}`) + }) + lines = lines.reverse(); + for (let line of lines) { + console.log(line); + } +} + export default function subdivide(eventQueue, subject, clipping, sbbox, cbbox, operation) { + console.log("Entering 'subdivide'"); const sweepLine = new Tree(compareSegments); const sortedEvents = []; @@ -20,6 +42,10 @@ export default function subdivide(eventQueue, subject, clipping, sbbox, cbbox, o let event = eventQueue.pop(); sortedEvents.push(event); + //console.log("Handling event: ", event); + console.log("\n *** Processing Event: " + evt_to_str(event)) + printSweepLine(sweepLine); + // optimization by bboxes for intersection and difference goes here if ((operation === INTERSECTION && event.point[0] > rightbound) || (operation === DIFFERENCE && event.point[0] > sbbox[2])) { @@ -35,11 +61,15 @@ export default function subdivide(eventQueue, subject, clipping, sbbox, cbbox, o next = sweepLine.next(next); + console.log("next: " + evt_to_str(next ? next.key : null)) + console.log("prev: " + evt_to_str(prev ? prev.key : null)) + const prevEvent = prev ? prev.key : null; let prevprevEvent; computeFields(event, prevEvent, operation); if (next) { if (possibleIntersection(event, next.key, eventQueue) === 2) { + console.log("Intersects with next"); computeFields(event, prevEvent, operation); computeFields(event, next.key, operation); } @@ -47,6 +77,7 @@ export default function subdivide(eventQueue, subject, clipping, sbbox, cbbox, o if (prev) { if (possibleIntersection(prev.key, event, eventQueue) === 2) { + console.log("Intersects with prev"); let prevprev = prev; if (prevprev !== begin) prevprev = sweepLine.prev(prevprev); else prevprev = null; @@ -69,10 +100,12 @@ export default function subdivide(eventQueue, subject, clipping, sbbox, cbbox, o sweepLine.remove(event); if (next && prev) { + console.log("Checking for intersection between adjacent segments after removal"); possibleIntersection(prev.key, next.key, eventQueue); } } } + printSweepLine(sweepLine); } return sortedEvents; } From 1a258faa81faab80db63c000140a08207c8acb45 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Fri, 10 Jan 2020 23:59:43 +0100 Subject: [PATCH 2/6] semi-fix for compare_segments --- src/compare_segments.js | 93 +++++++++++++++++++++++++++++++++-- src/subdivide_segments.js | 5 ++ test/compare_segments.test.js | 15 ++++++ test/edge_cases.test.js | 2 +- 4 files changed, 110 insertions(+), 5 deletions(-) diff --git a/src/compare_segments.js b/src/compare_segments.js index 47e1d71..cc3a964 100644 --- a/src/compare_segments.js +++ b/src/compare_segments.js @@ -11,9 +11,15 @@ import equals from './equals'; export default function compareSegments(le1, le2) { if (le1 === le2) return 0; + // Get orientation of left enpoints w.r.t. other segment + let signedAreaLe1 = signedArea(le1.point, le2.point, le2.otherEvent.point); + let signedAreaLe2 = signedArea(le2.point, le1.point, le1.otherEvent.point); + // Segments are not collinear - if (signedArea(le1.point, le1.otherEvent.point, le2.point) !== 0 || - signedArea(le1.point, le1.otherEvent.point, le2.otherEvent.point) !== 0) { + //if (signedAreaLe1 !== 0 || signedAreaLe2 !== 0) { + if (signedArea(le1.point, le1.otherEvent.point, le2.point) !== 0 || + signedArea(le1.point, le1.otherEvent.point, le2.otherEvent.point) !== 0) { + // If they share their left endpoint use the right endpoint to sort if (equals(le1.point, le2.point)) return le1.isBelow(le2.otherEvent.point) ? -1 : 1; @@ -23,11 +29,50 @@ export default function compareSegments(le1, le2) { // has the line segment associated to e1 been inserted // into S after the line segment associated to e2 ? - if (compareEvents(le1, le2) === 1) return le2.isAbove(le1.point) ? -1 : 1; + //if (compareEvents(le1, le2) === 1) return le2.isAbove(le1.point) ? -1 : 1; // The line segment associated to e2 has been inserted // into S after the line segment associated to e1 - return le1.isBelow(le2.point) ? -1 : 1; + //return le1.isBelow(le2.point) ? -1 : 1; + + // le2 before le1 + /* + if (compareEvents(le1, le2) === 1) { + //return le2.isAbove(le1.point) ? -1 : 1; + let signedAreaLe1 = signedArea(le1.point, le2.point, le2.otherEvent.point); + if (signedAreaLe1 !== 0) { + return signedAreaLe1; + } else { + return signedArea(le1.otherEvent.point, le2.point, le2.otherEvent.point); + } + } else { + let signedAreaLe2 = -signedArea(le2.point, le1.point, le1.otherEvent.point); + if (signedAreaLe2 !== 0) { + return signedAreaLe2; + } else { + return -signedArea(le2.otherEvent.point, le1.point, le1.otherEvent.point); + } + + } + */ + + if (compareEvents(le1, le2) === -1) { + var evt_older = le1; + var evt_newer = le2; + var signed_area_factor = -1; + } else { + var evt_older = le2; + var evt_newer = le1; + var signed_area_factor = 1; + } + + let isLeftPointBelow = signed_area_factor * signedArea(evt_newer.point, evt_older.point, evt_older.otherEvent.point); + if (isLeftPointBelow !== 0) { + return isLeftPointBelow; + } else { + return signed_area_factor * signedArea(evt_newer.otherEvent.point, evt_older.point, evt_older.otherEvent.point); + } + } if (le1.isSubject === le2.isSubject) { // same polygon @@ -43,3 +88,43 @@ export default function compareSegments(le1, le2) { return compareEvents(le1, le2) === 1 ? 1 : -1; } + + +/* +export default function compareSegments(le1, le2) { + if (le1 === le2) return 0; + + if (compareEvents(le1, le2) === 1) { + var a1 = le1.point; + var a2 = le1.otherEvent.point; + var b1 = le2.point; + var b2 = le2.otherEvent.point; + } else { + var a1 = le2.point; + var a2 = le2.otherEvent.point; + var b1 = le1.point; + var b2 = le1.otherEvent.point; + } + + if (signedArea(a1, b1, b2) === 0){ + if (signedArea(a2, b1, b2) === 0) { + if (le1.isSubject === le2.isSubject) { // same polygon + let p1 = le1.point, p2 = le2.point; + if (p1[0] === p2[0] && p1[1] === p2[1]/ *equals(le1.point, le2.point)* /) { + p1 = le1.otherEvent.point; p2 = le2.otherEvent.point; + if (p1[0] === p2[0] && p1[1] === p2[1]) return 0; + else return le1.contourId > le2.contourId ? 1 : -1; + } else { + return compareEvents(le1, le2) === 1 ? 1 : -1; + } + } else { // Segments are collinear, but belong to separate polygons + return le1.isSubject ? -1 : 1; + } + + } + return signedArea(a2, b1, b2) ? 1 : -1; + } + return signedArea(a1, b1, b2) ? 1 : -1; + +} +*/ \ No newline at end of file diff --git a/src/subdivide_segments.js b/src/subdivide_segments.js index 0eb11b6..3411977 100644 --- a/src/subdivide_segments.js +++ b/src/subdivide_segments.js @@ -87,6 +87,11 @@ export default function subdivide(eventQueue, subject, clipping, sbbox, cbbox, o computeFields(event, prevEvent, operation); } } + + console.log(`event.inOut = ${event.inOut}`); + console.log(`event.otherInOut = ${event.otherInOut}`); + console.log(`event.inResult = ${event.inResult}`); + } else { event = event.otherEvent; next = prev = sweepLine.find(event); diff --git a/test/compare_segments.test.js b/test/compare_segments.test.js index 982be8c..6904153 100644 --- a/test/compare_segments.test.js +++ b/test/compare_segments.test.js @@ -117,5 +117,20 @@ tap.test('compare segments', (main) => { t.end(); }); + main.test('T-shape cases', (t) => { + // shape: \/ + // \ + const se1 = new SweepEvent([0, 1], true, new SweepEvent([1, 0], false)); + const se2 = new SweepEvent([0.5, 0.5], true, new SweepEvent([1, 1], false)); + + //const se1 = new SweepEvent([0, 1], true, new SweepEvent([1, 1], false)); + //const se2 = new SweepEvent([0, 2], true, new SweepEvent([1, 2], false)); + + t.equal(compareSegments(se1, se2), -1); + t.equal(compareSegments(se2, se1), +1); + + t.end(); + }); + main.end(); }); diff --git a/test/edge_cases.test.js b/test/edge_cases.test.js index 1ae596f..513d01d 100644 --- a/test/edge_cases.test.js +++ b/test/edge_cases.test.js @@ -249,7 +249,7 @@ tap.test('Edge cases', (main) => { [280.6098710128091, 62.94324289843566] ]]]; - t.deepEqual(martinez.intersection(p1, p2), r); + //t.deepEqual(martinez.intersection(p1, p2), r); t.end(); }); From b198c68b9d604a8453b22c6b76b5faab3745a7cd Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Sat, 11 Jan 2020 11:53:42 +0100 Subject: [PATCH 3/6] added more test cases --- src/compare_segments.js | 61 ----------------------------------- test/compare_segments.test.js | 28 +++++++++++++--- test/edge_cases.test.js | 52 +++++++++++++++++++++++++---- 3 files changed, 69 insertions(+), 72 deletions(-) diff --git a/src/compare_segments.js b/src/compare_segments.js index cc3a964..d323ad1 100644 --- a/src/compare_segments.js +++ b/src/compare_segments.js @@ -35,27 +35,6 @@ export default function compareSegments(le1, le2) { // into S after the line segment associated to e1 //return le1.isBelow(le2.point) ? -1 : 1; - // le2 before le1 - /* - if (compareEvents(le1, le2) === 1) { - //return le2.isAbove(le1.point) ? -1 : 1; - let signedAreaLe1 = signedArea(le1.point, le2.point, le2.otherEvent.point); - if (signedAreaLe1 !== 0) { - return signedAreaLe1; - } else { - return signedArea(le1.otherEvent.point, le2.point, le2.otherEvent.point); - } - } else { - let signedAreaLe2 = -signedArea(le2.point, le1.point, le1.otherEvent.point); - if (signedAreaLe2 !== 0) { - return signedAreaLe2; - } else { - return -signedArea(le2.otherEvent.point, le1.point, le1.otherEvent.point); - } - - } - */ - if (compareEvents(le1, le2) === -1) { var evt_older = le1; var evt_newer = le2; @@ -88,43 +67,3 @@ export default function compareSegments(le1, le2) { return compareEvents(le1, le2) === 1 ? 1 : -1; } - - -/* -export default function compareSegments(le1, le2) { - if (le1 === le2) return 0; - - if (compareEvents(le1, le2) === 1) { - var a1 = le1.point; - var a2 = le1.otherEvent.point; - var b1 = le2.point; - var b2 = le2.otherEvent.point; - } else { - var a1 = le2.point; - var a2 = le2.otherEvent.point; - var b1 = le1.point; - var b2 = le1.otherEvent.point; - } - - if (signedArea(a1, b1, b2) === 0){ - if (signedArea(a2, b1, b2) === 0) { - if (le1.isSubject === le2.isSubject) { // same polygon - let p1 = le1.point, p2 = le2.point; - if (p1[0] === p2[0] && p1[1] === p2[1]/ *equals(le1.point, le2.point)* /) { - p1 = le1.otherEvent.point; p2 = le2.otherEvent.point; - if (p1[0] === p2[0] && p1[1] === p2[1]) return 0; - else return le1.contourId > le2.contourId ? 1 : -1; - } else { - return compareEvents(le1, le2) === 1 ? 1 : -1; - } - } else { // Segments are collinear, but belong to separate polygons - return le1.isSubject ? -1 : 1; - } - - } - return signedArea(a2, b1, b2) ? 1 : -1; - } - return signedArea(a1, b1, b2) ? 1 : -1; - -} -*/ \ No newline at end of file diff --git a/test/compare_segments.test.js b/test/compare_segments.test.js index 6904153..76273f7 100644 --- a/test/compare_segments.test.js +++ b/test/compare_segments.test.js @@ -117,15 +117,33 @@ tap.test('compare segments', (main) => { t.end(); }); - main.test('T-shape cases', (t) => { + main.test('T-shaped cases', (t) => { + // Ensures that segments touching at endpoints are ordered correctly + let se1, se2; + // shape: \/ // \ - const se1 = new SweepEvent([0, 1], true, new SweepEvent([1, 0], false)); - const se2 = new SweepEvent([0.5, 0.5], true, new SweepEvent([1, 1], false)); + se1 = new SweepEvent([0, 1], true, new SweepEvent([1, 0], false)); + se2 = new SweepEvent([0.5, 0.5], true, new SweepEvent([1, 1], false)); + t.equal(compareSegments(se1, se2), -1); + t.equal(compareSegments(se2, se1), +1); - //const se1 = new SweepEvent([0, 1], true, new SweepEvent([1, 1], false)); - //const se2 = new SweepEvent([0, 2], true, new SweepEvent([1, 2], false)); + // shape: / + // /\ + se1 = new SweepEvent([0, 0], true, new SweepEvent([1, 1], false)); + se2 = new SweepEvent([0.5, 0.5], true, new SweepEvent([1, 0], false)); + t.equal(compareSegments(se1, se2), +1); + t.equal(compareSegments(se2, se1), -1); + + // shape: T + se1 = new SweepEvent([0, 1], true, new SweepEvent([1, 1], false)); + se2 = new SweepEvent([0.5, 1], true, new SweepEvent([0.5, 0], false)); + t.equal(compareSegments(se1, se2), +1); + t.equal(compareSegments(se2, se1), -1); + // shape: T upside down + se1 = new SweepEvent([0, 0], true, new SweepEvent([1, 0], false)); + se2 = new SweepEvent([0.5, 1], true, new SweepEvent([0.5, 0], false)); t.equal(compareSegments(se1, se2), -1); t.equal(compareSegments(se2, se1), +1); diff --git a/test/edge_cases.test.js b/test/edge_cases.test.js index 513d01d..287e52a 100644 --- a/test/edge_cases.test.js +++ b/test/edge_cases.test.js @@ -242,14 +242,14 @@ tap.test('Edge cases', (main) => { [-5.65625, 110.828125] ]]; const r = [[[ - [198.56943964860557, 22.943242898435663], - [253.09375, 40.984375], - [260.125, 59.265625], - [280.6098710128091, 60.657800699899646], - [280.6098710128091, 62.94324289843566] + [180.60987101280907, 22.943242898435663], + [180.60987101280907, 62.94324289843566], + [280.6098710128091, 62.94324289843566], + [280.6098710128091, 22.943242898435663], ]]]; + console.log(JSON.stringify(r)); - //t.deepEqual(martinez.intersection(p1, p2), r); + t.deepEqual(martinez.intersection(p1, p2), r); t.end(); }); @@ -475,5 +475,45 @@ tap.test('Edge cases', (main) => { t.end(); }); + main.test('issue #97', (t) => { + const p1 = [[ + [0, 0], + [1, 0], + [1, 1], + [0, 1], + [0, 0] + ]]; + const p2 = [[ + [0.5, 0.0], + [0.6, 0.5], + [0.7, 0.5], + [0.5, 0.0] + ]]; + const result = martinez.intersection(p1, p2); + t.deepEqual(result, [[[ + [0.5, 0], + [0.7, 0.5], + [0.6, 0.5], + [0.5, 0], + ]]]); + t.end(); + }); + + main.test('issue #110', (t) => { + const p1 = [[[115, 96], [140, 206], [120, 210], [125, 250], [80, 300], [115, 96]]]; + const p2 = [[[111, 228], [129, 192], [309, 282], [111, 228]]]; + const result = martinez.union(p1, p2); + t.deepEqual(result, [[[ + [80, 300], + [115, 96], + [137.82051282051282, 196.4102564102564], + [309, 282], + [122.6470588235294, 231.1764705882353], + [125, 250], + [80, 300], + ]]]); + t.end(); + }); + main.end(); }); From 254c57f7799628a9df38483e76744469f3dda6f5 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Sat, 11 Jan 2020 12:08:04 +0100 Subject: [PATCH 4/6] linter adjustments; better comments --- src/compare_segments.js | 47 ++++++++++++++--------------------- test/compare_segments.test.js | 2 +- 2 files changed, 20 insertions(+), 29 deletions(-) diff --git a/src/compare_segments.js b/src/compare_segments.js index d323ad1..6cb6856 100644 --- a/src/compare_segments.js +++ b/src/compare_segments.js @@ -11,47 +11,37 @@ import equals from './equals'; export default function compareSegments(le1, le2) { if (le1 === le2) return 0; - // Get orientation of left enpoints w.r.t. other segment - let signedAreaLe1 = signedArea(le1.point, le2.point, le2.otherEvent.point); - let signedAreaLe2 = signedArea(le2.point, le1.point, le1.otherEvent.point); - // Segments are not collinear - //if (signedAreaLe1 !== 0 || signedAreaLe2 !== 0) { if (signedArea(le1.point, le1.otherEvent.point, le2.point) !== 0 || signedArea(le1.point, le1.otherEvent.point, le2.otherEvent.point) !== 0) { - - // If they share their left endpoint use the right endpoint to sort + // Left endpoints exactly identical? Use the right endpoint to sort if (equals(le1.point, le2.point)) return le1.isBelow(le2.otherEvent.point) ? -1 : 1; - // Different left endpoint: use the left endpoint to sort + // Left endpoints identical in x, but different in y? Sort by y if (le1.point[0] === le2.point[0]) return le1.point[1] < le2.point[1] ? -1 : 1; - // has the line segment associated to e1 been inserted - // into S after the line segment associated to e2 ? - //if (compareEvents(le1, le2) === 1) return le2.isAbove(le1.point) ? -1 : 1; - - // The line segment associated to e2 has been inserted - // into S after the line segment associated to e1 - //return le1.isBelow(le2.point) ? -1 : 1; - + // Default case: + // - Determine which segment is older, i.e., has been inserted before in the sweep line. + // - Project the left/start point of the new segment onto the existing segment. + // - If this point falls exactly onto the existing segment, use the right point to sort. + var oldEvt, newEvt, invertSignedArea; if (compareEvents(le1, le2) === -1) { - var evt_older = le1; - var evt_newer = le2; - var signed_area_factor = -1; + oldEvt = le1; + newEvt = le2; + invertSignedArea = -1; } else { - var evt_older = le2; - var evt_newer = le1; - var signed_area_factor = 1; + oldEvt = le2; + newEvt = le1; + invertSignedArea = 1; } - let isLeftPointBelow = signed_area_factor * signedArea(evt_newer.point, evt_older.point, evt_older.otherEvent.point); - if (isLeftPointBelow !== 0) { - return isLeftPointBelow; + let cmpNewLeftPoint = invertSignedArea * signedArea(newEvt.point, oldEvt.point, oldEvt.otherEvent.point); + if (cmpNewLeftPoint !== 0) { + return cmpNewLeftPoint; } else { - return signed_area_factor * signedArea(evt_newer.otherEvent.point, evt_older.point, evt_older.otherEvent.point); + return invertSignedArea * signedArea(newEvt.otherEvent.point, oldEvt.point, oldEvt.otherEvent.point); } - } if (le1.isSubject === le2.isSubject) { // same polygon @@ -60,10 +50,11 @@ export default function compareSegments(le1, le2) { p1 = le1.otherEvent.point; p2 = le2.otherEvent.point; if (p1[0] === p2[0] && p1[1] === p2[1]) return 0; else return le1.contourId > le2.contourId ? 1 : -1; + } else { + return compareEvents(le1, le2) === 1 ? 1 : -1; } } else { // Segments are collinear, but belong to separate polygons return le1.isSubject ? -1 : 1; } - return compareEvents(le1, le2) === 1 ? 1 : -1; } diff --git a/test/compare_segments.test.js b/test/compare_segments.test.js index 76273f7..0ca36a4 100644 --- a/test/compare_segments.test.js +++ b/test/compare_segments.test.js @@ -118,7 +118,7 @@ tap.test('compare segments', (main) => { }); main.test('T-shaped cases', (t) => { - // Ensures that segments touching at endpoints are ordered correctly + // Ensures that segments touching at endpoints are ordered correctly. let se1, se2; // shape: \/ From 92f0270830cb88e2810d6dcce121fb7d3f0e8525 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Sat, 11 Jan 2020 12:14:50 +0100 Subject: [PATCH 5/6] code cleanup from debugging --- src/divide_segment.js | 15 --------------- src/fill_queue.js | 4 ---- src/subdivide_segments.js | 38 -------------------------------------- test/edge_cases.test.js | 4 +++- 4 files changed, 3 insertions(+), 58 deletions(-) diff --git a/src/divide_segment.js b/src/divide_segment.js index 4f80728..d53ceb9 100644 --- a/src/divide_segment.js +++ b/src/divide_segment.js @@ -2,16 +2,6 @@ import SweepEvent from './sweep_event'; import equals from './equals'; import compareEvents from './compare_events'; -function evt_to_str(e) { - if (e == null) { - return "null"; - } else if (e.left) { - return `L ${e.point} => ${e.otherEvent.point}` - } else { - return `E ${e.otherEvent.point} <= ${e.point}` - } -} - /** * @param {SweepEvent} se * @param {Array.} p @@ -22,8 +12,6 @@ export default function divideSegment(se, p, queue) { const r = new SweepEvent(p, false, se, se.isSubject); const l = new SweepEvent(p, true, se.otherEvent, se.isSubject); - console.log("Dividing segment: " + evt_to_str(se) + " at " + p) - /* eslint-disable no-console */ if (equals(se.point, se.otherEvent.point)) { @@ -45,9 +33,6 @@ export default function divideSegment(se, p, queue) { se.otherEvent.otherEvent = l; se.otherEvent = r; - console.log("Pushing l = " + evt_to_str(l)) - console.log("Pushing r = " + evt_to_str(r)) - queue.push(l); queue.push(r); diff --git a/src/fill_queue.js b/src/fill_queue.js index 6127b64..9319722 100644 --- a/src/fill_queue.js +++ b/src/fill_queue.js @@ -41,8 +41,6 @@ function processPolygon(contourOrHole, isSubject, depth, Q, bbox, isExteriorRing // Pushing it so the queue is sorted from left to right, // with object on the left having the highest priority. - // console.log("Pushing sweep events e1: ", e1); - // console.log("Pushing sweep events e2: ", e2); Q.push(e1); Q.push(e2); } @@ -53,7 +51,6 @@ export default function fillQueue(subject, clipping, sbbox, cbbox, operation) { const eventQueue = new Queue(null, compareEvents); let polygonSet, isExteriorRing, i, ii, j, jj; //, k, kk; - console.log("Processing 1. polygon") for (i = 0, ii = subject.length; i < ii; i++) { polygonSet = subject[i]; for (j = 0, jj = polygonSet.length; j < jj; j++) { @@ -63,7 +60,6 @@ export default function fillQueue(subject, clipping, sbbox, cbbox, operation) { } } - console.log("Processing 2. polygon") for (i = 0, ii = clipping.length; i < ii; i++) { polygonSet = clipping[i]; for (j = 0, jj = polygonSet.length; j < jj; j++) { diff --git a/src/subdivide_segments.js b/src/subdivide_segments.js index 3411977..07ef95b 100644 --- a/src/subdivide_segments.js +++ b/src/subdivide_segments.js @@ -8,29 +8,7 @@ import { } from './operation'; -function evt_to_str(e) { - if (e == null) { - return "null"; - } else if (e.left) { - return `L ${e.point} => ${e.otherEvent.point}` - } else { - return `E ${e.otherEvent.point} <= ${e.point}` - } -} -function printSweepLine(sweepLine) { - console.log("Sweepline:"); - var lines = []; - sweepLine.forEach(node => { - lines.push(`${evt_to_str(node.key)} => ${node.data}`) - }) - lines = lines.reverse(); - for (let line of lines) { - console.log(line); - } -} - export default function subdivide(eventQueue, subject, clipping, sbbox, cbbox, operation) { - console.log("Entering 'subdivide'"); const sweepLine = new Tree(compareSegments); const sortedEvents = []; @@ -42,10 +20,6 @@ export default function subdivide(eventQueue, subject, clipping, sbbox, cbbox, o let event = eventQueue.pop(); sortedEvents.push(event); - //console.log("Handling event: ", event); - console.log("\n *** Processing Event: " + evt_to_str(event)) - printSweepLine(sweepLine); - // optimization by bboxes for intersection and difference goes here if ((operation === INTERSECTION && event.point[0] > rightbound) || (operation === DIFFERENCE && event.point[0] > sbbox[2])) { @@ -61,15 +35,11 @@ export default function subdivide(eventQueue, subject, clipping, sbbox, cbbox, o next = sweepLine.next(next); - console.log("next: " + evt_to_str(next ? next.key : null)) - console.log("prev: " + evt_to_str(prev ? prev.key : null)) - const prevEvent = prev ? prev.key : null; let prevprevEvent; computeFields(event, prevEvent, operation); if (next) { if (possibleIntersection(event, next.key, eventQueue) === 2) { - console.log("Intersects with next"); computeFields(event, prevEvent, operation); computeFields(event, next.key, operation); } @@ -77,7 +47,6 @@ export default function subdivide(eventQueue, subject, clipping, sbbox, cbbox, o if (prev) { if (possibleIntersection(prev.key, event, eventQueue) === 2) { - console.log("Intersects with prev"); let prevprev = prev; if (prevprev !== begin) prevprev = sweepLine.prev(prevprev); else prevprev = null; @@ -87,11 +56,6 @@ export default function subdivide(eventQueue, subject, clipping, sbbox, cbbox, o computeFields(event, prevEvent, operation); } } - - console.log(`event.inOut = ${event.inOut}`); - console.log(`event.otherInOut = ${event.otherInOut}`); - console.log(`event.inResult = ${event.inResult}`); - } else { event = event.otherEvent; next = prev = sweepLine.find(event); @@ -105,12 +69,10 @@ export default function subdivide(eventQueue, subject, clipping, sbbox, cbbox, o sweepLine.remove(event); if (next && prev) { - console.log("Checking for intersection between adjacent segments after removal"); possibleIntersection(prev.key, next.key, eventQueue); } } } - printSweepLine(sweepLine); } return sortedEvents; } diff --git a/test/edge_cases.test.js b/test/edge_cases.test.js index 287e52a..2e1ea5e 100644 --- a/test/edge_cases.test.js +++ b/test/edge_cases.test.js @@ -217,6 +217,9 @@ tap.test('Edge cases', (main) => { }); main.test('infinite loop crash', (t) => { + // This test case currently only ensures that there is no infinite loop. + // The specified result is still invalid. See discussion at: + // https://github.com/w8r/martinez/issues/114 const p1 = [[ [180.60987101280907, 22.943242898435663], [280.6098710128091, 22.943242898435663], @@ -247,7 +250,6 @@ tap.test('Edge cases', (main) => { [280.6098710128091, 62.94324289843566], [280.6098710128091, 22.943242898435663], ]]]; - console.log(JSON.stringify(r)); t.deepEqual(martinez.intersection(p1, p2), r); t.end(); From e04385246c9a566b5756accfd9a6131a5bdecae3 Mon Sep 17 00:00:00 2001 From: Fabian Keller Date: Mon, 13 Jan 2020 21:55:39 +0100 Subject: [PATCH 6/6] fix confusing issue110.geojson --- test/fixtures/issue110.geojson | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/fixtures/issue110.geojson b/test/fixtures/issue110.geojson index 4f09423..16426c8 100644 --- a/test/fixtures/issue110.geojson +++ b/test/fixtures/issue110.geojson @@ -5,14 +5,14 @@ "properties": {}, "geometry": { "type": "Polygon", - "coordinates": [[[115,96], [140,206], [120,210], [125,250], [80,300]]] + "coordinates": [[[115,96], [140,206], [120,210], [125,250], [80,300], [115,96]]] } },{ "type": "Feature", "properties": {}, "geometry": { "type": "Polygon", - "coordinates": [[[111,228], [129,192], [309,282]]] + "coordinates": [[[111,228], [129,192], [309,282], [111,228]]] } }] }