Skip to content

Commit bef5de7

Browse files
committed
Workaround for lack of symmetry in Math.sin.
Chrome 33 included some sin/cos optimisations, which unfortunately broke our assumption that sin(-x) + sin(x) = 0 for all x. More details here: https://code.google.com/p/v8/issues/detail?id=3006 This fix uses: sin(x) = sgn(x) * sin(abs(x)) and: cos(x) = cos(abs(x)) where it matters, which fixes area calculations for degenerate polygons such as: {"type":"Polygon", "coordinates":[[[-0.0002,0.0001],[0.0002,0.0001],[-0.0002,0.0001]]]} Fixes d3#1753.
1 parent 04fa5dd commit bef5de7

4 files changed

Lines changed: 16 additions & 12 deletions

File tree

d3.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2877,7 +2877,7 @@
28772877
function nextPoint(λ, φ) {
28782878
λ *= d3_radians;
28792879
φ = φ * d3_radians / 2 + π / 4;
2880-
var = λ - λ0, cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(), v = k * Math.sin();
2880+
var = λ - λ0, sdλ = >= 0 ? 1 : -1, adλ = sdλ * , cosφ = Math.cos(φ), sinφ = Math.sin(φ), k = sinφ0 * sinφ, u = cosφ0 * cosφ + k * Math.cos(adλ), v = k * sdλ * Math.sin(adλ);
28812881
d3_geo_areaRingSum.add(Math.atan2(v, u));
28822882
λ0 = λ, cosφ0 = cosφ, sinφ0 = sinφ;
28832883
}
@@ -3339,9 +3339,9 @@
33393339
while (true) {
33403340
if (j === m) j = 0;
33413341
point = ring[j];
3342-
var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), = λ - λ0, antimeridian = abs() > π, k = sinφ0 * sinφ;
3343-
d3_geo_areaRingSum.add(Math.atan2(k * Math.sin(), cosφ0 * cosφ + k * Math.cos()));
3344-
polarAngle += antimeridian ? + ( >= 0 ? τ : -τ) : ;
3342+
var λ = point[0], φ = point[1] / 2 + π / 4, sinφ = Math.sin(φ), cosφ = Math.cos(φ), = λ - λ0, sdλ = >= 0 ? 1 : -1, adλ = sdλ * , antimeridian = adλ > π, k = sinφ0 * sinφ;
3343+
d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ)));
3344+
polarAngle += antimeridian ? + sdλ * τ : ;
33453345
if (antimeridian ^ λ0 >= meridian ^ λ >= meridian) {
33463346
var arc = d3_geo_cartesianCross(d3_geo_cartesian(point0), d3_geo_cartesian(point));
33473347
d3_geo_cartesianNormalize(arc);

d3.min.js

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

src/geo/area.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,11 +49,13 @@ function d3_geo_areaRingStart() {
4949
// previous point, current point. Uses a formula derived from Cagnoli’s
5050
// theorem. See Todhunter, Spherical Trig. (1871), Sec. 103, Eq. (2).
5151
var = λ - λ0,
52+
sdλ = >= 0 ? 1 : -1,
53+
adλ = sdλ * ,
5254
cosφ = Math.cos(φ),
5355
sinφ = Math.sin(φ),
5456
k = sinφ0 * sinφ,
55-
u = cosφ0 * cosφ + k * Math.cos(),
56-
v = k * Math.sin();
57+
u = cosφ0 * cosφ + k * Math.cos(adλ),
58+
v = k * sdλ * Math.sin(adλ);
5759
d3_geo_areaRingSum.add(Math.atan2(v, u));
5860

5961
// Advance the previous points.

src/geo/point-in-polygon.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ function d3_geo_pointInPolygon(point, polygon) {
3131
sinφ = Math.sin(φ),
3232
cosφ = Math.cos(φ),
3333
= λ - λ0,
34-
antimeridian = abs() > π,
34+
sdλ = >= 0 ? 1 : -1,
35+
adλ = sdλ * ,
36+
antimeridian = adλ > π,
3537
k = sinφ0 * sinφ;
36-
d3_geo_areaRingSum.add(Math.atan2(k * Math.sin(), cosφ0 * cosφ + k * Math.cos()));
38+
d3_geo_areaRingSum.add(Math.atan2(k * sdλ * Math.sin(adλ), cosφ0 * cosφ + k * Math.cos(adλ)));
3739

38-
polarAngle += antimeridian ? + ( >= 0 ? τ : -τ): ;
40+
polarAngle += antimeridian ? + sdλ * τ : ;
3941

4042
// Are the longitudes either side of the point's meridian, and are the
4143
// latitudes smaller than the parallel?

0 commit comments

Comments
 (0)