Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Graticule errors under gnomonic projection. #54

Closed
jheer opened this issue Aug 12, 2016 · 4 comments · Fixed by #91
Closed

Graticule errors under gnomonic projection. #54

jheer opened this issue Aug 12, 2016 · 4 comments · Fixed by #91

Comments

@jheer
Copy link

jheer commented Aug 12, 2016

I've encountered some buggy behavior using the gnomonic projection with customized graticule steps. In some cases, there is incorrect line clipping. In others, an error is thrown. The issues arose when using a custom graticule step of [15, 15]. Removing the custom step or adjusting the projection clipAngle can make the issues to go away.

Below is an example that replicates the errors in d3 v4.2.1 and Chrome 51.0.2704.103 (Mac OS). The example assumes world-50m.json is on the relative path. Also, see comments below for more.

<!DOCTYPE html>
<meta charset="utf-8">
<style>

.graticule {
  fill: none;
  stroke: #777;
  stroke-width: .5px;
  stroke-opacity: .5;
}

.land {
  fill: #222;
}

.boundary {
  fill: none;
  stroke: #fff;
  stroke-width: .5px;
}

</style>
<body>
<script src="http://d3js.org/d3.v4.min.js"></script>
<script src="http://d3js.org/topojson.v1.min.js"></script>
<script>

var width = 960,
    height = 600;

var projection = d3.geoGnomonic()
    .scale(150)
    .translate([width / 2, height / 2])
    .rotate([-105, 0, 0]); // comment this line: no error, but bad line crossing
    // .clipAngle(90 - 1e-3); // uncomment this line, errors do not occur

var path = d3.geoPath()
    .projection(projection);

var graticule = d3.geoGraticule()
  .step([15, 15]); // comment this line, errors do not occur

var svg = d3.select("body").append("svg")
    .attr("width", width)
    .attr("height", height);

svg.append("path")
    .datum(graticule)
    .attr("class", "graticule")
    .attr("d", path);

d3.json("world-50m.json", function(error, world) {
  if (error) throw error;

  svg.insert("path", ".graticule")
      .datum(topojson.feature(world, world.objects.land))
      .attr("class", "land")
      .attr("d", path);

  svg.insert("path", ".graticule")
      .datum(topojson.mesh(world, world.objects.countries, function(a, b) { return a !== b; }))
      .attr("class", "boundary")
      .attr("d", path);
});

</script>
@mbostock
Copy link
Member

Yep. This is almost certainly a bug in clipping because the points on the graticule exactly fall on the clip circle. It goes away if you change the clip angle to 60.0001°, for example.

FYI, I probably won’t be able to fix this bug and #55 anytime soon, since it would require a much deeper understanding of Jason’s geographic clipping code than I currently have.

@Fil
Copy link
Member

Fil commented Aug 12, 2016

In intersect(a,b,two) there is the possibility to return;, which makes point2 = undefined on lines 15090 and 15102 of the current d3.v4 build and throws the error.

Either intersectshould never return undefined, or we must check that point2 is defined in those lines. With both solutions the graticule does display correctly.

Note that, when I log the value of t2 = w * w - uu * (cartesianDot(A, A) - 1); when the bug happens, it is ~ - 1e-16. Adding some epsilon to this determinant computation when it is negative seems like a possible solution:

- if (t2 < 0) return;
+ if (t2 < 0 && (t2 += epsilon) && t2 < 0) return;

@Fil
Copy link
Member

Fil commented Aug 13, 2016

My understanding of the code is that this test on t2 < 0 is here only to avoid throwing an error on the next sqrt because of a rounding error. There is no case where this is "really" negative.

The test can be replaced instead by:
var t = sqrt$1(Math.max(t2, 0));

The test was introduced in d3/d3@d93f45e .

Side note: there is an utf8 in one of the comments.

@Fil
Copy link
Member

Fil commented Mar 13, 2017

Amazingly I couldn't reproduce this bug anymore on any newer browser (Firefox, Safari Chrome). However, launching an old copy of "Brave.app" that hadn't updated, the bug was reproducible. Fixed by #91

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Development

Successfully merging a pull request may close this issue.

3 participants