wiki 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +1 -0
- data/lib/wiki.rb +2 -0
- data/lib/wiki/ReadMe.md +89 -0
- data/lib/wiki/config.ru +2 -0
- data/lib/wiki/favicon.rb +31 -0
- data/lib/wiki/page.rb +74 -0
- data/lib/wiki/random_id.rb +5 -0
- data/lib/wiki/server.rb +336 -0
- data/lib/wiki/server_helpers.rb +66 -0
- data/lib/wiki/stores/ReadMe.md +26 -0
- data/lib/wiki/stores/all.rb +3 -0
- data/lib/wiki/stores/couch.rb +121 -0
- data/lib/wiki/stores/file.rb +53 -0
- data/lib/wiki/stores/store.rb +38 -0
- data/lib/wiki/version.rb +3 -0
- data/lib/wiki/views/client/Gruntfile.js +50 -0
- data/lib/wiki/views/client/ReadMe.md +67 -0
- data/lib/wiki/views/client/build-test.bat +10 -0
- data/lib/wiki/views/client/build.bat +8 -0
- data/lib/wiki/views/client/builder.pl +41 -0
- data/lib/wiki/views/client/client.coffee +3 -0
- data/lib/wiki/views/client/client.js +3607 -0
- data/lib/wiki/views/client/crosses.png +0 -0
- data/lib/wiki/views/client/images/external-link-ltr-icon.png +0 -0
- data/lib/wiki/views/client/images/noise.png +0 -0
- data/lib/wiki/views/client/images/oops.jpg +0 -0
- data/lib/wiki/views/client/js/d3/d3.behavior.js +198 -0
- data/lib/wiki/views/client/js/d3/d3.chart.js +984 -0
- data/lib/wiki/views/client/js/d3/d3.csv.js +92 -0
- data/lib/wiki/views/client/js/d3/d3.geo.js +566 -0
- data/lib/wiki/views/client/js/d3/d3.geom.js +825 -0
- data/lib/wiki/views/client/js/d3/d3.js +3597 -0
- data/lib/wiki/views/client/js/d3/d3.layout.js +1923 -0
- data/lib/wiki/views/client/js/d3/d3.time.js +660 -0
- data/lib/wiki/views/client/js/images/ui-bg_glass_65_ffffff_1x400.png +0 -0
- data/lib/wiki/views/client/js/images/ui-icons_222222_256x240.png +0 -0
- data/lib/wiki/views/client/js/jquery-1.6.2.min.js +18 -0
- data/lib/wiki/views/client/js/jquery-1.7.1.min.js +4 -0
- data/lib/wiki/views/client/js/jquery-1.9.1.min.js +5 -0
- data/lib/wiki/views/client/js/jquery-migrate-1.1.1.min.js +3 -0
- data/lib/wiki/views/client/js/jquery-ui-1.10.1.custom.min.css +5 -0
- data/lib/wiki/views/client/js/jquery-ui-1.10.1.custom.min.js +6 -0
- data/lib/wiki/views/client/js/jquery-ui-1.8.16.custom.css +339 -0
- data/lib/wiki/views/client/js/jquery-ui-1.8.16.custom.min.js +315 -0
- data/lib/wiki/views/client/js/jquery.ie.cors.js +310 -0
- data/lib/wiki/views/client/js/jquery.ui.touch-punch.min.js +11 -0
- data/lib/wiki/views/client/js/modernizr.custom.63710.js +824 -0
- data/lib/wiki/views/client/js/sockjs-0.3.min.js +27 -0
- data/lib/wiki/views/client/js/underscore-min.js +30 -0
- data/lib/wiki/views/client/mkplugin.sh +97 -0
- data/lib/wiki/views/client/package.json +36 -0
- data/lib/wiki/views/client/runtests.html +26 -0
- data/lib/wiki/views/client/style.css +339 -0
- data/lib/wiki/views/client/test/mocha.css +231 -0
- data/lib/wiki/views/client/test/mocha.js +5340 -0
- data/lib/wiki/views/client/test/testclient.js +17133 -0
- data/lib/wiki/views/client/testclient.coffee +18 -0
- data/lib/wiki/views/client/theme/granite.css +59 -0
- data/lib/wiki/views/client/theme/stoneSeamless.jpg +0 -0
- data/lib/wiki/views/client/twitter-maintainance.jpg +0 -0
- data/lib/wiki/views/layout.haml +56 -0
- data/lib/wiki/views/oops.haml +5 -0
- data/lib/wiki/views/page.haml +20 -0
- data/lib/wiki/views/static.html +30 -0
- data/lib/wiki/views/view.haml +2 -0
- data/wiki.gemspec +28 -0
- metadata +121 -0
@@ -0,0 +1,92 @@
|
|
1
|
+
(function(){d3.csv = function(url, callback) {
|
2
|
+
d3.text(url, "text/csv", function(text) {
|
3
|
+
callback(text && d3.csv.parse(text));
|
4
|
+
});
|
5
|
+
};
|
6
|
+
d3.csv.parse = function(text) {
|
7
|
+
var header;
|
8
|
+
return d3.csv.parseRows(text, function(row, i) {
|
9
|
+
if (i) {
|
10
|
+
var o = {}, j = -1, m = header.length;
|
11
|
+
while (++j < m) o[header[j]] = row[j];
|
12
|
+
return o;
|
13
|
+
} else {
|
14
|
+
header = row;
|
15
|
+
return null;
|
16
|
+
}
|
17
|
+
});
|
18
|
+
};
|
19
|
+
|
20
|
+
d3.csv.parseRows = function(text, f) {
|
21
|
+
var EOL = {}, // sentinel value for end-of-line
|
22
|
+
EOF = {}, // sentinel value for end-of-file
|
23
|
+
rows = [], // output rows
|
24
|
+
re = /\r\n|[,\r\n]/g, // field separator regex
|
25
|
+
n = 0, // the current line number
|
26
|
+
t, // the current token
|
27
|
+
eol; // is the current token followed by EOL?
|
28
|
+
|
29
|
+
re.lastIndex = 0; // work-around bug in FF 3.6
|
30
|
+
|
31
|
+
/** @private Returns the next token. */
|
32
|
+
function token() {
|
33
|
+
if (re.lastIndex >= text.length) return EOF; // special case: end of file
|
34
|
+
if (eol) { eol = false; return EOL; } // special case: end of line
|
35
|
+
|
36
|
+
// special case: quotes
|
37
|
+
var j = re.lastIndex;
|
38
|
+
if (text.charCodeAt(j) === 34) {
|
39
|
+
var i = j;
|
40
|
+
while (i++ < text.length) {
|
41
|
+
if (text.charCodeAt(i) === 34) {
|
42
|
+
if (text.charCodeAt(i + 1) !== 34) break;
|
43
|
+
i++;
|
44
|
+
}
|
45
|
+
}
|
46
|
+
re.lastIndex = i + 2;
|
47
|
+
var c = text.charCodeAt(i + 1);
|
48
|
+
if (c === 13) {
|
49
|
+
eol = true;
|
50
|
+
if (text.charCodeAt(i + 2) === 10) re.lastIndex++;
|
51
|
+
} else if (c === 10) {
|
52
|
+
eol = true;
|
53
|
+
}
|
54
|
+
return text.substring(j + 1, i).replace(/""/g, "\"");
|
55
|
+
}
|
56
|
+
|
57
|
+
// common case
|
58
|
+
var m = re.exec(text);
|
59
|
+
if (m) {
|
60
|
+
eol = m[0].charCodeAt(0) !== 44;
|
61
|
+
return text.substring(j, m.index);
|
62
|
+
}
|
63
|
+
re.lastIndex = text.length;
|
64
|
+
return text.substring(j);
|
65
|
+
}
|
66
|
+
|
67
|
+
while ((t = token()) !== EOF) {
|
68
|
+
var a = [];
|
69
|
+
while ((t !== EOL) && (t !== EOF)) {
|
70
|
+
a.push(t);
|
71
|
+
t = token();
|
72
|
+
}
|
73
|
+
if (f && !(a = f(a, n++))) continue;
|
74
|
+
rows.push(a);
|
75
|
+
}
|
76
|
+
|
77
|
+
return rows;
|
78
|
+
};
|
79
|
+
d3.csv.format = function(rows) {
|
80
|
+
return rows.map(d3_csv_formatRow).join("\n");
|
81
|
+
};
|
82
|
+
|
83
|
+
function d3_csv_formatRow(row) {
|
84
|
+
return row.map(d3_csv_formatValue).join(",");
|
85
|
+
}
|
86
|
+
|
87
|
+
function d3_csv_formatValue(text) {
|
88
|
+
return /[",\n]/.test(text)
|
89
|
+
? "\"" + text.replace(/\"/g, "\"\"") + "\""
|
90
|
+
: text;
|
91
|
+
}
|
92
|
+
})();
|
@@ -0,0 +1,566 @@
|
|
1
|
+
(function(){d3.geo = {};
|
2
|
+
// TODO clip input coordinates on opposite hemisphere
|
3
|
+
d3.geo.azimuthal = function() {
|
4
|
+
var mode = "orthographic", // or stereographic
|
5
|
+
origin,
|
6
|
+
scale = 200,
|
7
|
+
translate = [480, 250],
|
8
|
+
x0,
|
9
|
+
y0,
|
10
|
+
cy0,
|
11
|
+
sy0;
|
12
|
+
|
13
|
+
function azimuthal(coordinates) {
|
14
|
+
var x1 = coordinates[0] * d3_radians - x0,
|
15
|
+
y1 = coordinates[1] * d3_radians,
|
16
|
+
cx1 = Math.cos(x1),
|
17
|
+
sx1 = Math.sin(x1),
|
18
|
+
cy1 = Math.cos(y1),
|
19
|
+
sy1 = Math.sin(y1),
|
20
|
+
k = mode == "stereographic" ? 1 / (1 + sy0 * sy1 + cy0 * cy1 * cx1) : 1,
|
21
|
+
x = k * cy1 * sx1,
|
22
|
+
y = k * (sy0 * cy1 * cx1 - cy0 * sy1);
|
23
|
+
return [
|
24
|
+
scale * x + translate[0],
|
25
|
+
scale * y + translate[1]
|
26
|
+
];
|
27
|
+
}
|
28
|
+
|
29
|
+
azimuthal.mode = function(x) {
|
30
|
+
if (!arguments.length) return mode;
|
31
|
+
mode = x;
|
32
|
+
return azimuthal;
|
33
|
+
};
|
34
|
+
|
35
|
+
azimuthal.origin = function(x) {
|
36
|
+
if (!arguments.length) return origin;
|
37
|
+
origin = x;
|
38
|
+
x0 = origin[0] * d3_radians;
|
39
|
+
y0 = origin[1] * d3_radians;
|
40
|
+
cy0 = Math.cos(y0);
|
41
|
+
sy0 = Math.sin(y0);
|
42
|
+
return azimuthal;
|
43
|
+
};
|
44
|
+
|
45
|
+
azimuthal.scale = function(x) {
|
46
|
+
if (!arguments.length) return scale;
|
47
|
+
scale = +x;
|
48
|
+
return azimuthal;
|
49
|
+
};
|
50
|
+
|
51
|
+
azimuthal.translate = function(x) {
|
52
|
+
if (!arguments.length) return translate;
|
53
|
+
translate = [+x[0], +x[1]];
|
54
|
+
return azimuthal;
|
55
|
+
};
|
56
|
+
|
57
|
+
return azimuthal.origin([0, 0]);
|
58
|
+
};
|
59
|
+
// Derived from Tom Carden's Albers implementation for Protovis.
|
60
|
+
// http://gist.github.com/476238
|
61
|
+
// http://mathworld.wolfram.com/AlbersEqual-AreaConicProjection.html
|
62
|
+
|
63
|
+
d3.geo.albers = function() {
|
64
|
+
var origin = [-98, 38],
|
65
|
+
parallels = [29.5, 45.5],
|
66
|
+
scale = 1000,
|
67
|
+
translate = [480, 250],
|
68
|
+
lng0, // d3_radians * origin[0]
|
69
|
+
n,
|
70
|
+
C,
|
71
|
+
p0;
|
72
|
+
|
73
|
+
function albers(coordinates) {
|
74
|
+
var t = n * (d3_radians * coordinates[0] - lng0),
|
75
|
+
p = Math.sqrt(C - 2 * n * Math.sin(d3_radians * coordinates[1])) / n;
|
76
|
+
return [
|
77
|
+
scale * p * Math.sin(t) + translate[0],
|
78
|
+
scale * (p * Math.cos(t) - p0) + translate[1]
|
79
|
+
];
|
80
|
+
}
|
81
|
+
|
82
|
+
function reload() {
|
83
|
+
var phi1 = d3_radians * parallels[0],
|
84
|
+
phi2 = d3_radians * parallels[1],
|
85
|
+
lat0 = d3_radians * origin[1],
|
86
|
+
s = Math.sin(phi1),
|
87
|
+
c = Math.cos(phi1);
|
88
|
+
lng0 = d3_radians * origin[0];
|
89
|
+
n = .5 * (s + Math.sin(phi2));
|
90
|
+
C = c * c + 2 * n * s;
|
91
|
+
p0 = Math.sqrt(C - 2 * n * Math.sin(lat0)) / n;
|
92
|
+
return albers;
|
93
|
+
}
|
94
|
+
|
95
|
+
albers.origin = function(x) {
|
96
|
+
if (!arguments.length) return origin;
|
97
|
+
origin = [+x[0], +x[1]];
|
98
|
+
return reload();
|
99
|
+
};
|
100
|
+
|
101
|
+
albers.parallels = function(x) {
|
102
|
+
if (!arguments.length) return parallels;
|
103
|
+
parallels = [+x[0], +x[1]];
|
104
|
+
return reload();
|
105
|
+
};
|
106
|
+
|
107
|
+
albers.scale = function(x) {
|
108
|
+
if (!arguments.length) return scale;
|
109
|
+
scale = +x;
|
110
|
+
return albers;
|
111
|
+
};
|
112
|
+
|
113
|
+
albers.translate = function(x) {
|
114
|
+
if (!arguments.length) return translate;
|
115
|
+
translate = [+x[0], +x[1]];
|
116
|
+
return albers;
|
117
|
+
};
|
118
|
+
|
119
|
+
return reload();
|
120
|
+
};
|
121
|
+
|
122
|
+
// A composite projection for the United States, 960x500. The set of standard
|
123
|
+
// parallels for each region comes from USGS, which is published here:
|
124
|
+
// http://egsc.usgs.gov/isb/pubs/MapProjections/projections.html#albers
|
125
|
+
// TODO allow the composite projection to be rescaled?
|
126
|
+
d3.geo.albersUsa = function() {
|
127
|
+
var lower48 = d3.geo.albers();
|
128
|
+
|
129
|
+
var alaska = d3.geo.albers()
|
130
|
+
.origin([-160, 60])
|
131
|
+
.parallels([55, 65]);
|
132
|
+
|
133
|
+
var hawaii = d3.geo.albers()
|
134
|
+
.origin([-160, 20])
|
135
|
+
.parallels([8, 18]);
|
136
|
+
|
137
|
+
var puertoRico = d3.geo.albers()
|
138
|
+
.origin([-60, 10])
|
139
|
+
.parallels([8, 18]);
|
140
|
+
|
141
|
+
function albersUsa(coordinates) {
|
142
|
+
var lon = coordinates[0],
|
143
|
+
lat = coordinates[1];
|
144
|
+
return (lat < 25
|
145
|
+
? (lon < -100 ? hawaii : puertoRico)
|
146
|
+
: (lat > 50 ? alaska : lower48))(coordinates);
|
147
|
+
}
|
148
|
+
|
149
|
+
albersUsa.scale = function(x) {
|
150
|
+
if (!arguments.length) return lower48.scale();
|
151
|
+
lower48.scale(x);
|
152
|
+
alaska.scale(x * .6);
|
153
|
+
hawaii.scale(x);
|
154
|
+
puertoRico.scale(x * 1.5);
|
155
|
+
return albersUsa.translate(lower48.translate());
|
156
|
+
};
|
157
|
+
|
158
|
+
albersUsa.translate = function(x) {
|
159
|
+
if (!arguments.length) return lower48.translate();
|
160
|
+
var dz = lower48.scale() / 1000,
|
161
|
+
dx = x[0],
|
162
|
+
dy = x[1];
|
163
|
+
lower48.translate(x);
|
164
|
+
alaska.translate([dx - 400 * dz, dy + 170 * dz]);
|
165
|
+
hawaii.translate([dx - 190 * dz, dy + 200 * dz]);
|
166
|
+
puertoRico.translate([dx + 580 * dz, dy + 430 * dz]);
|
167
|
+
return albersUsa;
|
168
|
+
};
|
169
|
+
|
170
|
+
return albersUsa.scale(lower48.scale());
|
171
|
+
};
|
172
|
+
|
173
|
+
var d3_radians = Math.PI / 180;
|
174
|
+
d3.geo.mercator = function() {
|
175
|
+
var scale = 500,
|
176
|
+
translate = [480, 250];
|
177
|
+
|
178
|
+
function mercator(coordinates) {
|
179
|
+
var x = (coordinates[0]) / 360,
|
180
|
+
y = (-180 / Math.PI * Math.log(Math.tan(Math.PI / 4 + coordinates[1] * Math.PI / 360))) / 360;
|
181
|
+
return [
|
182
|
+
scale * x + translate[0],
|
183
|
+
scale * Math.max(-.5, Math.min(.5, y)) + translate[1]
|
184
|
+
];
|
185
|
+
}
|
186
|
+
|
187
|
+
mercator.scale = function(x) {
|
188
|
+
if (!arguments.length) return scale;
|
189
|
+
scale = +x;
|
190
|
+
return mercator;
|
191
|
+
};
|
192
|
+
|
193
|
+
mercator.translate = function(x) {
|
194
|
+
if (!arguments.length) return translate;
|
195
|
+
translate = [+x[0], +x[1]];
|
196
|
+
return mercator;
|
197
|
+
};
|
198
|
+
|
199
|
+
return mercator;
|
200
|
+
};
|
201
|
+
/**
|
202
|
+
* Returns a function that, given a GeoJSON object (e.g., a feature), returns
|
203
|
+
* the corresponding SVG path. The function can be customized by overriding the
|
204
|
+
* projection. Point features are mapped to circles with a default radius of
|
205
|
+
* 4.5px; the radius can be specified either as a constant or a function that
|
206
|
+
* is evaluated per object.
|
207
|
+
*/
|
208
|
+
d3.geo.path = function() {
|
209
|
+
var pointRadius = 4.5,
|
210
|
+
pointCircle = d3_path_circle(pointRadius),
|
211
|
+
projection = d3.geo.albersUsa();
|
212
|
+
|
213
|
+
function path(d, i) {
|
214
|
+
if (typeof pointRadius === "function") {
|
215
|
+
pointCircle = d3_path_circle(pointRadius.apply(this, arguments));
|
216
|
+
}
|
217
|
+
return d3_geo_pathType(pathTypes, d);
|
218
|
+
}
|
219
|
+
|
220
|
+
function project(coordinates) {
|
221
|
+
return projection(coordinates).join(",");
|
222
|
+
}
|
223
|
+
|
224
|
+
var pathTypes = {
|
225
|
+
|
226
|
+
FeatureCollection: function(f) {
|
227
|
+
var path = [],
|
228
|
+
features = f.features,
|
229
|
+
i = -1, // features.index
|
230
|
+
n = features.length;
|
231
|
+
while (++i < n) path.push(d3_geo_pathType(pathTypes, features[i].geometry));
|
232
|
+
return path.join("");
|
233
|
+
},
|
234
|
+
|
235
|
+
Feature: function(f) {
|
236
|
+
return d3_geo_pathType(pathTypes, f.geometry);
|
237
|
+
},
|
238
|
+
|
239
|
+
Point: function(o) {
|
240
|
+
return "M" + project(o.coordinates) + pointCircle;
|
241
|
+
},
|
242
|
+
|
243
|
+
MultiPoint: function(o) {
|
244
|
+
var path = [],
|
245
|
+
coordinates = o.coordinates,
|
246
|
+
i = -1, // coordinates.index
|
247
|
+
n = coordinates.length;
|
248
|
+
while (++i < n) path.push("M", project(coordinates[i]), pointCircle);
|
249
|
+
return path.join("");
|
250
|
+
},
|
251
|
+
|
252
|
+
LineString: function(o) {
|
253
|
+
var path = ["M"],
|
254
|
+
coordinates = o.coordinates,
|
255
|
+
i = -1, // coordinates.index
|
256
|
+
n = coordinates.length;
|
257
|
+
while (++i < n) path.push(project(coordinates[i]), "L");
|
258
|
+
path.pop();
|
259
|
+
return path.join("");
|
260
|
+
},
|
261
|
+
|
262
|
+
MultiLineString: function(o) {
|
263
|
+
var path = [],
|
264
|
+
coordinates = o.coordinates,
|
265
|
+
i = -1, // coordinates.index
|
266
|
+
n = coordinates.length,
|
267
|
+
subcoordinates, // coordinates[i]
|
268
|
+
j, // subcoordinates.index
|
269
|
+
m; // subcoordinates.length
|
270
|
+
while (++i < n) {
|
271
|
+
subcoordinates = coordinates[i];
|
272
|
+
j = -1;
|
273
|
+
m = subcoordinates.length;
|
274
|
+
path.push("M");
|
275
|
+
while (++j < m) path.push(project(subcoordinates[j]), "L");
|
276
|
+
path.pop();
|
277
|
+
}
|
278
|
+
return path.join("");
|
279
|
+
},
|
280
|
+
|
281
|
+
Polygon: function(o) {
|
282
|
+
var path = [],
|
283
|
+
coordinates = o.coordinates,
|
284
|
+
i = -1, // coordinates.index
|
285
|
+
n = coordinates.length,
|
286
|
+
subcoordinates, // coordinates[i]
|
287
|
+
j, // subcoordinates.index
|
288
|
+
m; // subcoordinates.length
|
289
|
+
while (++i < n) {
|
290
|
+
subcoordinates = coordinates[i];
|
291
|
+
j = -1;
|
292
|
+
m = subcoordinates.length;
|
293
|
+
path.push("M");
|
294
|
+
while (++j < m) path.push(project(subcoordinates[j]), "L");
|
295
|
+
path[path.length - 1] = "Z";
|
296
|
+
}
|
297
|
+
return path.join("");
|
298
|
+
},
|
299
|
+
|
300
|
+
MultiPolygon: function(o) {
|
301
|
+
var path = [],
|
302
|
+
coordinates = o.coordinates,
|
303
|
+
i = -1, // coordinates index
|
304
|
+
n = coordinates.length,
|
305
|
+
subcoordinates, // coordinates[i]
|
306
|
+
j, // subcoordinates index
|
307
|
+
m, // subcoordinates.length
|
308
|
+
subsubcoordinates, // subcoordinates[j]
|
309
|
+
k, // subsubcoordinates index
|
310
|
+
p; // subsubcoordinates.length
|
311
|
+
while (++i < n) {
|
312
|
+
subcoordinates = coordinates[i];
|
313
|
+
j = -1;
|
314
|
+
m = subcoordinates.length;
|
315
|
+
while (++j < m) {
|
316
|
+
subsubcoordinates = subcoordinates[j];
|
317
|
+
k = -1;
|
318
|
+
p = subsubcoordinates.length - 1;
|
319
|
+
path.push("M");
|
320
|
+
while (++k < p) path.push(project(subsubcoordinates[k]), "L");
|
321
|
+
path[path.length - 1] = "Z";
|
322
|
+
}
|
323
|
+
}
|
324
|
+
return path.join("");
|
325
|
+
},
|
326
|
+
|
327
|
+
GeometryCollection: function(o) {
|
328
|
+
var path = [],
|
329
|
+
geometries = o.geometries,
|
330
|
+
i = -1, // geometries index
|
331
|
+
n = geometries.length;
|
332
|
+
while (++i < n) path.push(d3_geo_pathType(pathTypes, geometries[i]));
|
333
|
+
return path.join("");
|
334
|
+
}
|
335
|
+
|
336
|
+
};
|
337
|
+
|
338
|
+
var areaTypes = {
|
339
|
+
|
340
|
+
FeatureCollection: function(f) {
|
341
|
+
var area = 0,
|
342
|
+
features = f.features,
|
343
|
+
i = -1, // features.index
|
344
|
+
n = features.length;
|
345
|
+
while (++i < n) area += d3_geo_pathType(areaTypes, features[i]);
|
346
|
+
return area;
|
347
|
+
},
|
348
|
+
|
349
|
+
Feature: function(f) {
|
350
|
+
return d3_geo_pathType(areaTypes, f.geometry);
|
351
|
+
},
|
352
|
+
|
353
|
+
Point: d3_geo_pathZero,
|
354
|
+
MultiPoint: d3_geo_pathZero,
|
355
|
+
LineString: d3_geo_pathZero,
|
356
|
+
MultiLineString: d3_geo_pathZero,
|
357
|
+
|
358
|
+
Polygon: function(o) {
|
359
|
+
return polygonArea(o.coordinates);
|
360
|
+
},
|
361
|
+
|
362
|
+
MultiPolygon: function(o) {
|
363
|
+
var sum = 0,
|
364
|
+
coordinates = o.coordinates,
|
365
|
+
i = -1, // coordinates index
|
366
|
+
n = coordinates.length;
|
367
|
+
while (++i < n) sum += polygonArea(coordinates[i]);
|
368
|
+
return sum;
|
369
|
+
},
|
370
|
+
|
371
|
+
GeometryCollection: function(o) {
|
372
|
+
var sum = 0,
|
373
|
+
geometries = o.geometries,
|
374
|
+
i = -1, // geometries index
|
375
|
+
n = geometries.length;
|
376
|
+
while (++i < n) sum += d3_geo_pathType(areaTypes, geometries[i]);
|
377
|
+
return sum;
|
378
|
+
}
|
379
|
+
|
380
|
+
};
|
381
|
+
|
382
|
+
function polygonArea(coordinates) {
|
383
|
+
var sum = area(coordinates[0]), // exterior ring
|
384
|
+
i = 0, // coordinates.index
|
385
|
+
n = coordinates.length;
|
386
|
+
while (++i < n) sum -= area(coordinates[i]); // holes
|
387
|
+
return sum;
|
388
|
+
}
|
389
|
+
|
390
|
+
function polygonCentroid(coordinates) {
|
391
|
+
var polygon = d3.geom.polygon(coordinates[0].map(projection)), // exterior ring
|
392
|
+
centroid = polygon.centroid(1),
|
393
|
+
x = centroid[0],
|
394
|
+
y = centroid[1],
|
395
|
+
z = Math.abs(polygon.area()),
|
396
|
+
i = 0, // coordinates index
|
397
|
+
n = coordinates.length;
|
398
|
+
while (++i < n) {
|
399
|
+
polygon = d3.geom.polygon(coordinates[i].map(projection)); // holes
|
400
|
+
centroid = polygon.centroid(1);
|
401
|
+
x -= centroid[0];
|
402
|
+
y -= centroid[1];
|
403
|
+
z -= Math.abs(polygon.area());
|
404
|
+
}
|
405
|
+
return [x, y, 6 * z]; // weighted centroid
|
406
|
+
}
|
407
|
+
|
408
|
+
var centroidTypes = {
|
409
|
+
|
410
|
+
// TODO FeatureCollection
|
411
|
+
// TODO Point
|
412
|
+
// TODO MultiPoint
|
413
|
+
// TODO LineString
|
414
|
+
// TODO MultiLineString
|
415
|
+
// TODO GeometryCollection
|
416
|
+
|
417
|
+
Feature: function(f) {
|
418
|
+
return d3_geo_pathType(centroidTypes, f.geometry);
|
419
|
+
},
|
420
|
+
|
421
|
+
Polygon: function(o) {
|
422
|
+
var centroid = polygonCentroid(o.coordinates);
|
423
|
+
return [centroid[0] / centroid[2], centroid[1] / centroid[2]];
|
424
|
+
},
|
425
|
+
|
426
|
+
MultiPolygon: function(o) {
|
427
|
+
var area = 0,
|
428
|
+
coordinates = o.coordinates,
|
429
|
+
centroid,
|
430
|
+
x = 0,
|
431
|
+
y = 0,
|
432
|
+
z = 0,
|
433
|
+
i = -1, // coordinates index
|
434
|
+
n = coordinates.length;
|
435
|
+
while (++i < n) {
|
436
|
+
centroid = polygonCentroid(coordinates[i]);
|
437
|
+
x += centroid[0];
|
438
|
+
y += centroid[1];
|
439
|
+
z += centroid[2];
|
440
|
+
}
|
441
|
+
return [x / z, y / z];
|
442
|
+
}
|
443
|
+
|
444
|
+
};
|
445
|
+
|
446
|
+
|
447
|
+
function area(coordinates) {
|
448
|
+
return Math.abs(d3.geom.polygon(coordinates.map(projection)).area());
|
449
|
+
}
|
450
|
+
|
451
|
+
path.projection = function(x) {
|
452
|
+
projection = x;
|
453
|
+
return path;
|
454
|
+
};
|
455
|
+
|
456
|
+
path.area = function(d) {
|
457
|
+
return d3_geo_pathType(areaTypes, d);
|
458
|
+
};
|
459
|
+
|
460
|
+
path.centroid = function(d) {
|
461
|
+
return d3_geo_pathType(centroidTypes, d);
|
462
|
+
};
|
463
|
+
|
464
|
+
path.pointRadius = function(x) {
|
465
|
+
if (typeof x === "function") pointRadius = x;
|
466
|
+
else {
|
467
|
+
pointRadius = +x;
|
468
|
+
pointCircle = d3_path_circle(pointRadius);
|
469
|
+
}
|
470
|
+
return path;
|
471
|
+
};
|
472
|
+
|
473
|
+
return path;
|
474
|
+
};
|
475
|
+
|
476
|
+
function d3_path_circle(radius) {
|
477
|
+
return "m0," + radius
|
478
|
+
+ "a" + radius + "," + radius + " 0 1,1 0," + (-2 * radius)
|
479
|
+
+ "a" + radius + "," + radius + " 0 1,1 0," + (+2 * radius)
|
480
|
+
+ "z";
|
481
|
+
}
|
482
|
+
|
483
|
+
function d3_geo_pathZero() {
|
484
|
+
return 0;
|
485
|
+
}
|
486
|
+
|
487
|
+
function d3_geo_pathType(types, o) {
|
488
|
+
return o && o.type in types ? types[o.type](o) : "";
|
489
|
+
}
|
490
|
+
/**
|
491
|
+
* Given a GeoJSON object, returns the corresponding bounding box. The bounding
|
492
|
+
* box is represented by a two-dimensional array: [[left, bottom], [right,
|
493
|
+
* top]], where left is the minimum longitude, bottom is the minimum latitude,
|
494
|
+
* right is maximum longitude, and top is the maximum latitude.
|
495
|
+
*/
|
496
|
+
d3.geo.bounds = function(feature) {
|
497
|
+
var left = Infinity,
|
498
|
+
bottom = Infinity,
|
499
|
+
right = -Infinity,
|
500
|
+
top = -Infinity;
|
501
|
+
d3_geo_bounds(feature, function(x, y) {
|
502
|
+
if (x < left) left = x;
|
503
|
+
if (x > right) right = x;
|
504
|
+
if (y < bottom) bottom = y;
|
505
|
+
if (y > top) top = y;
|
506
|
+
});
|
507
|
+
return [[left, bottom], [right, top]];
|
508
|
+
};
|
509
|
+
|
510
|
+
function d3_geo_bounds(o, f) {
|
511
|
+
if (o.type in d3_geo_boundsTypes) d3_geo_boundsTypes[o.type](o, f);
|
512
|
+
}
|
513
|
+
|
514
|
+
var d3_geo_boundsTypes = {
|
515
|
+
Feature: d3_geo_boundsFeature,
|
516
|
+
FeatureCollection: d3_geo_boundsFeatureCollection,
|
517
|
+
LineString: d3_geo_boundsLineString,
|
518
|
+
MultiLineString: d3_geo_boundsMultiLineString,
|
519
|
+
MultiPoint: d3_geo_boundsLineString,
|
520
|
+
MultiPolygon: d3_geo_boundsMultiPolygon,
|
521
|
+
Point: d3_geo_boundsPoint,
|
522
|
+
Polygon: d3_geo_boundsPolygon
|
523
|
+
};
|
524
|
+
|
525
|
+
function d3_geo_boundsFeature(o, f) {
|
526
|
+
d3_geo_bounds(o.geometry, f);
|
527
|
+
}
|
528
|
+
|
529
|
+
function d3_geo_boundsFeatureCollection(o, f) {
|
530
|
+
for (var a = o.features, i = 0, n = a.length; i < n; i++) {
|
531
|
+
d3_geo_bounds(a[i].geometry, f);
|
532
|
+
}
|
533
|
+
}
|
534
|
+
|
535
|
+
function d3_geo_boundsLineString(o, f) {
|
536
|
+
for (var a = o.coordinates, i = 0, n = a.length; i < n; i++) {
|
537
|
+
f.apply(null, a[i]);
|
538
|
+
}
|
539
|
+
}
|
540
|
+
|
541
|
+
function d3_geo_boundsMultiLineString(o, f) {
|
542
|
+
for (var a = o.coordinates, i = 0, n = a.length; i < n; i++) {
|
543
|
+
for (var b = a[i], j = 0, m = b.length; j < m; j++) {
|
544
|
+
f.apply(null, b[j]);
|
545
|
+
}
|
546
|
+
}
|
547
|
+
}
|
548
|
+
|
549
|
+
function d3_geo_boundsMultiPolygon(o, f) {
|
550
|
+
for (var a = o.coordinates, i = 0, n = a.length; i < n; i++) {
|
551
|
+
for (var b = a[i][0], j = 0, m = b.length; j < m; j++) {
|
552
|
+
f.apply(null, b[j]);
|
553
|
+
}
|
554
|
+
}
|
555
|
+
}
|
556
|
+
|
557
|
+
function d3_geo_boundsPoint(o, f) {
|
558
|
+
f.apply(null, o.coordinates);
|
559
|
+
}
|
560
|
+
|
561
|
+
function d3_geo_boundsPolygon(o, f) {
|
562
|
+
for (var a = o.coordinates[0], i = 0, n = a.length; i < n; i++) {
|
563
|
+
f.apply(null, a[i]);
|
564
|
+
}
|
565
|
+
}
|
566
|
+
})();
|