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

d3.geo.path.bounds returning pi #2796

Closed
timiyay opened this issue Apr 14, 2016 · 3 comments
Closed

d3.geo.path.bounds returning pi #2796

timiyay opened this issue Apr 14, 2016 · 3 comments

Comments

@timiyay
Copy link

timiyay commented Apr 14, 2016

I have a GeoJSON feature, which is a simple rectangle with clockwise winding.

var bboxFeature = {
  "type": "Feature",
  "geometry": {
    "type": "Polygon",
    "coordinates": [
      [
        [
          144.96064066886902,
          -37.834369664262354
        ],
        [
          144.97222781181335,
          -37.834369664262354
        ],
        [
          144.97222781181335,
          -37.83140388052918
        ],
        [
          144.96064066886902,
          -37.83140388052918
        ],
        [
          144.96064066886902,
          -37.834369664262354
        ]
      ]
    ]
  },
  "properties": {}
};

I'm creating a D3 geo visualisation, and am attempting to zoom / scale / translate the viewport to fit this bounding box.

expected
bbox_expected

When I input this feature into d3.geo.path.bounds(), it returns a 2-dimensional array where every point equals PI.

[
  [3.141592653589793, 3.141592653589793],
  [3.141592653589793, 3.141592653589793]
]

When I attempt to render this via .append('path'), the shape is incorrect. It renders a square, with a small dot inside it (though I'm assuming the rendering bug is probably a symptom of the fact that the bounds are off). It's the orange square below.

bbox_actual

@timiyay timiyay changed the title d3.geo.path.bounds returning PI d3.geo.path.bounds returning pi Apr 14, 2016
@timiyay
Copy link
Author

timiyay commented Apr 14, 2016

Further hacking shows improved results if I reverse the order of my polygon coordinates.

The docs state

Important: the inside of a polygon is all points that the polygon winds around in a clockwise order. If your GeoJSON input has polygons in the wrong winding order, you must reverse them, say via ST_ForceRHR; you can also convert your GeoJSON to TopoJSON, and this will happen automatically.

I read this as saying the outer ring of the polygon should be clockwise, and interior rings should be anti-clockwise. Yet, the backwards is what is giving me better results. Am I taking crazy pills?

@mbostock
Copy link
Member

One common point of confusion in understanding clockwise and anticlockwise is that in spherical coordinates (latitude and longitude), positive y is up; however, in the Cartesian coordinates used by Canvas and SVG, position y is down. So, if a given sequence of coordinates form a clockwise ring in the Cartesian coordinate system used by Canvas and SVG, the same sequence forms an anticlockwise ring in spherical geographic coordinates.

I haven’t inspected your data to verify this, but I assume that’s the case here, so I’m closing the bug. I’ll reopen this bug if you tell me that’s not the case. (Though also see #1317 #2024 #2025, as there are a few cases where D3 gets the winding order wrong for very small polygons due to floating point error.)

@timiyay
Copy link
Author

timiyay commented Apr 16, 2016

@mbostock Thanks for your reply. I think you're correct that this isn't a bug, but a misunderstanding on my part.

The CW vs CCW issue is definitely non-obvious, but it should be easy to handle now you've explained it to me. I'll ensure my geographic coordinates use an exterior->CCW / interior-> CW structure, before rendering in D3.

The docs suggests using PostGIS's ST_ForceRHR to enforce winding order. In light of the fact the geographic winding order is reversed, when projecting to Cartesian coordinates, shouldn't the suggestion be to use ST_ForceLHR? Or is this projection-specific? Or am I still not fully grasping the issue?

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

No branches or pull requests

2 participants