~bcsaller/juju-gui/update-reductions

« back to all changes in this revision

Viewing changes to lib/d3/src/geo/path.js

  • Committer: kapil.foss at gmail
  • Date: 2012-07-13 18:45:59 UTC
  • Revision ID: kapil.foss@gmail.com-20120713184559-2xl7be17egsrz0c9
reshape

Show diffs side-by-side

added added

removed removed

Lines of Context:
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
 
 */
8
 
d3.geo.path = function() {
9
 
  var pointRadius = 4.5,
10
 
      pointCircle = d3_path_circle(pointRadius),
11
 
      projection = d3.geo.albersUsa(),
12
 
      buffer = [];
13
 
 
14
 
  function path(d, i) {
15
 
    if (typeof pointRadius === "function") pointCircle = d3_path_circle(pointRadius.apply(this, arguments));
16
 
    pathType(d);
17
 
    var result = buffer.length ? buffer.join("") : null;
18
 
    buffer = [];
19
 
    return result;
20
 
  }
21
 
 
22
 
  function project(coordinates) {
23
 
    return projection(coordinates).join(",");
24
 
  }
25
 
 
26
 
  var pathType = d3_geo_type({
27
 
 
28
 
    FeatureCollection: function(o) {
29
 
      var features = o.features,
30
 
          i = -1, // features.index
31
 
          n = features.length;
32
 
      while (++i < n) buffer.push(pathType(features[i].geometry));
33
 
    },
34
 
 
35
 
    Feature: function(o) {
36
 
      pathType(o.geometry);
37
 
    },
38
 
 
39
 
    Point: function(o) {
40
 
      buffer.push("M", project(o.coordinates), pointCircle);
41
 
    },
42
 
 
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);
48
 
    },
49
 
 
50
 
    LineString: function(o) {
51
 
      var coordinates = o.coordinates,
52
 
          i = -1, // coordinates.index
53
 
          n = coordinates.length;
54
 
      buffer.push("M");
55
 
      while (++i < n) buffer.push(project(coordinates[i]), "L");
56
 
      buffer.pop();
57
 
    },
58
 
 
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
66
 
      while (++i < n) {
67
 
        subcoordinates = coordinates[i];
68
 
        j = -1;
69
 
        m = subcoordinates.length;
70
 
        buffer.push("M");
71
 
        while (++j < m) buffer.push(project(subcoordinates[j]), "L");
72
 
        buffer.pop();
73
 
      }
74
 
    },
75
 
 
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
83
 
      while (++i < n) {
84
 
        subcoordinates = coordinates[i];
85
 
        j = -1;
86
 
        if ((m = subcoordinates.length - 1) > 0) {
87
 
          buffer.push("M");
88
 
          while (++j < m) buffer.push(project(subcoordinates[j]), "L");
89
 
          buffer[buffer.length - 1] = "Z";
90
 
        }
91
 
      }
92
 
    },
93
 
 
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
104
 
      while (++i < n) {
105
 
        subcoordinates = coordinates[i];
106
 
        j = -1;
107
 
        m = subcoordinates.length;
108
 
        while (++j < m) {
109
 
          subsubcoordinates = subcoordinates[j];
110
 
          k = -1;
111
 
          if ((p = subsubcoordinates.length - 1) > 0) {
112
 
            buffer.push("M");
113
 
            while (++k < p) buffer.push(project(subsubcoordinates[k]), "L");
114
 
            buffer[buffer.length - 1] = "Z";
115
 
          }
116
 
        }
117
 
      }
118
 
    },
119
 
 
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]));
125
 
    }
126
 
 
127
 
  });
128
 
 
129
 
  var areaType = path.area = d3_geo_type({
130
 
 
131
 
    FeatureCollection: function(o) {
132
 
      var area = 0,
133
 
          features = o.features,
134
 
          i = -1, // features.index
135
 
          n = features.length;
136
 
      while (++i < n) area += areaType(features[i]);
137
 
      return area;
138
 
    },
139
 
 
140
 
    Feature: function(o) {
141
 
      return areaType(o.geometry);
142
 
    },
143
 
 
144
 
    Polygon: function(o) {
145
 
      return polygonArea(o.coordinates);
146
 
    },
147
 
 
148
 
    MultiPolygon: function(o) {
149
 
      var sum = 0,
150
 
          coordinates = o.coordinates,
151
 
          i = -1, // coordinates index
152
 
          n = coordinates.length;
153
 
      while (++i < n) sum += polygonArea(coordinates[i]);
154
 
      return sum;
155
 
    },
156
 
 
157
 
    GeometryCollection: function(o) {
158
 
      var sum = 0,
159
 
          geometries = o.geometries,
160
 
          i = -1, // geometries index
161
 
          n = geometries.length;
162
 
      while (++i < n) sum += areaType(geometries[i]);
163
 
      return sum;
164
 
    }
165
 
 
166
 
  }, 0);
167
 
 
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
173
 
    return sum;
174
 
  }
175
 
 
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),
180
 
        x = centroid[0],
181
 
        y = centroid[1],
182
 
        z = area,
183
 
        i = 0, // coordinates index
184
 
        n = coordinates.length;
185
 
    while (++i < n) {
186
 
      polygon = d3.geom.polygon(coordinates[i].map(projection)); // holes
187
 
      area = polygon.area();
188
 
      centroid = polygon.centroid(area < 0 ? (area *= -1, 1) : -1);
189
 
      x -= centroid[0];
190
 
      y -= centroid[1];
191
 
      z -= area;
192
 
    }
193
 
    return [x, y, 6 * z]; // weighted centroid
194
 
  }
195
 
 
196
 
  var centroidType = path.centroid = d3_geo_type({
197
 
 
198
 
    // TODO FeatureCollection
199
 
    // TODO Point
200
 
    // TODO MultiPoint
201
 
    // TODO LineString
202
 
    // TODO MultiLineString
203
 
    // TODO GeometryCollection
204
 
 
205
 
    Feature: function(o) {
206
 
      return centroidType(o.geometry);
207
 
    },
208
 
 
209
 
    Polygon: function(o) {
210
 
      var centroid = polygonCentroid(o.coordinates);
211
 
      return [centroid[0] / centroid[2], centroid[1] / centroid[2]];
212
 
    },
213
 
 
214
 
    MultiPolygon: function(o) {
215
 
      var area = 0,
216
 
          coordinates = o.coordinates,
217
 
          centroid,
218
 
          x = 0,
219
 
          y = 0,
220
 
          z = 0,
221
 
          i = -1, // coordinates index
222
 
          n = coordinates.length;
223
 
      while (++i < n) {
224
 
        centroid = polygonCentroid(coordinates[i]);
225
 
        x += centroid[0];
226
 
        y += centroid[1];
227
 
        z += centroid[2];
228
 
      }
229
 
      return [x / z, y / z];
230
 
    }
231
 
 
232
 
  });
233
 
 
234
 
  function area(coordinates) {
235
 
    return Math.abs(d3.geom.polygon(coordinates.map(projection)).area());
236
 
  }
237
 
 
238
 
  path.projection = function(x) {
239
 
    projection = x;
240
 
    return path;
241
 
  };
242
 
 
243
 
  path.pointRadius = function(x) {
244
 
    if (typeof x === "function") pointRadius = x;
245
 
    else {
246
 
      pointRadius = +x;
247
 
      pointCircle = d3_path_circle(pointRadius);
248
 
    }
249
 
    return path;
250
 
  };
251
 
 
252
 
  return path;
253
 
};
254
 
 
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)
259
 
      + "z";
260
 
}