Skip to content

Commit d33907b

Browse files
committed
Slightly cleaner Sphere implementation.
1 parent 050b1c3 commit d33907b

6 files changed

Lines changed: 107 additions & 83 deletions

File tree

d3.js

Lines changed: 49 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -5367,7 +5367,7 @@
53675367
this.polygon(polygon.coordinates);
53685368
},
53695369
Sphere: function() {
5370-
this.polygon(null);
5370+
this.sphere();
53715371
},
53725372
object: function(object) {
53735373
return d3_geo_typeObjects.hasOwnProperty(object.type) ? this[object.type](object) : this.geometry(object);
@@ -5383,7 +5383,8 @@
53835383
polygon: function(coordinates) {
53845384
var i = -1, n = coordinates.length;
53855385
while (++i < n) this.line(coordinates[i]);
5386-
}
5386+
},
5387+
sphere: d3_noop
53875388
};
53885389
var d3_geo_typeGeometries = {
53895390
LineString: 1,
@@ -5544,6 +5545,9 @@
55445545
},
55455546
polygon: function(polygon, context) {
55465547
d3_geo_circleClipPolygon(polygon, context, clipLine, interpolate);
5548+
},
5549+
sphere: function(context) {
5550+
d3_geo_projectionSphere(context, interpolate);
55475551
}
55485552
};
55495553
function visible(point) {
@@ -5562,7 +5566,7 @@
55625566
v = visible(point1);
55635567
if (v !== v0) {
55645568
point2 = intersect(point0, point1);
5565-
if (pointsEqual(point0, point2) || pointsEqual(point1, point2)) {
5569+
if (d3_geo_circlePointsEqual(point0, point2) || d3_geo_circlePointsEqual(point1, point2)) {
55665570
point1[0] += ε;
55675571
point1[1] += ε;
55685572
v = visible(point1);
@@ -5587,7 +5591,7 @@
55875591
x0 = x;
55885592
y0 = y;
55895593
}
5590-
if (v && !pointsEqual(point0, point1)) context.lineTo(point1[0], point1[1]);
5594+
if (v && !d3_geo_circlePointsEqual(point0, point1)) context.lineTo(point1[0], point1[1]);
55915595
point0 = point1;
55925596
}
55935597
return [ clean && area * .5, v00 && v ];
@@ -5622,38 +5626,28 @@
56225626
}
56235627
function d3_geo_circleClipPolygon(coordinates, context, clipLine, interpolate) {
56245628
var subject = [], clip = [], segments = [], buffer = d3_geo_circleBufferSegments(clipLine), draw = [], visibleArea = 0, invisibleArea = 0, invisible = false;
5625-
if (coordinates) {
5626-
coordinates.forEach(function(ring) {
5627-
var x = buffer(ring, context), ringSegments = x[1], segment, n = ringSegments.length;
5628-
if (!n) {
5629-
invisible = true;
5630-
invisibleArea += x[0][0];
5631-
return;
5632-
}
5633-
if (x[0][0] !== false) {
5634-
visibleArea += x[0][0];
5635-
draw.push(segment = ringSegments[0]);
5636-
var point = segment[0], n = segment.length - 1, i = 0;
5637-
context.moveTo(point[0], point[1]);
5638-
while (++i < n) context.lineTo((point = segment[i])[0], point[1]);
5639-
context.closePath();
5640-
return;
5641-
}
5642-
if (n > 1 && x[0][1]) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
5643-
segments = segments.concat(ringSegments.filter(d3_geo_circleSegmentLength1));
5644-
});
5645-
} else {
5646-
visibleArea = -4 * π;
5647-
}
5629+
coordinates.forEach(function(ring) {
5630+
var x = buffer(ring, context), ringSegments = x[1], segment, n = ringSegments.length;
5631+
if (!n) {
5632+
invisible = true;
5633+
invisibleArea += x[0][0];
5634+
return;
5635+
}
5636+
if (x[0][0] !== false) {
5637+
visibleArea += x[0][0];
5638+
draw.push(segment = ringSegments[0]);
5639+
var point = segment[0], n = segment.length - 1, i = 0;
5640+
context.moveTo(point[0], point[1]);
5641+
while (++i < n) context.lineTo((point = segment[i])[0], point[1]);
5642+
context.closePath();
5643+
return;
5644+
}
5645+
if (n > 1 && x[0][1]) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
5646+
segments = segments.concat(ringSegments.filter(d3_geo_circleSegmentLength1));
5647+
});
56485648
if (!segments.length) {
56495649
if (visibleArea < 0 || invisible && invisibleArea < 0) {
5650-
var moved = false;
5651-
interpolate(null, null, 1, {
5652-
lineTo: function(x, y) {
5653-
(moved ? context.lineTo : (moved = true, context.moveTo))(x, y);
5654-
}
5655-
});
5656-
context.closePath();
5650+
d3_geo_projectionSphere(context, interpolate);
56575651
}
56585652
}
56595653
segments.forEach(function(segment) {
@@ -5787,7 +5781,7 @@
57875781
}, true), segments ];
57885782
};
57895783
}
5790-
function pointsEqual(a, b) {
5784+
function d3_geo_circlePointsEqual(a, b) {
57915785
return Math.abs(a[0] - b[0]) < ε && Math.abs(a[1] - b[1]) < ε;
57925786
}
57935787
function d3_geo_circleSegmentLength1(segment) {
@@ -5993,6 +5987,9 @@
59935987
},
59945988
point: function(coordinates) {
59955989
projection.point(coordinates, context);
5990+
},
5991+
sphere: function() {
5992+
projection.sphere(context);
59965993
}
59975994
});
59985995
var areaType = d3_geo_type({
@@ -6150,6 +6147,11 @@
61506147
clip.polygon(coordinates, resample);
61516148
context = null;
61526149
};
6150+
projection.sphere = function(c) {
6151+
context = c;
6152+
clip.sphere(resample);
6153+
context = null;
6154+
};
61536155
projection.clipAngle = function(_) {
61546156
if (!arguments.length) return clipAngle;
61556157
clip = _ == null ? (clipAngle = _, d3_geo_projectionCutAntemeridian(rotatePoint)) : d3_geo_circleClip(clipAngle = +_, rotatePoint);
@@ -6291,6 +6293,9 @@
62916293
},
62926294
polygon: function(polygon, context) {
62936295
d3_geo_circleClipPolygon(polygon, context, clip.line, d3_geo_antemeridianInterpolate);
6296+
},
6297+
sphere: function(context) {
6298+
d3_geo_projectionSphere(context, d3_geo_antemeridianInterpolate);
62946299
}
62956300
};
62966301
return clip;
@@ -6317,6 +6322,15 @@
63176322
context.lineTo(to[0], to[1]);
63186323
}
63196324
}
6325+
function d3_geo_projectionSphere(context, interpolate) {
6326+
var moved = false;
6327+
interpolate(null, null, 1, {
6328+
lineTo: function(x, y) {
6329+
(moved ? context.lineTo : (moved = true, context.moveTo))(x, y);
6330+
}
6331+
});
6332+
context.closePath();
6333+
}
63206334
function d3_geo_rotation(δλ, δφ, δγ) {
63216335
return δλ ? δφ || δγ ? d3_geo_compose(d3_geo_rotationλ(δλ), d3_geo_rotationφγ(δφ, δγ)) : d3_geo_rotationλ(δλ) : δφ || δγ ? d3_geo_rotationφγ(δφ, δγ) : d3_geo_identityRotation;
63226336
}

