Commit a264d55e authored by Jason Davies's avatar Jason Davies
Browse files

Don’t generate empty polygons during clipping.

Fixes #1823; spurious closePath events were being generated for
degenerate polygons due to generation of empty polygons and rings in
rare cases.
parent fa55eead
......@@ -3224,7 +3224,6 @@
clip.lineEnd = ringEnd;
segments = [];
polygon = [];
listener.polygonStart();
},
polygonEnd: function() {
clip.point = point;
......@@ -3233,13 +3232,15 @@
segments = d3.merge(segments);
var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon);
if (segments.length) {
if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener);
} else if (clipStartInside) {
if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
listener.lineStart();
interpolate(null, null, 1, listener);
listener.lineEnd();
}
listener.polygonEnd();
if (polygonStarted) listener.polygonEnd(), polygonStarted = false;
segments = polygon = null;
},
sphere: function() {
......@@ -3267,7 +3268,7 @@
line.lineEnd();
}
var segments;
var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygon, ring;
var buffer = d3_geo_clipBufferListener(), ringListener = clipLine(buffer), polygonStarted = false, polygon, ring;
function pointRing(λ, φ) {
ring.push([ λ, φ ]);
var point = rotate(λ, φ);
......@@ -3288,9 +3289,12 @@
if (clean & 1) {
segment = ringSegments[0];
var n = segment.length - 1, i = -1, point;
if (n > 0) {
if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
listener.lineStart();
while (++i < n) listener.point((point = segment[i])[0], point[1]);
listener.lineEnd();
}
return;
}
if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
......
This source diff could not be displayed because it is too large. You can view the blob instead.
......@@ -18,7 +18,6 @@ function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) {
clip.lineEnd = ringEnd;
segments = [];
polygon = [];
listener.polygonStart();
},
polygonEnd: function() {
clip.point = point;
......@@ -28,13 +27,15 @@ function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) {
segments = d3.merge(segments);
var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon);
if (segments.length) {
if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener);
} else if (clipStartInside) {
if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
listener.lineStart();
interpolate(null, null, 1, listener);
listener.lineEnd();
}
listener.polygonEnd();
if (polygonStarted) listener.polygonEnd(), polygonStarted = false;
segments = polygon = null;
},
sphere: function() {
......@@ -61,6 +62,7 @@ function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) {
var buffer = d3_geo_clipBufferListener(),
ringListener = clipLine(buffer),
polygonStarted = false,
polygon,
ring;
......@@ -96,9 +98,12 @@ function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) {
var n = segment.length - 1,
i = -1,
point;
if (n > 0) {
if (!polygonStarted) listener.polygonStart(), polygonStarted = true;
listener.lineStart();
while (++i < n) listener.point((point = segment[i])[0], point[1]);
listener.lineEnd();
}
return;
}
......
......@@ -386,6 +386,10 @@ suite.addBatch({
"renders a small circle of 120°": function(p) {
p(_.geo.circle().angle(120)());
assert.deepEqual(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }), [{type: "moveTo", x: 87, y: 700}]);
},
"degenerate polygon": function(p) {
p({type: "Polygon", coordinates: [[[0, 0], [0, 0], [0, 0], [0, 0]]]});
assert.deepEqual(testContext.buffer(), []);
}
},
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment