Merge remote-tracking branch 'origin/geo-rings' into 3.3.7

Conflicts:
	src/geo/clip-antimeridian.js
This commit is contained in:
Mike Bostock 2013-10-09 08:07:55 -07:00
Родитель dc8a61595f d23919fe82
Коммит 261940aa54
10 изменённых файлов: 290 добавлений и 222 удалений

212
d3.js поставляемый
Просмотреть файл

@ -186,7 +186,8 @@ d3 = function() {
return entries;
};
d3.merge = function(arrays) {
return Array.prototype.concat.apply([], arrays);
var n = arrays.length;
return n ? n > 1 ? Array.prototype.concat.apply([], arrays) : arrays[0] : [];
};
var abs = Math.abs;
d3.range = function(start, stop, step) {
@ -2612,92 +2613,105 @@ d3 = function() {
function d3_true() {
return true;
}
function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) {
var subject = [], clip = [];
segments.forEach(function(segment) {
if ((n = segment.length - 1) <= 0) return;
var n, p0 = segment[0], p1 = segment[n];
function d3_geo_clipPolygon(segments, compare, clipStartInside, pointInPolygon, interpolate, listener) {
var subject = [], clip = [], rings = [], n = segments.length;
for (var i = 0; i < n; ++i) {
var segment = segments[i];
if ((m = segment.length - 1) <= 0) continue;
var m, p0 = segment[0], p1 = segment[m];
if (d3_geo_sphericalEqual(p0, p1)) {
listener.lineStart();
for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]);
listener.lineEnd();
return;
rings.push(segment);
continue;
}
var a = {
point: p0,
points: segment,
other: null,
visited: false,
entry: true,
subject: true
}, b = {
point: p0,
points: [ p0 ],
other: a,
visited: false,
entry: false,
subject: false
};
var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true), b = new d3_geo_clipPolygonIntersection(p0, null, a, false);
a.other = b;
subject.push(a);
clip.push(b);
a = {
point: p1,
points: [ p1 ],
other: null,
visited: false,
entry: false,
subject: true
};
b = {
point: p1,
points: [ p1 ],
other: a,
visited: false,
entry: true,
subject: false
};
a = new d3_geo_clipPolygonIntersection(p1, segment, null, false);
b = new d3_geo_clipPolygonIntersection(p1, null, a, true);
a.other = b;
subject.push(a);
clip.push(b);
});
clip.sort(compare);
d3_geo_clipPolygonLinkCircular(subject);
d3_geo_clipPolygonLinkCircular(clip);
if (!subject.length) return;
for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) {
clip[i].entry = entry = !entry;
}
var start = subject[0], current, points, point;
while (1) {
current = start;
while (current.visited) if ((current = current.next) === start) return;
points = current.points;
listener.lineStart();
do {
current.visited = current.other.visited = true;
if (current.entry) {
if (current.subject) {
for (var i = 0; i < points.length; i++) listener.point((point = points[i])[0], point[1]);
if (subject.length) {
clip.sort(compare);
d3_geo_clipPolygonLinkCircular(subject);
d3_geo_clipPolygonLinkCircular(clip);
for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) {
clip[i].entry = entry = !entry;
}
var start = subject[0], listener_ = listener, point;
if (rings.length) listener = d3_geo_clipBufferListener();
while (1) {
var current = start, isSubject = true;
while (current.visited) if ((current = current.next) === start) break;
if (current.visited) break;
listener.polygonStart();
listener.lineStart();
do {
current.visited = current.other.visited = true;
if (current.entry) {
if (isSubject) {
for (var i = 0, points = current.points, n = points.length; i < n; ++i) {
listener.point((point = points[i])[0], point[1]);
}
} else {
interpolate(current.point, current.next.point, 1, listener);
}
current = current.next;
} else {
interpolate(current.point, current.next.point, 1, listener);
if (isSubject) {
for (var points = current.points, i = points.length; --i >= 0; ) {
listener.point((point = points[i])[0], point[1]);
}
} else {
interpolate(current.point, current.prev.point, -1, listener);
}
current = current.prev;
}
current = current.next;
} else {
if (current.subject) {
points = current.prev.points;
for (var i = points.length; --i >= 0; ) listener.point((point = points[i])[0], point[1]);
} else {
interpolate(current.point, current.prev.point, -1, listener);
current = current.other;
isSubject = !isSubject;
} while (!current.visited);
listener.lineEnd();
listener.polygonEnd();
}
if (n = rings.length) {
var exteriors = listener.buffer(), exteriorPolygon = [ null ];
listener = listener_;
for (var j = 0, m = exteriors.length; j < m; ++j) {
var exterior = exteriorPolygon[0] = exteriors[j];
listener.polygonStart();
d3_geo_clipPolygonStreamRing(exterior, listener);
for (var i = 0; i < n; ++i) {
var ring = rings[i];
if (ring && pointInPolygon(ring[0], exteriorPolygon)) {
d3_geo_clipPolygonStreamRing(ring, listener);
rings[i] = null;
}
}
current = current.prev;
listener.polygonEnd();
}
current = current.other;
points = current.points;
} while (!current.visited);
listener.lineEnd();
}
} else if ((n = rings.length) || clipStartInside) {
listener.polygonStart();
if (clipStartInside) {
listener.lineStart();
interpolate(null, null, 1, listener);
listener.lineEnd();
}
for (var i = 0; i < n; ++i) {
d3_geo_clipPolygonStreamRing(rings[i], listener);
}
listener.polygonEnd();
}
}
function d3_geo_clipPolygonStreamRing(ring, listener) {
listener.lineStart();
for (var i = 0, n = ring.length - 1, p; i < n; ++i) {
listener.point((p = ring[i])[0], p[1]);
}
listener.lineEnd();
}
function d3_geo_clipPolygonLinkCircular(array) {
if (!(n = array.length)) return;
var n, i = 0, a = array[0], b;
@ -2709,6 +2723,14 @@ d3 = function() {
a.next = b = array[0];
b.prev = a;
}
function d3_geo_clipPolygonIntersection(point, points, other, entry) {
this.point = point;
this.points = points;
this.other = other;
this.entry = entry;
this.visited = false;
this.next = this.prev = null;
}
function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) {
return function(rotate, listener) {
var line = clipLine(listener), rotatedClipStart = rotate.invert(clipStart[0], clipStart[1]);
@ -2722,22 +2744,12 @@ d3 = function() {
clip.lineEnd = ringEnd;
segments = [];
polygon = [];
listener.polygonStart();
},
polygonEnd: function() {
clip.point = point;
clip.lineStart = lineStart;
clip.lineEnd = lineEnd;
segments = d3.merge(segments);
var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon);
if (segments.length) {
d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener);
} else if (clipStartInside) {
listener.lineStart();
interpolate(null, null, 1, listener);
listener.lineEnd();
}
listener.polygonEnd();
d3_geo_clipPolygon(d3.merge(segments), d3_geo_clipSort, d3_geo_pointInPolygon(rotatedClipStart, polygon), d3_geo_pointInPolygon, interpolate, listener);
segments = polygon = null;
},
sphere: function() {
@ -2778,19 +2790,11 @@ d3 = function() {
function ringEnd() {
pointRing(ring[0][0], ring[0][1]);
ringListener.lineEnd();
var clean = ringListener.clean(), ringSegments = buffer.buffer(), segment, n = ringSegments.length;
var clean = ringListener.clean(), ringSegments = buffer.buffer(), n = ringSegments.length;
ring.pop();
polygon.push(ring);
ring = null;
if (!n) return;
if (clean & 1) {
segment = ringSegments[0];
var n = segment.length - 1, i = -1, point;
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()));
segments.push(ringSegments.filter(d3_geo_clipSegmentLength1));
}
@ -2810,6 +2814,8 @@ d3 = function() {
line.push([ λ, φ ]);
},
lineEnd: d3_noop,
polygonStart: d3_noop,
polygonEnd: d3_noop,
buffer: function() {
var buffer = lines;
lines = [];
@ -2836,7 +2842,7 @@ d3 = function() {
point = ring[j];
var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), = λ - λ0, antimeridian = abs() > π, k = sinφ0 * sinφ;
d3_geo_areaRingSum.add(Math.atan2(k * Math.sin(), cosφ0 * cosφ + k * Math.cos()));
polarAngle += antimeridian ? + ( >= 0 ? 2 : -2) * π : ;
polarAngle += antimeridian ? + ( >= 0 ? τ : -τ) : ;
if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) {
var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point));
d3_geo_cartesianNormalize(arc);
@ -2911,7 +2917,7 @@ d3 = function() {
listener.point(-π, 0);
listener.point(-π, φ);
} else if (abs(from[0] - to[0]) > ε) {
var s = (from[0] < to[0] ? 1 : -1) * π;
var s = from[0] < to[0] ? π : -π;
φ = direction * s / 2;
listener.point(-s, φ);
listener.point(0, φ);
@ -3094,25 +3100,11 @@ d3 = function() {
clean = true;
},
polygonEnd: function() {
listener = listener_;
segments = d3.merge(segments);
var clipStartInside = insidePolygon([ x0, y1 ]), inside = clean && clipStartInside, visible = segments.length;
if (inside || visible) {
listener.polygonStart();
if (inside) {
listener.lineStart();
interpolate(null, null, 1, listener);
listener.lineEnd();
}
if (visible) {
d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener);
}
listener.polygonEnd();
}
d3_geo_clipPolygon(d3.merge(segments), compare, pointInPolygon([ x0, y1 ], polygon), pointInPolygon, interpolate, listener = listener_);
segments = polygon = ring = null;
}
};
function insidePolygon(p) {
function pointInPolygon(p, polygon) {
var wn = 0, n = polygon.length, y = p[1];
for (var i = 0; i < n; ++i) {
for (var j = 1, v = polygon[i], m = v.length, a = v[0], b; j < m; ++j) {

10
d3.min.js поставляемый

Различия файлов скрыты, потому что одна или несколько строк слишком длинны

Просмотреть файл

@ -1,3 +1,7 @@
d3.merge = function(arrays) {
return Array.prototype.concat.apply([], arrays);
var n = arrays.length;
return n ? n > 1
? Array.prototype.concat.apply([], arrays)
: arrays[0]
: [];
};

Просмотреть файл

@ -84,7 +84,7 @@ function d3_geo_clipAntimeridianInterpolate(from, to, direction, listener) {
listener.point(-π, 0);
listener.point(-π, φ);
} else if (abs(from[0] - to[0]) > ε) {
var s = (from[0] < to[0] ? 1 : -1) * π;
var s = from[0] < to[0] ? π : -π;
φ = direction * s / 2;
listener.point(-s, φ);
listener.point( 0, φ);

Просмотреть файл

@ -48,28 +48,12 @@ function d3_geo_clipExtent(x0, y0, x1, y1) {
clean = true;
},
polygonEnd: function() {
listener = listener_;
segments = d3.merge(segments);
var clipStartInside = insidePolygon([x0, y1]),
inside = clean && clipStartInside,
visible = segments.length;
if (inside || visible) {
listener.polygonStart();
if (inside) {
listener.lineStart();
interpolate(null, null, 1, listener);
listener.lineEnd();
}
if (visible) {
d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener);
}
listener.polygonEnd();
}
d3_geo_clipPolygon(d3.merge(segments), compare, pointInPolygon([x0, y1], polygon), pointInPolygon, interpolate, listener = listener_);
segments = polygon = ring = null;
}
};
function insidePolygon(p) {
function pointInPolygon(p, polygon) {
var wn = 0, // the winding number counter
n = polygon.length,
y = p[1];

Просмотреть файл

@ -1,81 +1,140 @@
import "../math/trigonometry";
import "spherical";
// General spherical polygon clipping algorithm: takes a polygon, cuts it into
// visible line segments and rejoins the segments by interpolating along the
// clip edge.
function d3_geo_clipPolygon(segments, compare, clipStartInside, interpolate, listener) {
// General spherical polygon clipping algorithm.
// Given a polygon that has been cut into visible line segments, rejoins the
// segments by interpolating along the clip edge where necessary.
function d3_geo_clipPolygon(segments, compare, clipStartInside, pointInPolygon, interpolate, listener) {
var subject = [],
clip = [];
clip = [],
rings = [],
n = segments.length;
segments.forEach(function(segment) {
if ((n = segment.length - 1) <= 0) return;
var n, p0 = segment[0], p1 = segment[n];
for (var i = 0; i < n; ++i) {
var segment = segments[i];
if ((m = segment.length - 1) <= 0) continue;
var m, p0 = segment[0], p1 = segment[m];
// If the first and last points of a segment are coincident, then treat as
// a closed ring.
// TODO if all rings are closed, then the winding order of the exterior
// ring should be checked.
if (d3_geo_sphericalEqual(p0, p1)) {
listener.lineStart();
for (var i = 0; i < n; ++i) listener.point((p0 = segment[i])[0], p0[1]);
listener.lineEnd();
return;
rings.push(segment);
continue;
}
var a = {point: p0, points: segment, other: null, visited: false, entry: true, subject: true},
b = {point: p0, points: [p0], other: a, visited: false, entry: false, subject: false};
var a = new d3_geo_clipPolygonIntersection(p0, segment, null, true),
b = new d3_geo_clipPolygonIntersection(p0, null, a, false);
a.other = b;
subject.push(a);
clip.push(b);
a = {point: p1, points: [p1], other: null, visited: false, entry: false, subject: true};
b = {point: p1, points: [p1], other: a, visited: false, entry: true, subject: false};
a = new d3_geo_clipPolygonIntersection(p1, segment, null, false);
b = new d3_geo_clipPolygonIntersection(p1, null, a, true);
a.other = b;
subject.push(a);
clip.push(b);
});
clip.sort(compare);
d3_geo_clipPolygonLinkCircular(subject);
d3_geo_clipPolygonLinkCircular(clip);
if (!subject.length) return;
for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) {
clip[i].entry = entry = !entry;
}
var start = subject[0],
current,
points,
point;
while (1) {
// Find first unvisited intersection.
current = start;
while (current.visited) if ((current = current.next) === start) return;
points = current.points;
listener.lineStart();
do {
current.visited = current.other.visited = true;
if (current.entry) {
if (current.subject) {
for (var i = 0; i < points.length; i++) listener.point((point = points[i])[0], point[1]);
// If there are any segments to be joined…
if (subject.length) {
clip.sort(compare);
d3_geo_clipPolygonLinkCircular(subject);
d3_geo_clipPolygonLinkCircular(clip);
// Mark intersection points as alternating between entering and exiting.
for (var i = 0, entry = clipStartInside, n = clip.length; i < n; ++i) {
clip[i].entry = entry = !entry;
}
var start = subject[0],
listener_ = listener,
point;
// If there are closed rings, then buffer the rejoined segments so they can
// be output with the correct interior rings later.
if (rings.length) listener = d3_geo_clipBufferListener();
while (1) {
// Find first unvisited intersection.
var current = start,
isSubject = true;
while (current.visited) if ((current = current.next) === start) break;
if (current.visited) break;
listener.polygonStart();
listener.lineStart();
do {
current.visited = current.other.visited = true;
if (current.entry) {
if (isSubject) {
for (var i = 0, points = current.points, n = points.length; i < n; ++i) {
listener.point((point = points[i])[0], point[1]);
}
} else {
interpolate(current.point, current.next.point, 1, listener);
}
current = current.next;
} else {
interpolate(current.point, current.next.point, 1, listener);
if (isSubject) {
for (var points = current.points, i = points.length; --i >= 0;) {
listener.point((point = points[i])[0], point[1]);
}
} else {
interpolate(current.point, current.prev.point, -1, listener);
}
current = current.prev;
}
current = current.next;
} else {
if (current.subject) {
points = current.prev.points;
for (var i = points.length; --i >= 0;) listener.point((point = points[i])[0], point[1]);
} else {
interpolate(current.point, current.prev.point, -1, listener);
current = current.other;
isSubject = !isSubject;
} while (!current.visited);
listener.lineEnd();
listener.polygonEnd();
}
if (n = rings.length) {
var exteriors = listener.buffer(),
exteriorPolygon = [null];
listener = listener_;
for (var j = 0, m = exteriors.length; j < m; ++j) {
var exterior = exteriorPolygon[0] = exteriors[j];
listener.polygonStart();
d3_geo_clipPolygonStreamRing(exterior, listener);
for (var i = 0; i < n; ++i) {
var ring = rings[i];
if (ring && pointInPolygon(ring[0], exteriorPolygon)) {
d3_geo_clipPolygonStreamRing(ring, listener);
rings[i] = null;
}
}
current = current.prev;
listener.polygonEnd();
}
current = current.other;
points = current.points;
} while (!current.visited);
listener.lineEnd();
}
}
// Otherwise, there are no intersections.
else if ((n = rings.length) || clipStartInside) {
listener.polygonStart();
// If the clip polygon is inside the subject polygon, then the clip polygon
// becomes the exterior.
if (clipStartInside) {
listener.lineStart();
interpolate(null, null, 1, listener);
listener.lineEnd();
}
for (var i = 0; i < n; ++i) {
d3_geo_clipPolygonStreamRing(rings[i], listener);
}
listener.polygonEnd();
}
}
function d3_geo_clipPolygonStreamRing(ring, listener) {
listener.lineStart();
for (var i = 0, n = ring.length - 1, p; i < n; ++i) {
listener.point((p = ring[i])[0], p[1]);
}
listener.lineEnd();
}
function d3_geo_clipPolygonLinkCircular(array) {
@ -92,3 +151,12 @@ function d3_geo_clipPolygonLinkCircular(array) {
a.next = b = array[0];
b.prev = a;
}
function d3_geo_clipPolygonIntersection(point, points, other, entry) {
this.point = point;
this.points = points;
this.other = other;
this.entry = entry;
this.visited = false;
this.next = this.prev = null;
}

Просмотреть файл

@ -18,23 +18,14 @@ function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) {
clip.lineEnd = ringEnd;
segments = [];
polygon = [];
listener.polygonStart();
},
polygonEnd: function() {
clip.point = point;
clip.lineStart = lineStart;
clip.lineEnd = lineEnd;
segments = d3.merge(segments);
var clipStartInside = d3_geo_pointInPolygon(rotatedClipStart, polygon);
if (segments.length) {
d3_geo_clipPolygon(segments, d3_geo_clipSort, clipStartInside, interpolate, listener);
} else if (clipStartInside) {
listener.lineStart();
interpolate(null, null, 1, listener);
listener.lineEnd();
}
listener.polygonEnd();
d3_geo_clipPolygon(d3.merge(segments), d3_geo_clipSort, d3_geo_pointInPolygon(rotatedClipStart, polygon), d3_geo_pointInPolygon, interpolate, listener);
segments = polygon = null;
},
sphere: function() {
@ -81,7 +72,6 @@ function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) {
var clean = ringListener.clean(),
ringSegments = buffer.buffer(),
segment,
n = ringSegments.length;
ring.pop();
@ -90,18 +80,6 @@ function d3_geo_clip(pointVisible, clipLine, interpolate, clipStart) {
if (!n) return;
// No intersections.
if (clean & 1) {
segment = ringSegments[0];
var n = segment.length - 1,
i = -1,
point;
listener.lineStart();
while (++i < n) listener.point((point = segment[i])[0], point[1]);
listener.lineEnd();
return;
}
// Rejoin connected segments.
// TODO reuse bufferListener.rejoin()?
if (n > 1 && clean & 2) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
@ -124,6 +102,8 @@ function d3_geo_clipBufferListener() {
lineStart: function() { lines.push(line = []); },
point: function(λ, φ) { line.push([λ, φ]); },
lineEnd: d3_noop,
polygonStart: d3_noop,
polygonEnd: d3_noop,
buffer: function() {
var buffer = lines;
lines = [];

Просмотреть файл

@ -34,7 +34,7 @@ function d3_geo_pointInPolygon(point, polygon) {
k = sinφ0 * sinφ;
d3_geo_areaRingSum.add(Math.atan2(k * Math.sin(), cosφ0 * cosφ + k * Math.cos()));
polarAngle += antimeridian ? + ( >= 0 ? 2 : -2) * π : ;
polarAngle += antimeridian ? + ( >= 0 ? τ : -τ): ;
// Are the longitudes either side of the point's meridian, and are the
// latitudes smaller than the parallel?

Просмотреть файл

@ -1,4 +1,5 @@
var vows = require("vows"),
_ = require("../../"),
load = require("../load"),
assert = require("../assert");
@ -143,6 +144,45 @@ suite.addBatch({
{type: "lineEnd"},
{type: "polygonEnd"}
]);
},
"a polygon that should be split into two polygons, each with a hole": function(d3) {
var clip = d3.geo.clipExtent().extent([[240, 110], [720, 375]]),
stream = clip.stream(testContext);
_.geo.stream({type: "Polygon", coordinates: [
[[300, 30], [660, 30], [660, 200], [570, 200], [570, 80], [390, 80], [390, 200], [300, 200], [300, 30]],
[[330, 140], [330, 170], [360, 170], [360, 140], [330, 140]],
[[600, 140], [600, 170], [630, 170], [630, 140], [600, 140]]
]}, stream);
assert.deepEqual(testContext.buffer(), [
{type: "polygonStart"},
{type: "lineStart"},
{type: "point", x: 660, y: 110},
{type: "point", x: 660, y: 200},
{type: "point", x: 570, y: 200},
{type: "point", x: 570, y: 110},
{type: "lineEnd"},
{type: "lineStart"},
{type: "point", x: 600, y: 140},
{type: "point", x: 600, y: 170},
{type: "point", x: 630, y: 170},
{type: "point", x: 630, y: 140},
{type: "lineEnd"},
{type: "polygonEnd"},
{type: "polygonStart"},
{type: "lineStart"},
{type: "point", x: 390, y: 110},
{type: "point", x: 390, y: 200},
{type: "point", x: 300, y: 200},
{type: "point", x: 300, y: 110},
{type: "lineEnd"},
{type: "lineStart"},
{type: "point", x: 330, y: 140},
{type: "point", x: 330, y: 170},
{type: "point", x: 360, y: 170},
{type: "point", x: 360, y: 140},
{type: "lineEnd"},
{type: "polygonEnd"}
]);
}
}
}

Просмотреть файл

@ -401,8 +401,8 @@ suite.addBatch({
.precision(0)
.clipAngle(90))({type: "Polygon", coordinates: [pole]});
assert.deepEqual(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }), [
{type: "moveTo", x: 510, y: 160},
{type: "moveTo", x: 87, y: 700}
{type: "moveTo", x: 87, y: 700},
{type: "moveTo", x: 510, y: 160}
]);
}
},
@ -506,8 +506,8 @@ suite.addBatch({
"renders a small circle of 120° in two parts": function(p) {
p(_.geo.circle().angle(120)());
assert.deepEqual(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }), [
{type: "moveTo", x: 276, y: 493},
{type: "moveTo", x: 87, y: 700}
{type: "moveTo", x: 87, y: 700},
{type: "moveTo", x: 276, y: 493}
]);
}
},
@ -580,9 +580,9 @@ suite.addBatch({
"renders stripes": function(p) {
p(stripes(80, -80));
assert.deepEqual(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }), [
{type: "moveTo", x: 1331, y: 259},
{type: "moveTo", x: -420, y: -150},
{type: "moveTo", x: -420, y: 650},
{type: "moveTo", x: 1331, y: 259}
{type: "moveTo", x: -420, y: 650}
]);
}
},
@ -600,8 +600,8 @@ suite.addBatch({
"renders stripes": function(p) {
p(stripes(80, -80));
assert.deepEqual(testContext.buffer().filter(function(d) { return d.type === "moveTo"; }), [
{type: "moveTo", x: 480, y: 200},
{type: "moveTo", x: 1350, y: 210}
{type: "moveTo", x: 1350, y: 210},
{type: "moveTo", x: 480, y: 200}
]);
}
},