|
17219 | 17219 | profileStart('snapAndCut'); |
17220 | 17220 | var arcs = dataset.arcs; |
17221 | 17221 | var cutOpts = snapDist > 0 ? {tolerance: snapDist} : {tolerance: 0}; |
| 17222 | + |
| 17223 | + // Probe for intersections before any modification. If the input has none, |
| 17224 | + // every pass of the loop below is provably a no-op: snap() can only |
| 17225 | + // consolidate FP noise around intersection points, cutPathsAtIntersections |
| 17226 | + // inserts cut points only where segments cross, and buildTopology is gated |
| 17227 | + // on coordsHaveChanged. So we can return early and skip a ~O(V log V) snap |
| 17228 | + // that would snap zero points, which is the dominant cost of robust |
| 17229 | + // dissolve on already-clean polygon input. |
| 17230 | + // |
| 17231 | + // limit=1 makes the probe cheap on dirty input too — it stops the stripe |
| 17232 | + // scan after the first hit, so the probe's full cost is only paid on |
| 17233 | + // truly clean input (where it replaces the equivalent scan that |
| 17234 | + // cutPathsAtIntersections would otherwise do on pass 1). |
| 17235 | + var probeOpts = {tolerance: cutOpts.tolerance, limit: 1}; |
| 17236 | + profileStart('probeIntersections'); |
| 17237 | + var probe = findSegmentIntersections(arcs, probeOpts); |
| 17238 | + profileEnd('probeIntersections'); |
| 17239 | + if (probe.length === 0) { |
| 17240 | + debug('[snapAndCut] skipped (no intersections)'); |
| 17241 | + profileEnd('snapAndCut'); |
| 17242 | + return false; |
| 17243 | + } |
| 17244 | + |
17222 | 17245 | var coordsHaveChanged = false; |
17223 | 17246 | var snapCount = 0, dupeCount, cutCount; |
17224 | 17247 | var maxLoops = 4, loopCount = 0; |
|
0 commit comments