Skip to content

Commit e3c3e54

Browse files
committed
Revert b0659e0.
This appears to cause a significant performance regression as shown in the rotating Ocean example (http://bl.ocks.org/mbostock/6713736): performance went from 60 FPS to 20 FPS.
1 parent af6a4e0 commit e3c3e54

7 files changed

Lines changed: 184 additions & 256 deletions

File tree

d3.js

Lines changed: 78 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -2616,15 +2616,16 @@ d3 = function() {
26162616
function d3_true() {
26172617
return true;
26182618
}
2619-
function d3_geo_clipPolygon(segments, compare, clipStartInside, pointInPolygon, interpolate, listener) {
2620-
var subject = [], clip = [], rings = [], n = segments.length;
2621-
for (var i = 0; i < n; ++i) {
2622-
var segment = segments[i];
2623-
if ((m = segment.length - 1) <= 0) continue;
2624-
var m, p0 = segment[0], p1 = segment[m];
2619+
function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) {
2620+
var subject = [], clip = [];
2621+
segments.forEach(function(segment) {
2622+
if ((n = segment.length - 1) <= 0) return;
2623+
var n, p0 = segment[0], p1 = segment[n];
26252624
if (d3_geo_sphericalEqual(p0, p1)) {
2626-
rings.push(segment);
2627-
continue;
2625+
listener.lineStart();
2626+
for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]);
2627+
listener.lineEnd();
2628+
return;
26282629
}
26292630
var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false);
26302631
a.o = b;
@@ -2635,86 +2636,45 @@ d3 = function() {
26352636
a.o = b;
26362637
subject.push(a);
26372638
clip.push(b);
2638-
}
2639-
if (subject.length) {
2640-
clip.sort(compare);
2641-
d3_geo_clipPolygonLinkCircular(subject);
2642-
d3_geo_clipPolygonLinkCircular(clip);
2643-
for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) {
2644-
clip[i].e = entry = !entry;
2645-
}
2646-
var start = subject[0], listener_ = listener, point;
2647-
if (rings.length) listener = d3_geo_clipBufferListener();
2648-
while (1) {
2649-
var current = start, isSubject = true;
2650-
while (current.v) if ((current = current.n) === start) break;
2651-
if (current.v) break;
2652-
listener.polygonStart();
2653-
listener.lineStart();
2654-
do {
2655-
current.v = current.o.v = true;
2656-
if (current.e) {
2657-
if (isSubject) {
2658-
for (var i = 0, points = current.z, n = points.length; i < n; ++i) {
2659-
listener.point((point = points[i])[0], point[1]);
2660-
}
2661-
} else {
2662-
interpolate(current.x, current.n.x, 1, listener);
2663-
}
2664-
current = current.n;
2639+
});
2640+
clip.sort(compare);
2641+
d3_geo_clipPolygonLinkCircular(subject);
2642+
d3_geo_clipPolygonLinkCircular(clip);
2643+
if (!subject.length) return;
2644+
for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) {
2645+
clip[i].e = entry = !entry;
2646+
}
2647+
var start = subject[0], points, point;
2648+
while (1) {
2649+
var current = start, isSubject = true;
2650+
while (current.v) if ((current = current.n) === start) return;
2651+
points = current.z;
2652+
listener.lineStart();
2653+
do {
2654+
current.v = current.o.v = true;
2655+
if (current.e) {
2656+
if (isSubject) {
2657+
for (var i = 0, n = points.length; i < n; ++i) listener.point((point = points[i])[0], point[1]);
26652658
} else {
2666-
if (isSubject) {
2667-
for (var points = current.z, i = points.length; --i >= 0; ) {
2668-
listener.point((point = points[i])[0], point[1]);
2669-
}
2670-
} else {
2671-
interpolate(current.x, current.p.x, -1, listener);
2672-
}
2673-
current = current.p;
2659+
interpolate(current.x, current.n.x, 1, listener);
26742660
}
2675-
current = current.o;
2676-
isSubject = !isSubject;
2677-
} while (!current.v);
2678-
listener.lineEnd();
2679-
listener.polygonEnd();
2680-
}
2681-
if (n = rings.length) {
2682-
var exteriors = listener.buffer(), exteriorPolygon = [ null ];
2683-
listener = listener_;
2684-
for (var j = 0, m = exteriors.length; j < m; ++j) {
2685-
var exterior = exteriorPolygon[0] = exteriors[j];
2686-
listener.polygonStart();
2687-
d3_geo_clipPolygonStreamRing(exterior, listener);
2688-
for (var i = 0; i < n; ++i) {
2689-
var ring = rings[i];
2690-
if (ring && pointInPolygon(ring[0], exteriorPolygon)) {
2691-
d3_geo_clipPolygonStreamRing(ring, listener);
2692-
rings[i] = null;
2693-
}
2661+
current = current.n;
2662+
} else {
2663+
if (isSubject) {
2664+
points = current.p.z;
2665+
for (var i = points.length - 1; i >= 0; --i) listener.point((point = points[i])[0], point[1]);
2666+
} else {
2667+
interpolate(current.x, current.p.x, -1, listener);
26942668
}
2695-
listener.polygonEnd();
2669+
current = current.p;
26962670
}
2697-
}
2698-
} else if ((n = rings.length) || clipStartInside) {
2699-
listener.polygonStart();
2700-
if (clipStartInside) {
2701-
listener.lineStart();
2702-
interpolate(null, null, 1, listener);
2703-
listener.lineEnd();
2704-
}
2705-
for (var i = 0; i < n; ++i) {
2706-
d3_geo_clipPolygonStreamRing(rings[i], listener);
2707-
}
2708-
listener.polygonEnd();
2671+
current = current.o;
2672+
points = current.z;
2673+
isSubject = !isSubject;
2674+
} while (!current.v);
2675+
listener.lineEnd();
27092676
}
27102677
}
2711-
function d3_geo_clipPolygonStreamRing(ring, listener) {
2712-
listener.lineStart();
2713-
for (var i = 0, n = ring.length - 1, p; i < n; ++i) {
2714-
listener.point((p = ring[i])[0], p[1]);
2715-
}
2716-
listener.lineEnd();
2717-
}
27182678
function d3_geo_clipPolygonLinkCircular(array) {
27192679
if (!(n = array.length)) return;
27202680
var n, i = 0, a = array[0], b;
@@ -2747,12 +2707,22 @@ d3 = function() {
27472707
clip.lineEnd = ringEnd;
27482708
segments = [];
27492709
polygon = [];
2710+
listener.polygonStart();
27502711
},
27512712
polygonEnd: function() {
27522713
clip.point = point;
27532714
clip.lineStart = lineStart;
27542715
clip.lineEnd = lineEnd;
2755-
d3_geo_clipPolygon(d3.merge(segments), d3_geo_clipSort, d3_geo_pointInPolygon(rotatedClipStart, polygon), d3_geo_pointInPolygon, interpolate, listener);
2716+
segments = d3.merge(segments);
2717+
var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon);
2718+
if (segments.length) {
2719+
d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener);
2720+
} else if (clipStartInside) {
2721+
listener.lineStart();
2722+
interpolate(null, null, 1, listener);
2723+
listener.lineEnd();
2724+
}
2725+
listener.polygonEnd();
27562726
segments = polygon = null;
27572727
},
27582728
sphere: function() {
@@ -2793,11 +2763,19 @@ d3 = function() {
27932763
function ringEnd() {
27942764
pointRing(ring[0][0], ring[0][1]);
27952765
ringListener.lineEnd();
2796-
var clean = ringListener.clean(), ringSegments = buffer.buffer(), n = ringSegments.length;
2766+
var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length;
27972767
ring.pop();
27982768
polygon.push(ring);
27992769
ring = null;
28002770
if (!n) return;
2771+
if (clean & 1) {
2772+
segment = ringSegments[0];
2773+
var n = segment.length - 1, i = -1, point;
2774+
listener.lineStart();
2775+
while (++i < n) listener.point((point = segment[i])[0], point[1]);
2776+
listener.lineEnd();
2777+
return;
2778+
}
28012779
if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
28022780
segments.push(ringSegments.filter(d3_geo_clipSegmentLength1));
28032781
}
@@ -2817,8 +2795,6 @@ d3 = function() {
28172795
line.push([ λ, φ ]);
28182796
},
28192797
lineEnd: d3_noop,
2820-
polygonStart: d3_noop,
2821-
polygonEnd: d3_noop,
28222798
buffer: function() {
28232799
var buffer = lines;
28242800
lines = [];
@@ -3111,11 +3087,25 @@ d3 = function() {
31113087
clean = true;
31123088
},
31133089
polygonEnd: function() {
3114-
d3_geo_clipPolygon(d3.merge(segments), compare, pointInPolygon([ x0, y1 ], polygon), pointInPolygon, interpolate, listener = listener_);
3090+
listener = listener_;
3091+
segments = d3.merge(segments);
3092+
var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length;
3093+
if (inside || visible) {
3094+
listener.polygonStart();
3095+
if (inside) {
3096+
listener.lineStart();
3097+
interpolate(null, null, 1, listener);
3098+
listener.lineEnd();
3099+
}
3100+
if (visible) {
3101+
d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener);
3102+
}
3103+
listener.polygonEnd();
3104+
}
31153105
segments = polygon = ring = null;
31163106
}
31173107
};
3118-
function pointInPolygon(p, polygon) {
3108+
function insidePolygon(p) {
31193109
var wn = 0, n = polygon.length, y = p[1];
31203110
for (var i = 0; i < n; ++i) {
31213111
for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) {

d3.min.js

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/geo/clip-extent.js

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -48,12 +48,28 @@ function d3_geo_clipExtent(x0, y0, x1, y1) {
4848
clean = true;
4949
},
5050
polygonEnd: function() {
51-
d3_geo_clipPolygon(d3.merge(segments), compare, pointInPolygon([x0, y1], polygon), pointInPolygon, interpolate, listener = listener_);
51+
listener = listener_;
52+
segments = d3.merge(segments);
53+
var clipStartInside = insidePolygon([x0, y1]),
54+
inside = clean && clipStartInside,
55+
visible = segments.length;
56+
if (inside || visible) {
57+
listener.polygonStart();
58+
if (inside) {
59+
listener.lineStart();
60+
interpolate(null, null, 1, listener);
61+
listener.lineEnd();
62+
}
63+
if (visible) {
64+
d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener);
65+
}
66+
listener.polygonEnd();
67+
}
5268
segments = polygon = ring = null;
5369
}
5470
};
5571

56-
function pointInPolygon(p, polygon) {
72+
function insidePolygon(p) {
5773
var wn = 0, // the winding number counter
5874
n = polygon.length,
5975
y = p[1];

0 commit comments

Comments
 (0)