pocketfullofcheese
pocketfullofcheese

Reputation: 8837

d3.js: why is d3.geo.path() giving NaN?

I am trying to do some online mapping with d3, but running into a problem when I try to plot a line between two points.

I have calculated the centroid of two polygons (source and target)

In the code:

var projection = d3.geo.mercator()
    .scale(width)
    .translate([0, 0]);

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

From the JS console:

> path({type: "LineString",
      coordinates: [path.centroid(source_country), path.centroid(target_country)]});

"M277.05056877663407,121.67976219138909L-694.1792414247936,NaN"

Yet, the centroid calculations seem to be working fine (plotting those points shows them on the map)

> [path.centroid(source_country), path.centroid(target_country)]

[
Array[2]
0: 103.89396329123777
1: -41.453727169465765
length: 2
__proto__: Array[0]
, 
Array[2]
0: -260.3172155342976
1: -245.57309459883245
length: 2
__proto__: Array[0]

Any ideas why that NaN is appearing at the end of the path generated for my LineString?

Upvotes: 2

Views: 2900

Answers (2)

Siwei
Siwei

Reputation: 21569

OK just now I met the same error,

for anyone who meet NAN problem:

  1. the format of coordinate must be correct. e.g. for type Polygon, the coordinate must have a 3-level nested array. e.g. [[[1,2],[2,3]]]

  2. coordinates must be float/integer, but not string (e.g. 1 correct, "1" error )

  3. you can inspect the detailed content of the error result, e.g. M...L...Z... and find out where the error is.

Upvotes: 0

nrabinowitz
nrabinowitz

Reputation: 55678

The problem here is that you're projecting the lat/lon coordinates twice. The path() operator expects to take lat/lon and project to pixels; the path.centroid() method also expects a lat/lon geometry, and also produces a pixel-based projection.

So when you call path on [path.centroid(...), path.centroid(...)], you're trying to project already-projected coordinates. You get at NaN because the y-position of the pixel coordinates, -245, is out of bounds for a longitude value.

The easiest way to fix this is probably to use d3.svg.line to create the centroid-centroid path. I haven't tested this, but I think it would look like:

var line = d3.svg.line();
line([path.centroid(source_country), path.centroid(target_country)]);

Upvotes: 4

Related Questions