source: Dev/branches/jQueryUI/client/d3/src/geo/path.js @ 249

Last change on this file since 249 was 249, checked in by hendrikvanantwerpen, 13 years ago

This one's for Subversion, because it's so close...

First widget (stripped down sequencer).
Seperated client and server code in two direcotry trees.

File size: 7.6 KB
Line 
1/**
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.
7 */
8d3.geo.path = function() {
9  var pointRadius = 4.5,
10      pointCircle = d3_path_circle(pointRadius),
11      projection = d3.geo.albersUsa();
12
13  function path(d, i) {
14    if (typeof pointRadius === "function") {
15      pointCircle = d3_path_circle(pointRadius.apply(this, arguments));
16    }
17    return d3_geo_pathType(pathTypes, d);
18  }
19
20  function project(coordinates) {
21    return projection(coordinates).join(",");
22  }
23
24  var pathTypes = {
25
26    FeatureCollection: function(f) {
27      var path = [],
28          features = f.features,
29          i = -1, // features.index
30          n = features.length;
31      while (++i < n) path.push(d3_geo_pathType(pathTypes, features[i].geometry));
32      return path.join("");
33    },
34
35    Feature: function(f) {
36      return d3_geo_pathType(pathTypes, f.geometry);
37    },
38
39    Point: function(o) {
40      return "M" + project(o.coordinates) + pointCircle;
41    },
42
43    MultiPoint: function(o) {
44      var path = [],
45          coordinates = o.coordinates,
46          i = -1, // coordinates.index
47          n = coordinates.length;
48      while (++i < n) path.push("M", project(coordinates[i]), pointCircle);
49      return path.join("");
50    },
51
52    LineString: function(o) {
53      var path = ["M"],
54          coordinates = o.coordinates,
55          i = -1, // coordinates.index
56          n = coordinates.length;
57      while (++i < n) path.push(project(coordinates[i]), "L");
58      path.pop();
59      return path.join("");
60    },
61
62    MultiLineString: function(o) {
63      var path = [],
64          coordinates = o.coordinates,
65          i = -1, // coordinates.index
66          n = coordinates.length,
67          subcoordinates, // coordinates[i]
68          j, // subcoordinates.index
69          m; // subcoordinates.length
70      while (++i < n) {
71        subcoordinates = coordinates[i];
72        j = -1;
73        m = subcoordinates.length;
74        path.push("M");
75        while (++j < m) path.push(project(subcoordinates[j]), "L");
76        path.pop();
77      }
78      return path.join("");
79    },
80
81    Polygon: function(o) {
82      var path = [],
83          coordinates = o.coordinates,
84          i = -1, // coordinates.index
85          n = coordinates.length,
86          subcoordinates, // coordinates[i]
87          j, // subcoordinates.index
88          m; // subcoordinates.length
89      while (++i < n) {
90        subcoordinates = coordinates[i];
91        j = -1;
92        m = subcoordinates.length;
93        path.push("M");
94        while (++j < m) path.push(project(subcoordinates[j]), "L");
95        path[path.length - 1] = "Z";
96      }
97      return path.join("");
98    },
99
100    MultiPolygon: function(o) {
101      var path = [],
102          coordinates = o.coordinates,
103          i = -1, // coordinates index
104          n = coordinates.length,
105          subcoordinates, // coordinates[i]
106          j, // subcoordinates index
107          m, // subcoordinates.length
108          subsubcoordinates, // subcoordinates[j]
109          k, // subsubcoordinates index
110          p; // subsubcoordinates.length
111      while (++i < n) {
112        subcoordinates = coordinates[i];
113        j = -1;
114        m = subcoordinates.length;
115        while (++j < m) {
116          subsubcoordinates = subcoordinates[j];
117          k = -1;
118          p = subsubcoordinates.length - 1;
119          path.push("M");
120          while (++k < p) path.push(project(subsubcoordinates[k]), "L");
121          path[path.length - 1] = "Z";
122        }
123      }
124      return path.join("");
125    },
126
127    GeometryCollection: function(o) {
128      var path = [],
129          geometries = o.geometries,
130          i = -1, // geometries index
131          n = geometries.length;
132      while (++i < n) path.push(d3_geo_pathType(pathTypes, geometries[i]));
133      return path.join("");
134    }
135
136  };
137
138  var areaTypes = {
139
140    FeatureCollection: function(f) {
141      var area = 0,
142          features = f.features,
143          i = -1, // features.index
144          n = features.length;
145      while (++i < n) area += d3_geo_pathType(areaTypes, features[i]);
146      return area;
147    },
148
149    Feature: function(f) {
150      return d3_geo_pathType(areaTypes, f.geometry);
151    },
152
153    Point: d3_geo_pathZero,
154    MultiPoint: d3_geo_pathZero,
155    LineString: d3_geo_pathZero,
156    MultiLineString: d3_geo_pathZero,
157
158    Polygon: function(o) {
159      return polygonArea(o.coordinates);
160    },
161
162    MultiPolygon: function(o) {
163      var sum = 0,
164          coordinates = o.coordinates,
165          i = -1, // coordinates index
166          n = coordinates.length;
167      while (++i < n) sum += polygonArea(coordinates[i]);
168      return sum;
169    },
170
171    GeometryCollection: function(o) {
172      var sum = 0,
173          geometries = o.geometries,
174          i = -1, // geometries index
175          n = geometries.length;
176      while (++i < n) sum += d3_geo_pathType(areaTypes, geometries[i]);
177      return sum;
178    }
179
180  };
181
182  function polygonArea(coordinates) {
183    var sum = area(coordinates[0]), // exterior ring
184        i = 0, // coordinates.index
185        n = coordinates.length;
186    while (++i < n) sum -= area(coordinates[i]); // holes
187    return sum;
188  }
189
190  function polygonCentroid(coordinates) {
191    var polygon = d3.geom.polygon(coordinates[0].map(projection)), // exterior ring
192        centroid = polygon.centroid(1),
193        x = centroid[0],
194        y = centroid[1],
195        z = Math.abs(polygon.area()),
196        i = 0, // coordinates index
197        n = coordinates.length;
198    while (++i < n) {
199      polygon = d3.geom.polygon(coordinates[i].map(projection)); // holes
200      centroid = polygon.centroid(1);
201      x -= centroid[0];
202      y -= centroid[1];
203      z -= Math.abs(polygon.area());
204    }
205    return [x, y, 6 * z]; // weighted centroid
206  }
207
208  var centroidTypes = {
209
210    // TODO FeatureCollection
211    // TODO Point
212    // TODO MultiPoint
213    // TODO LineString
214    // TODO MultiLineString
215    // TODO GeometryCollection
216
217    Feature: function(f) {
218      return d3_geo_pathType(centroidTypes, f.geometry);
219    },
220
221    Polygon: function(o) {
222      var centroid = polygonCentroid(o.coordinates);
223      return [centroid[0] / centroid[2], centroid[1] / centroid[2]];
224    },
225
226    MultiPolygon: function(o) {
227      var area = 0,
228          coordinates = o.coordinates,
229          centroid,
230          x = 0,
231          y = 0,
232          z = 0,
233          i = -1, // coordinates index
234          n = coordinates.length;
235      while (++i < n) {
236        centroid = polygonCentroid(coordinates[i]);
237        x += centroid[0];
238        y += centroid[1];
239        z += centroid[2];
240      }
241      return [x / z, y / z];
242    }
243
244  };
245
246
247  function area(coordinates) {
248    return Math.abs(d3.geom.polygon(coordinates.map(projection)).area());
249  }
250
251  path.projection = function(x) {
252    projection = x;
253    return path;
254  };
255
256  path.area = function(d) {
257    return d3_geo_pathType(areaTypes, d);
258  };
259
260  path.centroid = function(d) {
261    return d3_geo_pathType(centroidTypes, d);
262  };
263
264  path.pointRadius = function(x) {
265    if (typeof x === "function") pointRadius = x;
266    else {
267      pointRadius = +x;
268      pointCircle = d3_path_circle(pointRadius);
269    }
270    return path;
271  };
272
273  return path;
274};
275
276function d3_path_circle(radius) {
277  return "m0," + radius
278      + "a" + radius + "," + radius + " 0 1,1 0," + (-2 * radius)
279      + "a" + radius + "," + radius + " 0 1,1 0," + (+2 * radius)
280      + "z";
281}
282
283function d3_geo_pathZero() {
284  return 0;
285}
286
287function d3_geo_pathType(types, o) {
288  return o && o.type in types ? types[o.type](o) : "";
289}
Note: See TracBrowser for help on using the repository browser.