d3.min.js

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

src/geo/circle.js

Lines changed: 34 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,9 @@ function d3_geo_circleClip(degrees, rotate) {
6060
},
6161
polygon: function(polygon, context) {
6262
d3_geo_circleClipPolygon(polygon, context, clipLine, interpolate);
63+
},
64+
sphere: function(context) {
65+
d3_geo_projectionSphere(context, interpolate);
6366
}
6467
};
6568

@@ -95,7 +98,7 @@ function d3_geo_circleClip(degrees, rotate) {
9598
// handle degeneracies
9699
if (v !== v0) {
97100
point2 = intersect(point0, point1);
98-
if (pointsEqual(point0, point2) || pointsEqual(point1, point2)) {
101+
if (d3_geo_circlePointsEqual(point0, point2) || d3_geo_circlePointsEqual(point1, point2)) {
99102
point1[0] += ε;
100103
point1[1] += ε;
101104
v = visible(point1);
@@ -122,7 +125,7 @@ function d3_geo_circleClip(degrees, rotate) {
122125
x0 = x;
123126
y0 = y;
124127
}
125-
if (v && !pointsEqual(point0, point1)) context.lineTo(point1[0], point1[1]);
128+
if (v && !d3_geo_circlePointsEqual(point0, point1)) context.lineTo(point1[0], point1[1]);
126129
point0 = point1;
127130
}
128131
return [
@@ -198,50 +201,40 @@ function d3_geo_circleClipPolygon(coordinates, context, clipLine, interpolate) {
198201
invisibleArea = 0,
199202
invisible = false;
200203

201-
if (coordinates) {
202-
coordinates.forEach(function(ring) {
203-
var x = buffer(ring, context),
204-
ringSegments = x[1],
205-
segment,
206-
n = ringSegments.length;
207-
208-
if (!n) {
209-
invisible = true;
210-
invisibleArea += x[0][0];
211-
return;
212-
}
204+
coordinates.forEach(function(ring) {
205+
var x = buffer(ring, context),
206+
ringSegments = x[1],
207+
segment,
208+
n = ringSegments.length;
213209

214-
// No intersections.
215-
if (x[0][0] !== false) {
216-
visibleArea += x[0][0];
217-
draw.push(segment = ringSegments[0]);
218-
var point = segment[0],
219-
n = segment.length - 1,
220-
i = 0;
221-
context.moveTo(point[0], point[1]);
222-
while (++i < n) context.lineTo((point = segment[i])[0], point[1]);
223-
context.closePath();
224-
return;
225-
}
210+
if (!n) {
211+
invisible = true;
212+
invisibleArea += x[0][0];
213+
return;
214+
}
215+
216+
// No intersections.
217+
if (x[0][0] !== false) {
218+
visibleArea += x[0][0];
219+
draw.push(segment = ringSegments[0]);
220+
var point = segment[0],
221+
n = segment.length - 1,
222+
i = 0;
223+
context.moveTo(point[0], point[1]);
224+
while (++i < n) context.lineTo((point = segment[i])[0], point[1]);
225+
context.closePath();
226+
return;
227+
}
226228

227-
// Rejoin connected segments.
228-
if (n > 1 && x[0][1]) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
229+
// Rejoin connected segments.
230+
if (n > 1 && x[0][1]) ringSegments.push(ringSegments.pop().concat(ringSegments.shift()));
229231

230-
segments = segments.concat(ringSegments.filter(d3_geo_circleSegmentLength1));
231-
});
232-
} else {
233-
visibleArea = -4 * π; // whole sphere
234-
}
232+
segments = segments.concat(ringSegments.filter(d3_geo_circleSegmentLength1));
233+
});
235234

236235
if (!segments.length) {
237236
if (visibleArea < 0 || invisible && invisibleArea < 0) {
238-
var moved = false;
239-
interpolate(null, null, 1, {
240-
lineTo: function(x, y) {
241-
(moved ? context.lineTo : (moved = true, context.moveTo))(x, y);
242-
}
243-
});
244-
context.closePath();
237+
d3_geo_projectionSphere(context, interpolate);
245238
}
246239
}
247240
segments.forEach(function(segment) {
@@ -383,7 +376,7 @@ function d3_geo_circleBufferSegments(f) {
383376
};
384377
}
385378

386-
function pointsEqual(a, b) {
379+
function d3_geo_circlePointsEqual(a, b) {
387380
return Math.abs(a[0] - b[0]) < ε && Math.abs(a[1] - b[1]) < ε;
388381
}
389382

src/geo/path.js

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ d3.geo.path = function() {
2929
var pathType = d3_geo_type({
3030
line: function(coordinates) { projection.line(coordinates, context); },
3131
polygon: function(coordinates) { projection.polygon(coordinates, context); },
32-
point: function(coordinates) { projection.point(coordinates, context); }
32+
point: function(coordinates) { projection.point(coordinates, context); },
33+
sphere: function() { projection.sphere(context); }
3334
});
3435

3536
var areaType = d3_geo_type({

src/geo/projection.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ function d3_geo_projectionMutator(projectAt) {
3838
projection.point = function(coordinates, c) { context = c; clip.point(coordinates, resample); context = null; };
3939
projection.line = function(coordinates, c) { context = c; clip.line(coordinates, resample); context = null; };
4040
projection.polygon = function(coordinates, c) { context = c; clip.polygon(coordinates, resample); context = null; };
41+
projection.sphere = function( c) { context = c; clip.sphere( resample); context = null; };
4142

4243
projection.clipAngle = function(_) {
4344
if (!arguments.length) return clipAngle;
@@ -250,6 +251,9 @@ function d3_geo_projectionCutAntemeridian(rotatePoint) {
250251
},
251252
polygon: function(polygon, context) {
252253
d3_geo_circleClipPolygon(polygon, context, clip.line, d3_geo_antemeridianInterpolate);
254+
},
255+
sphere: function(context) {
256+
d3_geo_projectionSphere(context, d3_geo_antemeridianInterpolate);
253257
}
254258
};
255259
return clip;
@@ -277,3 +281,13 @@ function d3_geo_antemeridianInterpolate(from, to, direction, context) {
277281
context.lineTo(to[0], to[1]);
278282
}
279283
}
284+
285+
function d3_geo_projectionSphere(context, interpolate) {
286+
var moved = false;
287+
interpolate(null, null, 1, {
288+
lineTo: function(x, y) {
289+
(moved ? context.lineTo : (moved = true, context.moveTo))(x, y);
290+
}
291+
});
292+
context.closePath();
293+
}

src/geo/type.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ var d3_geo_typeDefaults = {
5151
},
5252

5353
Sphere: function() {
54-
this.polygon(null);
54+
this.sphere();
5555
},
5656

5757
// dispatch for any GeoJSON object type
@@ -81,7 +81,9 @@ var d3_geo_typeDefaults = {
8181
polygon: function(coordinates) {
8282
var i = -1, n = coordinates.length;
8383
while (++i < n) this.line(coordinates[i]);
84-
}
84+
},
85+
86+
sphere: d3_noop
8587
};
8688

8789
var d3_geo_typeGeometries = {

0 commit comments

Comments
 (0)