0

I was wondering whether there is a D3-API call that translates a d3.geo.bounds() array to a path.bounds pixel array given a width and height of the map?

I was unable to find such a call in the API documentation. I know that there are projections that should to the trick, but I failed in getting to the actual pixel bound from a geo bound.

Also, is there an API implementation of computing the lat/long centroid of a series of features?

I appreciate any help!

Example

Assume the user wants to zoom Germany and Poland to fullscreen. My computed lat-long boundary is:

lat:47.27148371456806 long: 5.850585058505857
(1321.6041604160416,246.58117844670664)
lat:55.06843452896922 long: 24.140414041404142
(1451.6651665166517,157.87336991900156) 

Checking with google-maps, the lat-long coordinates are correct. However, the computed pixel values (using the approach from https://stackoverflow.com/a/14457180/974815) seem weird to me. The screen resolution is 2560x1258.

I want to translate the lat-long boundaries to pixel boundaries in order to compute the offset for the mercator projection:

var offset = [
               this.width - (bounds[0][0] + bounds[1][0])/2,
               this.height - (bounds[0][1] + bounds[1][1])/2
             ];   

return d3.geo.path().projection(
                                 d3.geo.mercator()
                                   .center(this.__computeCentroid(features))
                                   .scale(scale)                                
                                   .translate(offset)
                               );

Best, Sebastian

Community
  • 1
  • 1
Sebastian B.
  • 287
  • 4
  • 19

1 Answers1

0

The geographic coordinates of features are translated into pixel (projection) coordinates using one of the projections available. You can either use the projection to translate the geographic bounds into projected bounds, or use path.bounds() directly to get that information. That is, instead of passing the feature to d3.geo.bounds(), you pass it to the .bounds() method of the d3.geo.path() that uses your projection.

There is no function to compute the centroid of a series of features. You can either combine the features into one (preferably using a GIS program) and get the centroid of that, or get the centroids of all the features and then get the centroid of the centroids by averaging the coordinates.

Lars Kotthoff
  • 107,425
  • 16
  • 204
  • 204
  • Thanks for the response! I knew about path.bounds(), but the issue I have is that for the reasons of not loosing precision, I had to compute the unified bound of multiple features, that is I have the geo-bounds for, lets say two features, and now I need to translate that bound to pixel bounds in order to compute the offset for the mercator projection to fit the bounds the screen resolution! Does this mean I have to translate the specific (combined) bound by hand? – Sebastian B. Mar 30 '14 at 12:56
  • You could either do that or use the projected bounds. As in the end you're projecting anyway, you shouldn't lose precision through that -- maybe a pixel here or there, but that doesn't matter unless your screen is really small. – Lars Kotthoff Mar 30 '14 at 13:08
  • For example, if you want to fit a collection of features only known at runtime to any screen resolution, you cannot really work with the projected bounds, because for the initial projection you have to take a first guess with some initial scale. Certainly there are islands in the world map smaller than the default scale and therefore projected bounds would return infinity (as a single pixel might be too less to display an island which is smaller than to fit a scale of 150). Guess I have to do it by hand. – Sebastian B. Mar 30 '14 at 13:14
  • Ok, I see your point. In that case, just use the projection to project the computed boundaries. – Lars Kotthoff Mar 30 '14 at 13:26
  • Yes and I seem to fail how to do that. Let's say I have two boundary points with lat long coordinates. I need to translate those to pixel coordinates in a screen with height y_h and width x_w. Do I have to do it as describe here: http://stackoverflow.com/a/14457180/974815 (I have checked, my computed lat long boundaries are correct, but the pixel boundaries using the formula from the links are weird)? Is there a D3-way? – Sebastian B. Mar 30 '14 at 13:29
  • Just use the [`projection()` function](https://github.com/mbostock/d3/wiki/Geo-Projections#_projection) on the bounds, e.g. `d3.geo.mercator()(bounds[0])`. – Lars Kotthoff Mar 30 '14 at 13:46