2
* Returns a function that, given a GeoJSON object (e.g., a feature), returns
3
* the corresponding SVG path. The function can be customized by overriding the
4
* projection. Point features are mapped to circles with a default radius of
5
* 4.5px; the radius can be specified either as a constant or a function that
6
* is evaluated per object.
8
d3.geo.path = function() {
10
pointCircle = d3_path_circle(pointRadius),
11
projection = d3.geo.albersUsa(),
15
if (typeof pointRadius === "function") pointCircle = d3_path_circle(pointRadius.apply(this, arguments));
17
var result = buffer.length ? buffer.join("") : null;
22
function project(coordinates) {
23
return projection(coordinates).join(",");
26
var pathType = d3_geo_type({
28
FeatureCollection: function(o) {
29
var features = o.features,
30
i = -1, // features.index
32
while (++i < n) buffer.push(pathType(features[i].geometry));
35
Feature: function(o) {
40
buffer.push("M", project(o.coordinates), pointCircle);
43
MultiPoint: function(o) {
44
var coordinates = o.coordinates,
45
i = -1, // coordinates.index
46
n = coordinates.length;
47
while (++i < n) buffer.push("M", project(coordinates[i]), pointCircle);
50
LineString: function(o) {
51
var coordinates = o.coordinates,
52
i = -1, // coordinates.index
53
n = coordinates.length;
55
while (++i < n) buffer.push(project(coordinates[i]), "L");
59
MultiLineString: function(o) {
60
var coordinates = o.coordinates,
61
i = -1, // coordinates.index
62
n = coordinates.length,
63
subcoordinates, // coordinates[i]
64
j, // subcoordinates.index
65
m; // subcoordinates.length
67
subcoordinates = coordinates[i];
69
m = subcoordinates.length;
71
while (++j < m) buffer.push(project(subcoordinates[j]), "L");
76
Polygon: function(o) {
77
var coordinates = o.coordinates,
78
i = -1, // coordinates.index
79
n = coordinates.length,
80
subcoordinates, // coordinates[i]
81
j, // subcoordinates.index
82
m; // subcoordinates.length
84
subcoordinates = coordinates[i];
86
if ((m = subcoordinates.length - 1) > 0) {
88
while (++j < m) buffer.push(project(subcoordinates[j]), "L");
89
buffer[buffer.length - 1] = "Z";
94
MultiPolygon: function(o) {
95
var coordinates = o.coordinates,
96
i = -1, // coordinates index
97
n = coordinates.length,
98
subcoordinates, // coordinates[i]
99
j, // subcoordinates index
100
m, // subcoordinates.length
101
subsubcoordinates, // subcoordinates[j]
102
k, // subsubcoordinates index
103
p; // subsubcoordinates.length
105
subcoordinates = coordinates[i];
107
m = subcoordinates.length;
109
subsubcoordinates = subcoordinates[j];
111
if ((p = subsubcoordinates.length - 1) > 0) {
113
while (++k < p) buffer.push(project(subsubcoordinates[k]), "L");
114
buffer[buffer.length - 1] = "Z";
120
GeometryCollection: function(o) {
121
var geometries = o.geometries,
122
i = -1, // geometries index
123
n = geometries.length;
124
while (++i < n) buffer.push(pathType(geometries[i]));
129
var areaType = path.area = d3_geo_type({
131
FeatureCollection: function(o) {
133
features = o.features,
134
i = -1, // features.index
136
while (++i < n) area += areaType(features[i]);
140
Feature: function(o) {
141
return areaType(o.geometry);
144
Polygon: function(o) {
145
return polygonArea(o.coordinates);
148
MultiPolygon: function(o) {
150
coordinates = o.coordinates,
151
i = -1, // coordinates index
152
n = coordinates.length;
153
while (++i < n) sum += polygonArea(coordinates[i]);
157
GeometryCollection: function(o) {
159
geometries = o.geometries,
160
i = -1, // geometries index
161
n = geometries.length;
162
while (++i < n) sum += areaType(geometries[i]);
168
function polygonArea(coordinates) {
169
var sum = area(coordinates[0]), // exterior ring
170
i = 0, // coordinates.index
171
n = coordinates.length;
172
while (++i < n) sum -= area(coordinates[i]); // holes
176
function polygonCentroid(coordinates) {
177
var polygon = d3.geom.polygon(coordinates[0].map(projection)), // exterior ring
178
area = polygon.area(),
179
centroid = polygon.centroid(area < 0 ? (area *= -1, 1) : -1),
183
i = 0, // coordinates index
184
n = coordinates.length;
186
polygon = d3.geom.polygon(coordinates[i].map(projection)); // holes
187
area = polygon.area();
188
centroid = polygon.centroid(area < 0 ? (area *= -1, 1) : -1);
193
return [x, y, 6 * z]; // weighted centroid
196
var centroidType = path.centroid = d3_geo_type({
198
// TODO FeatureCollection
202
// TODO MultiLineString
203
// TODO GeometryCollection
205
Feature: function(o) {
206
return centroidType(o.geometry);
209
Polygon: function(o) {
210
var centroid = polygonCentroid(o.coordinates);
211
return [centroid[0] / centroid[2], centroid[1] / centroid[2]];
214
MultiPolygon: function(o) {
216
coordinates = o.coordinates,
221
i = -1, // coordinates index
222
n = coordinates.length;
224
centroid = polygonCentroid(coordinates[i]);
229
return [x / z, y / z];
234
function area(coordinates) {
235
return Math.abs(d3.geom.polygon(coordinates.map(projection)).area());
238
path.projection = function(x) {
243
path.pointRadius = function(x) {
244
if (typeof x === "function") pointRadius = x;
247
pointCircle = d3_path_circle(pointRadius);
255
function d3_path_circle(radius) {
256
return "m0," + radius
257
+ "a" + radius + "," + radius + " 0 1,1 0," + (-2 * radius)
258
+ "a" + radius + "," + radius + " 0 1,1 0," + (+2 * radius)