d3.geo.bounds in d3 v3

1,262 views
Skip to first unread message

Nachiket Kakatkar

unread,
May 21, 2013, 12:07:56 AM5/21/13
to d3...@googlegroups.com
Hi all,

I have recently started learning D3 and trying to get started with the geo functionality.
I followed a gist which draws the us-states layer over a Bing map layer through OpenLayers.
The version of d3 used there is 2.9.3 and it works fine.
I tried using the latest version and found that the d3.geo.bounds returned a different value than what was returned with the previous version. The value returned in the new version is lat-lon limits of +-90, +- 180, while in the older version it returns the actual bounds.
Is this expected behaviour or could be an issue in the latest version ? Or should I be using the older version ?

Thanks,
Nachiket.

Mike Bostock

unread,
May 21, 2013, 12:25:02 AM5/21/13
to d3...@googlegroups.com
I think you want to use path.bounds here, not d3.geo.bounds, since you want the projected coordinates.


See also:


Mike

Nachiket Kakatkar

unread,
May 21, 2013, 1:25:38 AM5/21/13
to d3...@googlegroups.com
Thanks for the fast reply and pointers ! :)
I am now trying my sample data with path.bounds.

Also, I was wondering what is the difference in previous and new version with respect to d3.geo.bounds since it did work before.

Thanks,
Nachiket.


--
You received this message because you are subscribed to a topic in the Google Groups "d3-js" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/d3-js/LPfhETs20JM/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to d3-js+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 



--
The Road Goes Ever On and On.............
|\| http://nachiketismo.blogspot.com/ |\|

Jason Davies

unread,
May 21, 2013, 6:48:48 AM5/21/13
to d3...@googlegroups.com
On Tue, May 21, 2013 at 10:55:38AM +0530, Nachiket Kakatkar wrote:
> Also, I was wondering what is the difference in previous and new version
> with respect to d3.geo.bounds since it did work before.

I checked that particular Gist, http://bl.ocks.org/mbertrand/5218300 -
but I couldn't see any major difference in bounds (just minor
differences due to treating segments as geodesics).

However, D3 version 3 determines the inside of a polygon as being those
points that the polygon winds around in a clockwise order. In other
words, if you have a typical polygon with a counter-clockwise winding
order, both d3.geo.path and d3.geo.bounds will treat it as covering most
of the globe.

So perhaps your polygons have the wrong winding order, which is causing
d3.geo.bounds to return ±180°, ±90°.

--
Jason Davies, http://www.jasondavies.com/

Nachiket Kakatkar

unread,
May 22, 2013, 12:37:39 AM5/22/13
to d3...@googlegroups.com
Hi,

@Jason
Yes, I understand the logic of bounds covering entire globe if they are expected to be clockwise while the input (us-states data) comes anti-clockwise. Thank you for explaining.

Thanks,
Nachiket.


--
You received this message because you are subscribed to a topic in the Google Groups "d3-js" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/d3-js/LPfhETs20JM/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to d3-js+un...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.


Nachiket Kakatkar

unread,
May 22, 2013, 3:02:51 AM5/22/13
to d3...@googlegroups.com
Hi,

an update:
I tried rendering my data - "nyc_buildings" [ comes from a local geoserver [followed this tutorial] ] - which is GeoJSON in 900913 projection.
Using the same code as the us-states example - the changes made were as follows:
1.  the data source is changed .
2. the project() function - already the coordinates are in 900913 projection, so no need to transform, just returning the viewport coordinates.
3. In the 'reset' function, calculating the bounds, so that width and height set for the svg element scales with zoom.

Now, till zoom level 9, everything works correctly. However at zoom level 10, the input to the 'project' function gets somehow distorted. The 7 digit values input suddenly drops to 3 digits, because of which the returned values become very large. When we got back to 9, it becomes correct again. The top-left is still correct, the bottom-right becomes very large.
Why might the input xy to the project() function at zoom level 10 be different from those at previous levels?
(Actually, I think there is no connection between OpenLayers zoom and d3 manipulating the data and drawing svg, but this is an observation)

pasting the modified reset and project functions :


function reset() {
//recalculate the bounds
bounds = path.bounds(collection);
var topLeft = (bounds[0]),
bottomRight = (bounds[1]);

svg.attr("width", bottomRight[0] - topLeft[0])
.attr("height", bottomRight[1] - topLeft[1])
.style("margin-left", topLeft[0] + "px")
.style("margin-top", topLeft[1] + "px");
 
g.attr("transform", "translate(" + -topLeft[0] + "," + -topLeft[1] + ")");
 
feature.attr("d", path);
}
 
function
project(x) {
var point = map.getViewPortPxFromLonLat(new OpenLayers.LonLat(x[0], x[1]));
//.transform("EPSG:4326", "EPSG:900913"));
return [point.x, point.y];
}

Thanks,
Nachiket.

Jason Davies

unread,
May 22, 2013, 9:20:50 AM5/22/13
to d3...@googlegroups.com
The problem here is that d3.geo.projection assumes all inputs are in
spherical coordinates (degrees), and by default it adaptively resamples
line segments depending on their curvature when projected.

As well as resampling, other API methods for d3.geo.projection assume
spherical coordinates, e.g. projection.rotate rotates the input
coordinates about three axes, and of course projection.clipAngle clips
input features if they cross the antimeridian (or a small circle).

If you want to use d3.geo.path to draw pre-projected features, you can
do this using path.projection(null). This specifies an identity
projection with no resampling. (Note that passing a function to
path.projection(…) will automatically resample, so the assumption there
is still spherical coordinates.)

It's also possible to turn off resampling using projection.precision(0),
but spherical coordinates are still assumed, so you may still end up
running into difficulties due to clipping.

Depending on what you're trying to do, you might prefer to project your
data into spherical coordinates to take advantage of clipping and
resampling. Otherwise, if you just want to render paths with
pre-projected data, you can use path.projection(null).

justin goodwin

unread,
Sep 26, 2013, 10:25:55 PM9/26/13
to d3...@googlegroups.com
I just discovered this same issue with some data of mine I made a year or so ago.  Everything worked fine until the new version of D3. You can see my data here:


The are three polygons, the boundary of the ski resort, and two around the base of the chair lifts.  It does look I made the polygons by going counter clockwise.  Is this a desired output of the algorithm?  Do I need to redraw the boundaries clockwise?

Justin

Mike Bostock

unread,
Sep 26, 2013, 10:48:03 PM9/26/13
to d3...@googlegroups.com
Do I need to redraw the boundaries clockwise?

Yes.

Mike

justin goodwin

unread,
Sep 26, 2013, 11:13:31 PM9/26/13
to d3...@googlegroups.com, mi...@ocks.org
:) Thank god for geojson.io, that was really easy.  Was using Google Earth last year. 
Reply all
Reply to author
Forward
0 new messages