202 |
203 | This d3 tutorial gives a brief introduction to the following.
204 |
205 |
206 |
d3 Selectors
207 |
d3 Data Joins
208 |
209 |
210 | The above are just a fraction of the actual d3 library functionalities. The two topics are introduced here because the Moon Phase Visualizer demo is built with a basic usage of above functionalities of d3.js. This tutorial is intentionally short and aimed at just giving a good brief introduction for d3.js beginners.
211 |
212 |
213 |
214 |
215 |
216 |
What is d3.js?
217 |
218 |
219 |
d3.js associates data to an element or group of elements in the html page. Exactly what its definition says - Data Driven Documents.
220 |
All the resulting complex visualizations (graphs, charts, maps etc) associated with d3.js are the result of how we choose to represent that data.
221 |
222 |
223 |
224 |
225 |
226 |
227 |
d3 Selectors
228 |
229 |
230 |
d3.js helps to select elements from html page using two functions - select(), selectAll()
231 |
select() selects only one element. If there are more than one element for the given selector it selects the first one only.
232 |
selectAll() selects all the elements for that selector. d3.js uses css style selectors. If you are familiar with selecting elements with jQuery, d3 selectors are almost the same.
233 |
234 |
235 |
236 | When you select html element(s) with the above functions, you can do all the fancy things like change its attributes, style etc. For example, in the Moon Phase Visualizer demo, the rotation of moon is just selecting the circle element (moon) and just update the x and y position over the period of the time.
237 |
238 |
239 |
240 |
241 | // select the moon using 'select'. 'select' returns only one element
242 | var moon = d3.select("#moon");
243 |
244 | // calculate the co-ordinates
245 | // x = somevalue; y = somevalue;
246 |
247 | // now update the position using our selection
248 | moon.attr("cx", x).attr("cy", y);
249 |
250 | // ------------------------------------------------------------------
251 |
252 | // With 'selectAll' we can select all the elements for the selection
253 | // Here there are 2 timer elements in the page; returns both
254 | var timer = d3.selectAll(".phase.timer");
255 |
256 | // calculate the time
257 | // time = somevalue;
258 |
259 | // now update 'all' the elements from the 'selectAll'.
260 | timer.text( time );
261 |
262 |
263 |
264 |
265 | But the real power of d3.js is not just selecting random elements, but help associating some data with the elements (before or after selecting the elements) and manipulate the elements with respect to the data associated with the elements. d3.js does this with Data Joins.
266 |
267 |
268 |
269 |
270 |
271 |
272 |
d3 Data Joins
273 |
274 |
275 | Data Joins helps us to associate some data (which is given as an array) with html elements. If the data array changes, corresponding html elements can be easily associated or disassociated with the data.
276 |
277 |
278 |
279 |
280 | Data Joins involve the following
281 |
282 |
283 |
Selectors - we need some html elements to associate the data. These are got using selectors introduced previously. With Data Joins it is not necessary that the elements have to present already in the page. We will see that in a moment.
284 |
Data Array - the actual data to associate in the form of array. No matter how many elements are present, data is always given as an array.
285 |
'Key' function - optional function that describes the relation between the data array and the elements. By default, first element in the data array is associated with the first element, second data with second element and so on; that is index based. We can provide an optional function that explictly returns a 'key' that should be used as a relationship to associate the data in the array with the element.
286 |
enter() & append() - If new data is added to the data array, using enter() we can automatically access newly added data. At this point, the new html elements will not be present for this data. By calling append() new html elements can be added for the new data. This is called when our data is more than the html elements.
287 |
exit() & remove() - If data is removed from the data array, using exit() we can automatically access html elements for the removed data. With remove() we can remove the html elements associated with the removed data. This is called when html elements are more than our data.
288 |
289 |
290 |
291 |
292 |
293 |
294 |
Star Show with Data Joins
295 |
296 | The left main screen (Fig A) in the above demo contains number of stars as background. Each star is represented by an svg circle element. Each star has a distinct position in the form of an 'x' and 'y' co-ordinate. The positions are generated randomly. For every few seconds, some stars disappear which will become red before disappearing, and new stars will appear which will be shown as blue. This was done using d3 Data Joins and lets see how its done.
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 | Our data is represented by a set of (x,y) co-ordinates which will be attributes of an object. Now, we have to display this data as something visual, which is a star with that particular co-ordinates as its position. It is important to remember that we still dont have any circle elements in the page representing the stars.
305 |
306 |
307 |
308 | // our data array containing star co-ordinates; initially it will be empty
309 | var starData = [];
310 |
311 | // lets fill the starData with sets of 10 random co-ordinates; Each co-ordinate represent a star position.
312 | // [ {x: 1, y: 1}, {x: 34, y: 56}, {x: 32, y: 8}, {x: 22, y: 48} ....... ] // total of 10 sets
313 |
314 | // the holder that will contain all the stars
315 | var canvas = d3.select("#starCanvas");
316 |
317 |
318 |
319 |
320 |
321 |
322 |
323 |
324 |
325 |
326 |
327 |
328 | Now, let us try to associate the co-ordinates data with circle element
329 |
330 |
331 |
332 | canvas.selectAll("circle") // select the circle elements (0 elements currently)
333 | .data( starData ); // bind the data to the circles (10 co-ordinates)
334 |
335 |
336 |
337 | If we had initially 5 circle elements, the previous statement would have bound the first 5 co-ordinates to the 5 circle elements.
338 |
339 | If we see the above statement, we have 0 circle elements. But we have 10 co-ordinates. There are no circles to associate the co-ordinate data. In other words, we have 10 extra co-ordinate data for which we need circle elements to associate with.
340 |
341 |
342 |
343 |
344 | enter() & append(). Calling enter() returns the set of data for which there are no elements associated yet. In this case, all the 10 co-ordinates. Calling append("circle") creates new 'circle' elements and associates the data with it. The method append() appends elements of whatever tag is given as its argument. Expanding on the previous statement, we have
345 |
346 |
347 |
348 | canvas.selectAll("circle") // select the circle elements (0 elements currently)
349 | .data( starData ); // bind the data to the circles (10 co-ordinates)
350 | .enter() // gets the new data without elements associated
351 | .append("circle") // add the new elements for the new data
352 |
353 |
354 |
355 |
356 |
357 |
358 |
359 | At this point, we have new circle elements in the html page for each set of co-ordinates. Our aim is to make the co-ordinates as the position of the circle element. SVG circle elements takes the following attributes: cx - x position, cy - y position, r - radius of the circle. Now we have a unique situation. We have associated the co-ordinate data to the circle element. How to tell d3.js to take that data and use it on the html elements as attributes? Let us expand further.
360 |
361 |
362 |
363 | canvas.selectAll("circle") // select the circle elements (0 elements currently)
364 | .data( starData ); // bind the data to the circles (10 co-ordinates)
365 | .enter() // gets the new data without elements associated
366 | .append("circle") // add the new elements for the new data
367 | .attr("r", 1); // static radius value is used for all elements
368 | .attr("cx", function (d) { return d.x; } ) // dynamically takes x position from bound data for this element
369 | .attr("cy", function (d) { return d.y; } ) // dynamically takes y position from bound data for this element
370 |
371 |
372 |
373 | d3.js has attr() methods, that takes a value or a function as second argument. If a value is used, it is used directly. This is done for the r attribute. All the stars have a default radius of one. But for the (x,y) positions we need values from our co-ordinates which we associated with the circle. d3.js allows us to use a function as second argument, with our bound data as the argument. So we return our (x, y) value from our co-ordinate object for (cx, cy) attributes respectively.
374 |
375 |
376 |
377 |
378 |
379 |
380 |
381 |
382 | Let us remove some stars. For this, we don't have to do ugly stuff like look for circle elements in html page and remove them. By now, we can see that d3.js maintains a close relationship between our data and the corresponding html elements. First we have to remove data from our data array. Then calling exit() will return the html elements for which there is no data in our data array. At this point, we have html elements that have no data from our data array. They are not removed yet. We can do something with those extra html elements if we need to before removing them. Only by calling remove(), the extra html elements are actually removed.
383 |
384 |
385 |
386 | // let us remove 3 stars from the data Array
387 | starData = starData.slice(0, starData.length - 3);
388 |
389 | canvas.selectAll("circle") // select the circle elements (10 elements currently)
390 | .data( starData ); // bind the new data to the circles (7 co-ordinates)
391 | .exit() // gets the extra circle elements not bound to new data, in this case last 3
392 | // let us change their color to red for 2 seconds before removing them
393 | .transition().duration(2000).style("stroke", "red").style("fill", "red")
394 | // only now the extra html elements are removed.
395 | .remove();
396 |
397 |
398 |
399 |
400 |
401 |
402 |
403 |
404 | If we decide to add new stars, all we have to do is to update our data array and then let d3.js automatically add html elements from our data using our enter() and append() which we saw previously.
405 |
406 |
407 |
408 | // let us add 3 stars to our data array
409 | starData.push( {x: 23, y: 44} );
410 | starData.push( {x: 33, y: 54} );
411 | starData.push( {x: 43, y: 24} );
412 |
413 | canvas.selectAll("circle") // select the circle elements (7 elements currently)
414 | .data( starData ); // bind the new data to the circles (10 co-ordinates)
415 | .enter() // gets the extra data without bound html elements (last 3 co-ordinates)
416 | .append("circle") // add the new elements for the new data
417 | .attr("r", 1); // static radius value is used for all elements
418 | .attr("cx", function (d) { return d.x; } ) // dynamically takes x position from bound data for this element
419 | .attr("cy", function (d) { return d.y; } ) // dynamically takes y position from bound data for this element
420 | .style("stroke", "blue").style("fill", "blue") // initial star color
421 | // let us change their color back to white from blue after 2 seconds
422 | .transition().duration(2000).style("stroke", "white").style("fill", "white");
423 |
424 |
425 |
426 |
427 |
428 |
429 | How to update the existing elements to something we need? For example, if we want to change all the existing star color to 'silver'.
430 | In this case there are no additions or deletions. If we do a data join, we will get the existing html elements bound to the current data. Then we can manipulate the existing elements to our wish.
431 |
432 |
433 |
434 | canvas.selectAll("circle") // select the circle elements (10 elements currently)
435 | .data( starData ); // bind the current data to the circles (10 co-ordinates)
436 | // now we have got our existing stars; do whatever we want to do to them
437 | .style("stroke", "silver").style("fill", "silver");
438 |
439 |
440 |
441 | Every time Data Join is done, the data is updated with the corresponding html element. For example, if we have changed some of the stars' co-ordinates, previous data join would have updated them. To reflect that change, we need to update their position. Expanding on the previous statement,
442 |
443 |
444 |
445 | // we have updated some of the stars' co-ordinates; So update to their new positions
446 | canvas.selectAll("circle") // select the circle elements
447 | .data( starData ); // bind the current data to the circles (changed co-ordinates will be updated now)
448 | // update the circle elements to new position
449 | .attr("cx", function (d) { return d.x; } ) // all stars gets their new x co-ordinate
450 | .attr("cy", function (d) { return d.y; } ) // all stars gets their new y co-ordinate
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 | It is important to note that we have not used the optional 'key' function in our data binding, since we are using the default index based mapping. That is, first data in the data array should correspond to the first html element and so on. d3.js allows us to define a custom key function to define the relation between our data and the html element.
459 |
460 |
461 |
462 |
463 |
464 |
465 |
466 |
467 |
Resources
468 |
469 | d3.js wiki page gives a lot of interesting resources to check out. Particularly, Thinking with Joins by Michael Bostock (the creator of d3.js) is really great to learn about d3.js data joins.
470 |
471 |
472 |
473 |
474 |
475 |
Feedback
476 |
477 | Feedbacks and suggestions are greatly appreciated. If you are familiar with Github you can use Github issues for any changes or suggestions in this article. Also, you can ping your feedbacks to initdot@gmail.com.
478 |
479 |
480 |
481 |
482 |
483 |
484 | This demo is currently best viewed in chrome. Tested in Chrome and Firefox.
485 |
486 |
487 |
488 | This demo is not to scale. They are not shown with complete scientific accuracy for demonstration purposes.
489 |
183 | Moon phase visualizer is a simple demo to understand how Moon's phases (and eclipses) occur.
184 |
185 |
186 |
187 |
188 |
189 |
190 |
Moon Phases
191 |
192 |
193 |
Fig A (main left visual) - shows Moon's position during different phases. It shows the top view of Moon's orbit around Earth.
194 |
Fig a (top right visual) - shows Moon's shape during different phases for the position in Fig A.
195 |
The dotted portion of the moon in Fig A shows the side of the moon which is always facing the Earth. This is called Tidal Locking. Tidal Locking occurs because moon's rotation around its axis takes the same time taken for moon's rotation around earth.
196 |
197 |
198 |
199 |
200 |
201 |
Eclipses
202 |
203 |
204 |
Fig b (bottom left visual)- shows how earth and moon shadows have to coincide with line of nodes (the red line) for eclipses to occur.
205 |
If Fig b is visualized in 3 dimensional space, the bottom end of line of nodes will be facing towards the viewer, and the top end will be facing away from the viewer. Earth and Moon's shadow in these positions will also be facing towards and away respectively.
206 |
Moon's orbit around the earth is tilted by an angle of 5.1 degrees. Due to this moon will always miss the earth's shadow passing outside of it except in line of nodes.
207 |
Lunar Eclipse occurs when earth is between moon and the sun. This occurs only on a full moon day (Day 14 in Fig a).
208 |
Solar Eclipse occurs when moon is between earth and the sun. This occurs only on a new moon day (Day 29.5 in Fig a).
209 |
Eclipses occur only in the line of nodes.
210 |
211 |
212 |
213 | Eclipses happen when lines of nodes (red line in Fig b) co-incides with shadow of earth or moon. Watch the lines of nodes turn green for every few revolutions (approx 3-4) when the shadow of moon and earth coincides with them. If the moon is in full moon position then it is a lunar eclipse; if in new moon position it is a solar eclipse. The part of the shadow shown is called 'umbra' which results in Total Eclipses. There is another component of shadow called 'penumbra' (not shown in the figure) which results in partial eclipses.
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
Feedback & Contributing
222 |
223 |
224 | Feedbacks, Improvements and Contributions are greatly appreciated. If you are familiar with Github, you can find the source computer program for this demo here. Check out Github issue tracker here for current issues and problems.
225 |
226 |
227 |
228 |
229 |
230 |
231 |
About
232 |
233 |
234 | This demo is built using d3.js. There is a very brief introduction to d3.js with some of the elements of this demo, which you can check out here.
235 |
236 |
237 |
238 |
239 |
240 |
241 |
242 |
243 |
244 | This demo is currently best viewed in chrome. Tested in Chrome and Firefox.
245 |
246 |
247 |
248 | This demo is not to scale. They are not shown with complete scientific accuracy for demonstration purposes.
249 |
250 |
251 |
252 |
253 |
254 |
255 |
256 |
257 |
258 |
259 |
260 |
--------------------------------------------------------------------------------
/js/d3-moon-viz.js:
--------------------------------------------------------------------------------
1 | ( function () {
2 |
3 | // moon phase visualizer
4 | var moonViz = {
5 |
6 | stars: [], // holds the co-ordinates of the background stars
7 |
8 | render: function () {
9 |
10 | drawMainView(); // draws the big left visual
11 | drawAlternateView(); // draws the small right visual
12 | starShow(); // manages the background stars in the left visual
13 | }
14 |
15 | };
16 |
17 | // add a warning if the browser does not support svg (or any other necessary features)
18 | if (!Modernizr.svg) {
19 |
20 | // svg was not detected by the modernizr; add a warning.
21 | var warning = d3.select("#no-svg");
22 | var w_text = "Your browser does not seem to support svg. Please use any modern browser like Chrome or Firefox.";
23 | warning.text(w_text).attr("class", "no-svg");
24 |
25 | } else {
26 |
27 | // svg is present; hopefully demo will work; proceed with the Moon Phase Visualizer
28 |
29 | moonViz.render();
30 |
31 | moonViz.animate = function () {
32 |
33 | requestAnimationFrame( moonViz.animate );
34 | // updates the phase view in left main visual and top right visual
35 | moonViz.updateMoonPhaseView();
36 | // updates the eclipse view in bottom right visual
37 | moonViz.updateEclipseView();
38 |
39 | };
40 |
41 | requestAnimationFrame( moonViz.animate );
42 |
43 | // animates the background stars (adds and removes few random stars)
44 | setInterval( starShow, 10000 );
45 |
46 | }
47 |
48 | // **************************************************************************************************************************
49 |
50 | function drawMainView() {
51 |
52 |
53 | // this module draws the main left visual
54 | // shows the Moon's position during different phases
55 |
56 | // draw the svg canvas
57 | // svg dimensions
58 | var width = 880,
59 | height = 500;
60 |
61 | var svg = d3.select("body")
62 | .select("#moon-viz")
63 | .attr("width", width)
64 | .attr("height", height);
65 |
66 | svg.append("g").attr("id", "moon-viz-grouping");
67 |
68 | // draw the earth which is an circle
69 | // define earth co-ordinates and dimensions
70 | var ex = width/2,
71 | ey = height/2,
72 | esize = 75;
73 |
74 |
75 | var earth = d3.select("#moon-viz")
76 | .select("g#moon-viz-grouping")
77 | .append("g")
78 | .attr("id", "earth")
79 | .append("circle")
80 | .attr("cx", ex)
81 | .attr("cy", ey)
82 | .attr("r", esize);
83 |
84 | // draw continent like random goofy structures
85 | var co_ords = [ { x: ex, y: ey } ];
86 | co_ords.push( { x: +ex + 3, y: +ey + 3 } );
87 | co_ords.push( { x: +ex + 5, y: +ey + 6 } );
88 | co_ords.push( { x: +ex + 7, y: +ey + 6 } );
89 | co_ords.push( { x: +ex + 9, y: +ey + 16 } );
90 | co_ords.push( { x: +ex - 3, y: +ey + 16 } );
91 | co_ords.push( { x: +ex - 5, y: +ey + 6 } );
92 | co_ords.push( { x: +ex - 7, y: +ey + 6 } );
93 | co_ords.push( { x: +ex - 9, y: +ey + 6 } );
94 |
95 | co_ords.push( { x: +ex + 3, y: +ey + 3 - 50 } );
96 | co_ords.push( { x: +ex + 5, y: +ey + 6 - 50 } );
97 | co_ords.push( { x: +ex + 7, y: +ey + 6 - 50 } );
98 | co_ords.push( { x: +ex + 9, y: +ey + 16 - 50 } );
99 | co_ords.push( { x: +ex - 3, y: +ey + 16 - 50 } );
100 | co_ords.push( { x: +ex - 5, y: +ey + 6 - 50 } );
101 |
102 | co_ords.push( { x: +ex - 3 - 45, y: +ey + 16 + 30 } );
103 | co_ords.push( { x: +ex - 5 - 45, y: +ey + 6 + 30 } );
104 |
105 | co_ords.push( { x: +ex + 3 - 55, y: +ey + 3 - 15 } );
106 | co_ords.push( { x: +ex + 5 - 55, y: +ey + 6 - 15 } );
107 | co_ords.push( { x: +ex + 7 - 55, y: +ey + 6 - 15 } );
108 | co_ords.push( { x: +ex + 9 - 5, y: +ey + 16 - 15 } );
109 | co_ords.push( { x: +ex - 3 - 55, y: +ey + 3 - 15 } );
110 | co_ords.push( { x: +ex - 5 - 55, y: +ey + 6 - 15 } );
111 | co_ords.push( { x: +ex - 7 - 55, y: +ey + 6 - 15 } );
112 | co_ords.push( { x: +ex - 9 - 55, y: +ey + 16 - 15 } );
113 |
114 | co_ords.push( { x: +ex + 5 + 35, y: +ey + 6 - 15 } );
115 | co_ords.push( { x: +ex + 7 + 41, y: +ey + 6 - 15 } );
116 | co_ords.push( { x: +ex - 9 + 1, y: +ey + 16 - 15 } );
117 | co_ords.push( { x: +ex - 3 + 55, y: +ey + 3 - 15 } );
118 | co_ords.push( { x: +ex - 5 + 55, y: +ey + 6 - 15 } );
119 |
120 | co_ords.push( { x: +ex + 5 + 5, y: +ey + 6 - 15 } );
121 | co_ords.push( { x: +ex + 7 + 1, y: +ey + 6 - 15 } );
122 | co_ords.push( { x: +ex - 9 + 1, y: +ey + 16 - 15 } );
123 | co_ords.push( { x: +ex - 3 + 5, y: +ey + 3 - 15 } );
124 | co_ords.push( { x: +ex - 5 + 5, y: +ey + 6 - 15 } );
125 |
126 |
127 | // for each co-ordinate construct a template path when combined giving a continent like structure
128 | d3.select("#earth")
129 | .selectAll("path")
130 | .data( co_ords )
131 | .enter() // we are adding the 'continent' paths newly
132 | .append("path")
133 | .attr("class", "continent")
134 | .attr("d", function(d) {
135 | // we have an object as data with x and y as co-ordinates
136 | var x = d.x, y = d.y;
137 |
138 | return "M "+x+" "+y+" c-3 -5 -1 -10 4 -10 6 0 11 5 11 10 0 6 -2 10 -4 10 -3 0 -8 -4 -11 -10z"
139 | });
140 |
141 | // earth day and night masks as semicircles
142 | // left semicircle is the night mask, right semicircle is day mask
143 | // they provide a transparent overlay with day & night colors over the earth circle to show day & night
144 |
145 | // calculate the earth mask co-ordinates for both night and day mask
146 | // night and day masks are almost same as they form left and right semicircles
147 | // only the sweep flag parameter for svg arc commands needs to be changed
148 |
149 | var em_x1 = ex, // start x for earth mask
150 | em_y1 = ey - esize, // start y
151 | em_x2 = ex, // end x
152 | em_y2 = ey + esize, // end y
153 | em_night = 1, // night
154 | em_day = 0; // day
155 |
156 |
157 | var night_mask = d3.select("#moon-viz")
158 | .append("path")
159 | // draw the left semicircle using SVG arc
160 | .attr("d", "M "+em_x1+" "+em_y1+" L "+em_x2+" "+em_y2+" A "+esize+" "+esize+" 0 0 "+em_night+" "+em_x1+" "+em_y1+"")
161 | .style("fill", "black")
162 | .style("fill-opacity", "0.1");
163 |
164 | var day_mask = d3.select("#moon-viz")
165 | .append("path")
166 | // draw the right semicircle using SVG arc
167 | .attr("d", "M "+em_x1+" "+em_y1+" L "+em_x2+" "+em_y2+" A "+esize+" "+esize+" 0 0 "+em_day+" "+em_x1+" "+em_y1+"")
168 | .style("fill", "#FFFF00")
169 | .style("fill-opacity", "0.64");
170 |
171 | // draw the moon path which is an ellipse
172 | var mp_rx = 250, // rx for moon path
173 | mp_ry = 150; // ry for moon path
174 |
175 |
176 | var moon_path = d3.select("#moon-viz")
177 | .select("g#moon-viz-grouping")
178 | .append("ellipse")
179 | .attr("cx", width/2)
180 | .attr("cy", height/2)
181 | .attr("rx", mp_rx)
182 | .attr("ry", mp_ry)
183 | .style("fill", "none")
184 | .style("stroke", "#dedede");
185 |
186 | // moon is a circle; calculate its dimensions
187 | var mx = width/2 + mp_rx, // x for moon
188 | my = height/2, // y for moon
189 | msize = 25; // size of moon
190 |
191 |
192 | var moon = d3.select("#moon-viz")
193 | .select("g#moon-viz-grouping")
194 | // add a 'g' elem for moon
195 | .append("g")
196 | .attr("id", "moon")
197 | .append("g")
198 | .append("circle")
199 | .attr("cx", mx)
200 | .attr("cy", my)
201 | .attr("r", msize)
202 | .style("fill", "white");
203 |
204 | // co-ordinates for the mask indicating the dark side of the moon (left semicircle)
205 | var mm_x1 = mx, // start x for moon mask
206 | mm_y1 = my - msize, // start y
207 | mm_x2 = mx, // end x
208 | mm_y2 = my + msize; // end y
209 |
210 | // draw a semicircle mask for moon to show the lighted half of the moon
211 | var moon_mask = d3.select("#moon-viz")
212 | .select("#moon")
213 | .append("path")
214 | // draw the left semicircle which is the dark side of the moon using SVG arc
215 | .attr("d", "M "+mm_x1+" "+mm_y1+" L "+mm_x2+" "+mm_y2+" A "+msize+" "+msize+" 0 0 1 "+mm_x1+" "+mm_y1+"")
216 | .style("fill", "black")
217 | .style("fill-opacity", "0.8");
218 |
219 | // append a semicircle to moon
220 | d3.select("#moon").select("g")
221 | .append("path")
222 | .attr("d", "M "+mm_x1+" "+mm_y1+" L "+mm_x2+" "+mm_y2+" A "+msize+" "+msize+" 0 0 1 "+mm_x1+" "+mm_y1+"")
223 | .style("fill", "none")
224 | .style("stroke", "#404040")
225 | .style("stroke-width", "2.5")
226 | .style("stroke-dasharray", "3, 3");
227 |
228 | var start = {
229 | moon: 180, // start in the full moon position; left end
230 | earth: 0
231 | }; // start positions
232 |
233 | // AXIS rotation speeds of moon and earth
234 | var speed = {};
235 | speed.moon = +0.4;
236 | // make earth rotation visible faster than the moon. actually earth is 29.5 times faster than moon in axis rotation;
237 | // but it is scaled down to 15 to make it visibly better to understand
238 | speed.earth = speed.moon * 15;
239 |
240 | // get a reference for 'updateMoonPosition' which animates moon's position in left and top right visual
241 | // Through closures, we will able to access all the variables and data from this scope.
242 | // This reference is later called outside of this scope for animating.
243 | moonViz.updateMoonPhaseView = updateMoonPosition;
244 |
245 | // updates the left main visual and top right visual
246 | function updateMoonPosition () {
247 |
248 | var moon = d3.select("#moon-viz").select("#moon");
249 |
250 | var angle = start.moon%360;
251 | var radian = (angle/360)*(2*Math.PI);
252 |
253 | // the basic ellipse co-ordinates is given by x*cos(t), y*sin(t) where x, y are ellipse x and y radii
254 |
255 | // if just the 'moon' circle element has to be moved, the following co-ordinates work, but
256 | //var x = (width/2) + mp_rx * Math.cos(radian);
257 | //var y = (height/2) - mp_ry * Math.sin(radian);
258 | //moon.attr("cx", x).attr("cy", y);
259 |
260 | // we are dealing with a 'g' element holding the moon. g element needs a translate position
261 | var x = mp_rx * Math.cos(radian) - (width/2 - mp_rx + 2*msize);
262 | var y = -mp_ry * Math.sin(radian);
263 |
264 | // moon is rotated around its orbit
265 | moon.attr("transform", "translate("+x+","+y+")");
266 |
267 | // angle to rotate the moon
268 | var to_rotate = start.moon%360;
269 |
270 | // the base co-ordinate to rotate with; it will fall in the co-ordinate (mp_rx, 0) in the right end of x-axis of ellipse
271 | var nx = +(width/2) + mp_rx,
272 | ny = +(height/2);
273 |
274 | // moon is rotated around its axis
275 | moon.select("g")
276 | .attr("transform", "rotate(-"+to_rotate+", "+nx+", "+ny+")");
277 |
278 | // 'fine' factor, controls the speed of moon revolution
279 | // Also this same angle is used for moon's rotation around its orbit and axis, thus simulating 'tidal locking'
280 | start.moon += speed.moon;
281 |
282 | // update the moon phase view in the sidebar
283 | var proxy_moon = {
284 | el: d3.select("#top-proxy-moon"),
285 | radius: 50,
286 | position: +d3.select("#top-moon").attr("cx")
287 | };
288 |
289 | // for the first 180 deg Moon is waxing, the next 180 deg Moon is waning.
290 | var proxy_pos = (angle - 180)/180 * ( 2*proxy_moon.radius ),
291 | ref_pos;
292 |
293 | if (proxy_pos < 0) {
294 | ref_pos = proxy_moon.position - 2*proxy_moon.radius;
295 | } else {
296 | ref_pos = proxy_moon.position + 2*proxy_moon.radius;
297 | }
298 |
299 | proxy_moon.el.attr("cx", ref_pos - proxy_pos);
300 |
301 | // update the phase timer; actual moon orbit time is 29.5 days; tweak that info to the timer
302 | var phase_time = (p_time = +Math.ceil(29.5 - ((360-angle)/360)*29.5)) == 30 ? 29.5 : p_time;
303 |
304 | d3.selectAll(".phase.timer")
305 | .text("Day " + phase_time);
306 |
307 | // rotate the earth around its axis;
308 |
309 | var to_rotate = start.earth%360;
310 |
311 | //rotate the earth slightly faster than the moon
312 | d3.select("#earth")
313 | .attr("transform", "rotate(-"+to_rotate+", "+ex+","+ey+" )");
314 |
315 |
316 | start.earth += speed.earth;
317 |
318 | }
319 |
320 | // finally draw the sun
321 | var sun = d3.select("#moon-viz")
322 | .append("ellipse")
323 | .attr("id", "sun")
324 | .attr("cx", width)
325 | .attr("cy", height/2)
326 | .attr("rx", 50)
327 | .attr("ry", height/2)
328 | .style("fill", "#FFDB00");
329 |
330 |
331 | } // end of drawMoonOrbit module
332 |
333 | // -------------------------------------------------------------------------
334 |
335 |
336 | // draw the alternate view, the narrow right visual.
337 | function drawAlternateView () {
338 |
339 | // alternate view has two parts divided equally
340 | // top part shows the Moon's shape during different phases
341 | // bottom part shows a high level overview of eclipses
342 |
343 | var width = 400, // width of this view is common
344 | height = 500; // each view will share half of this height
345 |
346 | // tracks the x,y co-ordinates of moon and earth shadow which are triangles
347 | // the co-ordinate we will need is (x3,y3) which is the end that will touch the 'line of nodes'
348 | var eclipse_points = {
349 |
350 | moon: {
351 | x1: 0, y1: 0,
352 | x2: 0, y2: 0,
353 | x3: 0, y3: 0
354 | },
355 |
356 | earth: {
357 | x1: 0, y1: 0,
358 | x2: 0, y2: 0,
359 | x3: 0, y3: 0
360 | }
361 |
362 | };
363 |
364 | var top_view = d3.select("#alternate-view")
365 | .append("g")
366 | .attr("id", "top-view");
367 |
368 | // draw the 'horizontal' seperation line
369 | d3.select("#alternate-view")
370 | .append("line")
371 | .attr("x1", 0).attr("y1", height/2)
372 | .attr("x2", width).attr("y2", height/2)
373 | .style("stroke", "grey");
374 |
375 | // 'vertical' seperation line - line of nodes
376 | var lon = d3.select("#alternate-view")
377 | .append("line")
378 | .attr("x1", width/2).attr("y1", height/2)
379 | .attr("x2", width/2).attr("y2", height)
380 | .style("stroke", "tomato");
381 |
382 | // we have two sets of moons in this view; this is the top moon
383 |
384 | var topMoon = {
385 |
386 | // size of the moon
387 | size: 50,
388 |
389 | // main visible moon
390 | main: '',
391 |
392 | // proxy moon which overlaps the main moon to give the phase view
393 | proxy: ''
394 |
395 | };
396 |
397 | // this is the main visible moon
398 | topMoon.main = top_view.append("circle")
399 | .attr("id", "top-moon")
400 | .attr("cx", width/2 )
401 | .attr("cy", 0.5*(height/2) ) // middle of the upper half
402 | .attr("r", topMoon.size)
403 | .style("fill", "white");
404 |
405 |
406 |
407 | // proxy moon -> this will overlap the main moon to give the Moon phase visuals
408 | // inital proxy moon position will be to the right of the moon, revealing it completely
409 |
410 | var proxy_pos = 2*topMoon.size;
411 | var initial_pos = width/2;
412 |
413 | topMoon.proxy = top_view.append("circle")
414 | .attr("id", "top-proxy-moon")
415 | .attr("cx", initial_pos + proxy_pos ) // initial position will not hide the moon
416 | .attr("cy", 0.5*(height/2) ) // middle of the bottom half
417 | .attr("r", topMoon.size)
418 | .style("fill", "black");
419 |
420 | // ----------------------------------------------------
421 | // bottom half contains the side view with earth, moon and sun
422 |
423 | var bottom_view = d3.select("#alternate-view")
424 | .append("g")
425 | .attr("id", "bottom-view");
426 |
427 | // the centre reference plane
428 | var bottom_ref_line = bottom_view.append("line")
429 | .attr("x1", 0).attr("y1", 1.5*(height/2))
430 | .attr("x2", width).attr("y2", 1.5*(height/2)) // middle of bottom half
431 | .style("stroke", "grey");
432 |
433 | // add a 'g' element to group earth and moon components
434 | bottom_view.append("g")
435 | .attr("id", "earth-moon-plane");
436 |
437 | // contains earth and its shadow
438 | bottom_view.select("#earth-moon-plane")
439 | .append("g")
440 | .attr("id", "earth-plane");
441 |
442 | // contains moon, its shadow and its orbit
443 | bottom_view.select("#earth-moon-plane")
444 | .append("g")
445 | .attr("id", "moon-plane");
446 |
447 | // bottom moon orbit;
448 | // an ellipse which will vary in its x radius to simulate the oscillation of moon's ecliptic plane
449 |
450 | var earth = {
451 |
452 | size: 10,
453 |
454 | orbit: {
455 | x: width/3,
456 | y: 80
457 | },
458 |
459 | angle: 180, // start angle
460 |
461 | co_ords: {},
462 |
463 | el: '',
464 |
465 | shadow: 43
466 |
467 | };
468 |
469 | earth.co_ords.x = width/2,
470 | earth.co_ords.y = 1.5*(height/2) - earth.orbit.y;
471 |
472 | var earth_orbit = bottom_view.append("ellipse")
473 | .attr("cx", width/2)
474 | .attr("cy", 1.5*(height/2))
475 | .attr("rx", earth.orbit.x)
476 | .attr("ry", earth.orbit.y)
477 | .style("fill", "none")
478 | .style("stroke", "grey");
479 |
480 | earth.el = bottom_view.select("#earth-plane")
481 | .append("circle")
482 | .attr("id", "bottom-earth")
483 | .attr("class", "bottom earth")
484 | .attr("cx", earth.co_ords.x)
485 | .attr("cy", earth.co_ords.y)
486 | .attr("r", earth.size)
487 | .style("fill", "steelblue");
488 |
489 | // this is the bottom moon in the eclipse view
490 | var moon = {
491 |
492 | size: 5,
493 |
494 | orbit: {
495 | x: 35,
496 | y: 20
497 | },
498 |
499 | angle: 180,
500 |
501 | co_ords: {},
502 |
503 | el: '',
504 |
505 | shadow: 13,
506 |
507 | // orbital speed of the moon
508 | speed: 3
509 |
510 | };
511 |
512 | var moon_orbit = bottom_view.select("#moon-plane")
513 | .append("ellipse")
514 | .attr("rx", moon.orbit.x)
515 | .attr("ry", moon.orbit.y)
516 | .style("fill", "none")
517 | .style("stroke", "grey")
518 | .attr("transform", "rotate(-15)");
519 |
520 | // draw two points and a connection line to indicate full moon and new moon positions in the moon orbit
521 | bottom_view.select("#moon-plane")
522 | .append("g")
523 | .attr("id", "bottom-moon-orbit-points")
524 | .attr("transform", "rotate(-15)");
525 |
526 | bottom_view.select("#moon-plane").select("#bottom-moon-orbit-points")
527 | .append("line")
528 | .attr("x1", -moon.orbit.x).attr("y1", moon.orbit.y/2 - 2*moon.size)
529 | .attr("x2", moon.orbit.x).attr("y2", moon.orbit.y/2 - 2*moon.size)
530 | .style("stroke", "#505050");
531 |
532 | moon.el = bottom_view.select("#moon-plane")
533 | .append("circle")
534 | .attr("cx", moon.orbit.x)
535 | .attr("cy", 0)
536 | .attr("r", moon.size)
537 | .style("fill", "silver");
538 |
539 | var sun = bottom_view.append("circle")
540 | .attr("id", "bottom-sun")
541 | .attr("class", "bottom sun")
542 | .attr("cx", width/2)
543 | .attr("cy", 1.5*(height/2))
544 | .attr("r", 30)
545 | .style("fill", "yellow")
546 | .style("fill-opacity", 1);
547 |
548 | // get a reference for 'revolveEarth' which animates bottom right visual
549 | // Through closures, we will able to access all the variables and data from this scope.
550 | // This function reference is later called outside of this scope for animating.
551 | moonViz.updateEclipseView = revolveEarth;
552 |
553 | function revolveEarth () {
554 |
555 | var angle = earth.angle%360;
556 | var radian = (angle/360)*(2*Math.PI);
557 |
558 | // redefine height for the bottom view part
559 | var b_height = 1.5*(height/2);
560 |
561 | // the basic ellipse co-ordinates is given by x*cos(t), y*sin(t) where x, y are ellipse x and y radii
562 |
563 | // co-ordinates to move the earth around its orbit
564 | var x = (width/2) + earth.orbit.x * Math.cos(radian);
565 | var y = b_height - earth.orbit.y * Math.sin(radian);
566 |
567 | // rotate the earth
568 | earth.el.attr("cx", x).attr("cy", y).attr("transform", "rotate("+earth.angle+", "+x+", "+y+")");
569 |
570 | // actual moon orbit tilt is 5.1 deg, but to visibly show the tilt we are using 15 deg
571 | d3.select("#moon-plane").attr("transform", "rotate(-0, "+x+", "+y+") translate("+x+","+y+")");
572 |
573 | var shadow_angle = +270 - earth.angle;
574 |
575 | // plot the shadow points
576 | eclipse_points.earth = {
577 | // absolute position
578 | x1 : x - earth.size,
579 | y1 : y,
580 |
581 | // relative position
582 | x2 : 2*earth.size,
583 | y2 : 0,
584 |
585 | // relative position
586 | x3 : -earth.size,
587 | y3 : earth.shadow
588 | };
589 |
590 | // draw the earth shadow;
591 | var earth_shadow = d3.select("#earth-shadow")
592 | .attr("d", function(){
593 |
594 | var x1, y1, x2, y2, x3, y3;
595 |
596 | // absolute position
597 | x1 = eclipse_points.earth.x1;
598 | y1 = eclipse_points.earth.y1;
599 |
600 | // relative position
601 | x2 = eclipse_points.earth.x2;
602 | y2 = eclipse_points.earth.y2;
603 |
604 | // relative position
605 | x3 = eclipse_points.earth.x3;
606 | y3 = eclipse_points.earth.y3;
607 |
608 | var path = "M "+x1+" "+y1+" l "+x2+" "+y2+" l "+x3+" "+y3+" "+" L "+x1+" "+y1+" ";
609 |
610 | return path;
611 | })
612 | .attr("transform", "rotate("+shadow_angle+", "+x+", "+y+")")
613 | .style("fill", "#404040");
614 |
615 | earth.angle += moon.speed/12.41; // one orbital rotation of earth is 12 times that of a moon
616 |
617 | // revolve the moon around the earth too when earth is revolving around the sun
618 | revolveMoon();
619 |
620 | // update the timer in the eclipse view; normalization to start the month count from 180 deg
621 | var eclipse_time = (e_time = +Math.ceil(((angle-180)/360)*12)) <= 0 ? (12 + e_time) : e_time;
622 |
623 | d3.select("#eclipse-timer")
624 | .text("Month " + eclipse_time);
625 |
626 | } // end of revolveEarth module
627 |
628 | function revolveMoon () {
629 |
630 | var angle = moon.angle%360;
631 | var radian = (angle/360)*(2*Math.PI);
632 |
633 | // the basic ellipse co-ordinates is given by x*cos(t), y*sin(t) where x, y are ellipse x and y radii
634 | // here the moon position is relative to earth; so just the ellipse co-ordinates will work
635 | var x = +moon.orbit.x * Math.cos(radian);
636 | var y = -moon.orbit.y * Math.sin(radian);
637 |
638 | moon.el.attr("cx", x).attr("cy", y);
639 |
640 | var shadow_angle = Math.ceil(+270 - (earth.angle%360));
641 |
642 | var earth_x = +earth.el.attr("cx");
643 | var earth_y = +earth.el.attr("cy");
644 |
645 | var moon_x = +moon.el.attr("cx");
646 | var moon_y = +moon.el.attr("cy");
647 |
648 | var shadow_x = +x + earth_x;
649 | var shadow_y = +y + earth_y;
650 |
651 | // plot the moon shadow points
652 | eclipse_points.moon = {
653 | // absolute position
654 | x1 : shadow_x - moon.size,
655 | y1 : shadow_y,
656 |
657 | // relative position
658 | x2 : 2*moon.size,
659 | y2 : 0,
660 |
661 | // relative position
662 | x3 : -moon.size,
663 | y3 : moon.shadow
664 | };
665 |
666 | // draw the earth shadow;
667 | var moon_shadow = d3.select("#moon-shadow")
668 | .attr("d", function(){
669 |
670 | var x1, y1, x2, y2, x3, y3;
671 |
672 | // absolute position
673 | x1 = eclipse_points.moon.x1;
674 | y1 = eclipse_points.moon.y1;
675 |
676 | // relative position
677 | x2 = eclipse_points.moon.x2;
678 | y2 = eclipse_points.moon.y2;
679 |
680 | // relative position
681 | x3 = eclipse_points.moon.x3;
682 | y3 = eclipse_points.moon.y3;
683 |
684 | var path = "M "+x1+" "+y1+" l "+x2+" "+y2+" l "+x3+" "+y3+" "+" L "+x1+" "+y1+" ";
685 |
686 | // moon passes through the line of nodes
687 | if (shadow_angle == 0 || shadow_angle == 180) {
688 |
689 | // get the ceiled co-ordinates at line of nodes
690 | var ceiled = {
691 | moon: Math.ceil(x1 - x3),
692 | earth: Math.ceil(eclipse_points.earth.x1 - eclipse_points.earth.x3)
693 | } ;
694 |
695 | if (ceiled.moon >= (ceiled.earth - moon.size) && ceiled.moon <= (ceiled.earth + moon.size) ) {
696 | //console.log("eclipse point? " + new Date());
697 | // make the line of nodes as a visible green line
698 | lon.style("stroke", "green").style("stroke-width", "3")
699 | .transition().style("stroke", "tomato").style("stroke-width", "1").duration(4000);
700 | }
701 |
702 | }
703 |
704 | return path;
705 | })
706 | .attr("transform", "rotate("+shadow_angle+", "+shadow_x+", "+shadow_y+")")
707 | .style("fill", "#404040");
708 |
709 | moon.angle += moon.speed;
710 |
711 | } // end of revolveMoon module
712 |
713 | } // end of drawAlternateView module
714 |
715 | // ---------------------------------------
716 |
717 | // for every few seconds after the first time removes and adds random sets of stars
718 | function starShow () {
719 |
720 | // an array that contains the co-ordinates of the stars
721 | var starData = moonViz.stars;
722 | // the holder which will contain stars
723 | var canvas = d3.select("#starCanvas");
724 |
725 | // dimensions of the canvas
726 | var width = 880,
727 | height = 500;
728 |
729 | if ( starData.length == 0 ) {
730 | // this is the first time; there are no stars; add them
731 | var count = 0,
732 | limit = 150; // total stars to be present
733 |
734 | // add new stars
735 | while ( count++ < limit ) {
736 |
737 | starData.push({
738 | x: Math.ceil( Math.random()*width ),
739 | y: Math.ceil( Math.random()*height ),
740 | // one third of the stars is shown dim
741 | class: (Math.ceil( Math.random()*3 ))%3 == 0 ? 'star dim' : 'star'
742 | });
743 | }
744 |
745 | var new_stars = canvas.selectAll("circle") // circle as star in svg
746 | .data( starData )
747 | .enter() // stars are newly added for the first time
748 | .append("circle")
749 | .attr("class", function (d) { return d.class; } )
750 | .attr("cx", function (d) { return d.x; } )
751 | .attr("cy", function (d) { return d.y; } )
752 | .attr("r", 1);
753 | } else {
754 |
755 | // create new stars
756 | count = 0;
757 | limit = 50;
758 |
759 | starData = starData.slice( 0, starData.length - limit );
760 |
761 | // there are stars already; destroy and create 10 stars
762 | var old_stars = canvas.selectAll("circle") // circle as star in svg
763 | .data( starData ) // remove first 10 stars
764 | .exit()
765 | .attr("class", "star old")
766 | .transition()
767 | .duration(2000)
768 | .remove();
769 | // add new stars
770 | while ( count++ < limit ) {
771 |
772 | starData.push({
773 | x: Math.ceil( Math.random()*width ),
774 | y: Math.ceil( Math.random()*height ),
775 | // one third of the stars to be dim
776 | class: (Math.ceil( Math.random()*3 ))%3 == 0 ? 'star dim' : 'star'
777 | });
778 | }
779 |
780 | new_stars = canvas.selectAll("circle") // circle as star in svg
781 | .data( starData )
782 | .enter() // stars are newly added
783 | .append("circle")
784 | .attr("class", function (d) { return d.class; } )
785 | .attr("cx", function (d) { return d.x; } )
786 | .attr("cy", function (d) { return d.y; } )
787 | .attr("r", 1)
788 | .transition()
789 | .duration(2000)
790 | .attr("class", "star new")
791 | .transition()
792 | .duration(2000)
793 | .attr("class", function (d) { return d.class; } );
794 |
795 | }
796 |
797 | } // end of starShow module
798 |
799 | // ***************************************************************************************************************************
800 |
801 | } )();
802 |
803 | // requestAnimationFrame polyfill for browsers that doesn't support
804 | // ref: https://gist.github.com/paulirish/1579671
805 | (function() {
806 |
807 | // requestAnimationFrame polyfill by Erik Möller. fixes from Paul Irish and Tino Zijdel
808 | // MIT license
809 |
810 | var lastTime = 0;
811 | var vendors = ['ms', 'moz', 'webkit', 'o'];
812 | for(var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
813 | window.requestAnimationFrame = window[vendors[x]+'RequestAnimationFrame'];
814 | window.cancelAnimationFrame = window[vendors[x]+'CancelAnimationFrame']
815 | || window[vendors[x]+'CancelRequestAnimationFrame'];
816 | }
817 |
818 | if (!window.requestAnimationFrame)
819 | window.requestAnimationFrame = function(callback, element) {
820 | var currTime = new Date().getTime();
821 | var timeToCall = Math.max(0, 16 - (currTime - lastTime));
822 | var id = window.setTimeout(function() { callback(currTime + timeToCall); },
823 | timeToCall);
824 | lastTime = currTime + timeToCall;
825 | return id;
826 | };
827 |
828 | if (!window.cancelAnimationFrame)
829 | window.cancelAnimationFrame = function(id) {
830 | clearTimeout(id);
831 | };
832 | }());
833 |
--------------------------------------------------------------------------------
/js/lib/d3.min.js:
--------------------------------------------------------------------------------
1 | !function(){function n(n){return n&&(n.ownerDocument||n.document).documentElement}function t(n){return n&&n.ownerDocument?n.ownerDocument.defaultView:n}function e(n,t){return t>n?-1:n>t?1:n>=t?0:0/0}function r(n){return null===n?0/0:+n}function u(n){return!isNaN(n)}function i(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)<0?r=i+1:u=i}return r},right:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)>0?u=i:r=i+1}return r}}}function o(n){return n.length}function a(n){for(var t=1;n*t%1;)t*=10;return t}function c(n,t){for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}function l(){this._=Object.create(null)}function s(n){return(n+="")===pa||n[0]===va?va+n:n}function f(n){return(n+="")[0]===va?n.slice(1):n}function h(n){return s(n)in this._}function g(n){return(n=s(n))in this._&&delete this._[n]}function p(){var n=[];for(var t in this._)n.push(f(t));return n}function v(){var n=0;for(var t in this._)++n;return n}function d(){for(var n in this._)return!1;return!0}function m(){this._=Object.create(null)}function y(n){return n}function M(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function x(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.slice(1);for(var e=0,r=da.length;r>e;++e){var u=da[e]+t;if(u in n)return u}}function b(){}function _(){}function w(n){function t(){for(var t,r=e,u=-1,i=r.length;++ue;e++)for(var u,i=n[e],o=0,a=i.length;a>o;o++)(u=i[o])&&t(u,o,e);return n}function Z(n){return ya(n,Sa),n}function V(n){var t,e;return function(r,u,i){var o,a=n[i].update,c=a.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(o=a[t])&&++t0&&(n=n.slice(0,a));var l=ka.get(n);return l&&(n=l,c=B),a?t?u:r:t?b:i}function $(n,t){return function(e){var r=ta.event;ta.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{ta.event=r}}}function B(n,t){var e=$(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function W(e){var r=".dragsuppress-"+ ++Aa,u="click"+r,i=ta.select(t(e)).on("touchmove"+r,S).on("dragstart"+r,S).on("selectstart"+r,S);if(null==Ea&&(Ea="onselectstart"in e?!1:x(e.style,"userSelect")),Ea){var o=n(e).style,a=o[Ea];o[Ea]="none"}return function(n){if(i.on(r,null),Ea&&(o[Ea]=a),n){var t=function(){i.on(u,null)};i.on(u,function(){S(),t()},!0),setTimeout(t,0)}}}function J(n,e){e.changedTouches&&(e=e.changedTouches[0]);var r=n.ownerSVGElement||n;if(r.createSVGPoint){var u=r.createSVGPoint();if(0>Na){var i=t(n);if(i.scrollX||i.scrollY){r=ta.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var o=r[0][0].getScreenCTM();Na=!(o.f||o.e),r.remove()}}return Na?(u.x=e.pageX,u.y=e.pageY):(u.x=e.clientX,u.y=e.clientY),u=u.matrixTransform(n.getScreenCTM().inverse()),[u.x,u.y]}var a=n.getBoundingClientRect();return[e.clientX-a.left-n.clientLeft,e.clientY-a.top-n.clientTop]}function G(){return ta.event.changedTouches[0].identifier}function K(n){return n>0?1:0>n?-1:0}function Q(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function nt(n){return n>1?0:-1>n?qa:Math.acos(n)}function tt(n){return n>1?Ra:-1>n?-Ra:Math.asin(n)}function et(n){return((n=Math.exp(n))-1/n)/2}function rt(n){return((n=Math.exp(n))+1/n)/2}function ut(n){return((n=Math.exp(2*n))-1)/(n+1)}function it(n){return(n=Math.sin(n/2))*n}function ot(){}function at(n,t,e){return this instanceof at?(this.h=+n,this.s=+t,void(this.l=+e)):arguments.length<2?n instanceof at?new at(n.h,n.s,n.l):bt(""+n,_t,at):new at(n,t,e)}function ct(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(o-i)*n/60:180>n?o:240>n?i+(o-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,o;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,o=.5>=e?e*(1+t):e+t-e*t,i=2*e-o,new mt(u(n+120),u(n),u(n-120))}function lt(n,t,e){return this instanceof lt?(this.h=+n,this.c=+t,void(this.l=+e)):arguments.length<2?n instanceof lt?new lt(n.h,n.c,n.l):n instanceof ft?gt(n.l,n.a,n.b):gt((n=wt((n=ta.rgb(n)).r,n.g,n.b)).l,n.a,n.b):new lt(n,t,e)}function st(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),new ft(e,Math.cos(n*=Da)*t,Math.sin(n)*t)}function ft(n,t,e){return this instanceof ft?(this.l=+n,this.a=+t,void(this.b=+e)):arguments.length<2?n instanceof ft?new ft(n.l,n.a,n.b):n instanceof lt?st(n.h,n.c,n.l):wt((n=mt(n)).r,n.g,n.b):new ft(n,t,e)}function ht(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=pt(u)*Xa,r=pt(r)*$a,i=pt(i)*Ba,new mt(dt(3.2404542*u-1.5371385*r-.4985314*i),dt(-.969266*u+1.8760108*r+.041556*i),dt(.0556434*u-.2040259*r+1.0572252*i))}function gt(n,t,e){return n>0?new lt(Math.atan2(e,t)*Pa,Math.sqrt(t*t+e*e),n):new lt(0/0,0/0,n)}function pt(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function vt(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function dt(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function mt(n,t,e){return this instanceof mt?(this.r=~~n,this.g=~~t,void(this.b=~~e)):arguments.length<2?n instanceof mt?new mt(n.r,n.g,n.b):bt(""+n,mt,ct):new mt(n,t,e)}function yt(n){return new mt(n>>16,n>>8&255,255&n)}function Mt(n){return yt(n)+""}function xt(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function bt(n,t,e){var r,u,i,o=0,a=0,c=0;if(r=/([a-z]+)\((.*)\)/i.exec(n))switch(u=r[2].split(","),r[1]){case"hsl":return e(parseFloat(u[0]),parseFloat(u[1])/100,parseFloat(u[2])/100);case"rgb":return t(kt(u[0]),kt(u[1]),kt(u[2]))}return(i=Ga.get(n.toLowerCase()))?t(i.r,i.g,i.b):(null==n||"#"!==n.charAt(0)||isNaN(i=parseInt(n.slice(1),16))||(4===n.length?(o=(3840&i)>>4,o=o>>4|o,a=240&i,a=a>>4|a,c=15&i,c=c<<4|c):7===n.length&&(o=(16711680&i)>>16,a=(65280&i)>>8,c=255&i)),t(o,a,c))}function _t(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),o=Math.max(n,t,e),a=o-i,c=(o+i)/2;return a?(u=.5>c?a/(o+i):a/(2-o-i),r=n==o?(t-e)/a+(e>t?6:0):t==o?(e-n)/a+2:(n-t)/a+4,r*=60):(r=0/0,u=c>0&&1>c?0:r),new at(r,u,c)}function wt(n,t,e){n=St(n),t=St(t),e=St(e);var r=vt((.4124564*n+.3575761*t+.1804375*e)/Xa),u=vt((.2126729*n+.7151522*t+.072175*e)/$a),i=vt((.0193339*n+.119192*t+.9503041*e)/Ba);return ft(116*u-16,500*(r-u),200*(u-i))}function St(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function kt(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function Et(n){return"function"==typeof n?n:function(){return n}}function At(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),Nt(t,e,n,r)}}function Nt(n,t,e,r){function u(){var n,t=c.status;if(!t&&zt(c)||t>=200&&300>t||304===t){try{n=e.call(i,c)}catch(r){return void o.error.call(i,r)}o.load.call(i,n)}else o.error.call(i,c)}var i={},o=ta.dispatch("beforesend","progress","load","error"),a={},c=new XMLHttpRequest,l=null;return!this.XDomainRequest||"withCredentials"in c||!/^(http(s)?:)?\/\//.test(n)||(c=new XDomainRequest),"onload"in c?c.onload=c.onerror=u:c.onreadystatechange=function(){c.readyState>3&&u()},c.onprogress=function(n){var t=ta.event;ta.event=n;try{o.progress.call(i,c)}finally{ta.event=t}},i.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?a[n]:(null==t?delete a[n]:a[n]=t+"",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",i):t},i.responseType=function(n){return arguments.length?(l=n,i):l},i.response=function(n){return e=n,i},["get","post"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(ra(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),c.open(e,n,!0),null==t||"accept"in a||(a.accept=t+",*/*"),c.setRequestHeader)for(var s in a)c.setRequestHeader(s,a[s]);return null!=t&&c.overrideMimeType&&c.overrideMimeType(t),null!=l&&(c.responseType=l),null!=u&&i.on("error",u).on("load",function(n){u(null,n)}),o.beforesend.call(i,c),c.send(null==r?null:r),i},i.abort=function(){return c.abort(),i},ta.rebind(i,o,"on"),null==r?i:i.get(Ct(r))}function Ct(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function zt(n){var t=n.responseType;return t&&"text"!==t?n.response:n.responseText}function qt(){var n=Lt(),t=Tt()-n;t>24?(isFinite(t)&&(clearTimeout(tc),tc=setTimeout(qt,t)),nc=0):(nc=1,rc(qt))}function Lt(){var n=Date.now();for(ec=Ka;ec;)n>=ec.t&&(ec.f=ec.c(n-ec.t)),ec=ec.n;return n}function Tt(){for(var n,t=Ka,e=1/0;t;)t.f?t=n?n.n=t.n:Ka=t.n:(t.t8?function(n){return n/e}:function(n){return n*e},symbol:n}}function Pt(n){var t=n.decimal,e=n.thousands,r=n.grouping,u=n.currency,i=r&&e?function(n,t){for(var u=n.length,i=[],o=0,a=r[0],c=0;u>0&&a>0&&(c+a+1>t&&(a=Math.max(1,t-c)),i.push(n.substring(u-=a,u+a)),!((c+=a+1)>t));)a=r[o=(o+1)%r.length];return i.reverse().join(e)}:y;return function(n){var e=ic.exec(n),r=e[1]||" ",o=e[2]||">",a=e[3]||"-",c=e[4]||"",l=e[5],s=+e[6],f=e[7],h=e[8],g=e[9],p=1,v="",d="",m=!1,y=!0;switch(h&&(h=+h.substring(1)),(l||"0"===r&&"="===o)&&(l=r="0",o="="),g){case"n":f=!0,g="g";break;case"%":p=100,d="%",g="f";break;case"p":p=100,d="%",g="r";break;case"b":case"o":case"x":case"X":"#"===c&&(v="0"+g.toLowerCase());case"c":y=!1;case"d":m=!0,h=0;break;case"s":p=-1,g="r"}"$"===c&&(v=u[0],d=u[1]),"r"!=g||h||(g="g"),null!=h&&("g"==g?h=Math.max(1,Math.min(21,h)):("e"==g||"f"==g)&&(h=Math.max(0,Math.min(20,h)))),g=oc.get(g)||Ut;var M=l&&f;return function(n){var e=d;if(m&&n%1)return"";var u=0>n||0===n&&0>1/n?(n=-n,"-"):"-"===a?"":a;if(0>p){var c=ta.formatPrefix(n,h);n=c.scale(n),e=c.symbol+d}else n*=p;n=g(n,h);var x,b,_=n.lastIndexOf(".");if(0>_){var w=y?n.lastIndexOf("e"):-1;0>w?(x=n,b=""):(x=n.substring(0,w),b=n.substring(w))}else x=n.substring(0,_),b=t+n.substring(_+1);!l&&f&&(x=i(x,1/0));var S=v.length+x.length+b.length+(M?0:u.length),k=s>S?new Array(S=s-S+1).join(r):"";return M&&(x=i(k+x,k.length?s-b.length:1/0)),u+=v,n=x+b,("<"===o?u+n+k:">"===o?k+u+n:"^"===o?k.substring(0,S>>=1)+u+n+k.substring(S):u+(M?n:k+n))+e}}}function Ut(n){return n+""}function jt(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function Ft(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new cc(e-1)),1),e}function i(n,e){return t(n=new cc(+n),e),n}function o(n,r,i){var o=u(n),a=[];if(i>1)for(;r>o;)e(o)%i||a.push(new Date(+o)),t(o,1);else for(;r>o;)a.push(new Date(+o)),t(o,1);return a}function a(n,t,e){try{cc=jt;var r=new jt;return r._=n,o(r,t,e)}finally{cc=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=o;var c=n.utc=Ht(n);return c.floor=c,c.round=Ht(r),c.ceil=Ht(u),c.offset=Ht(i),c.range=a,n}function Ht(n){return function(t,e){try{cc=jt;var r=new jt;return r._=t,n(r,e)._}finally{cc=Date}}}function Ot(n){function t(n){function t(t){for(var e,u,i,o=[],a=-1,c=0;++aa;){if(r>=l)return-1;if(u=t.charCodeAt(a++),37===u){if(o=t.charAt(a++),i=C[o in sc?t.charAt(a++):o],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){_.lastIndex=0;var r=_.exec(t.slice(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){x.lastIndex=0;var r=x.exec(t.slice(e));return r?(n.w=b.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){E.lastIndex=0;var r=E.exec(t.slice(e));return r?(n.m=A.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,e){S.lastIndex=0;var r=S.exec(t.slice(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,r){return e(n,N.c.toString(),t,r)}function c(n,t,r){return e(n,N.x.toString(),t,r)}function l(n,t,r){return e(n,N.X.toString(),t,r)}function s(n,t,e){var r=M.get(t.slice(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var f=n.dateTime,h=n.date,g=n.time,p=n.periods,v=n.days,d=n.shortDays,m=n.months,y=n.shortMonths;t.utc=function(n){function e(n){try{cc=jt;var t=new cc;return t._=n,r(t)}finally{cc=Date}}var r=t(n);return e.parse=function(n){try{cc=jt;var t=r.parse(n);return t&&t._}finally{cc=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ae;var M=ta.map(),x=Yt(v),b=Zt(v),_=Yt(d),w=Zt(d),S=Yt(m),k=Zt(m),E=Yt(y),A=Zt(y);p.forEach(function(n,t){M.set(n.toLowerCase(),t)});var N={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return y[n.getMonth()]},B:function(n){return m[n.getMonth()]},c:t(f),d:function(n,t){return It(n.getDate(),t,2)},e:function(n,t){return It(n.getDate(),t,2)},H:function(n,t){return It(n.getHours(),t,2)},I:function(n,t){return It(n.getHours()%12||12,t,2)},j:function(n,t){return It(1+ac.dayOfYear(n),t,3)},L:function(n,t){return It(n.getMilliseconds(),t,3)},m:function(n,t){return It(n.getMonth()+1,t,2)},M:function(n,t){return It(n.getMinutes(),t,2)},p:function(n){return p[+(n.getHours()>=12)]},S:function(n,t){return It(n.getSeconds(),t,2)},U:function(n,t){return It(ac.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return It(ac.mondayOfYear(n),t,2)},x:t(h),X:t(g),y:function(n,t){return It(n.getFullYear()%100,t,2)},Y:function(n,t){return It(n.getFullYear()%1e4,t,4)},Z:ie,"%":function(){return"%"}},C={a:r,A:u,b:i,B:o,c:a,d:Qt,e:Qt,H:te,I:te,j:ne,L:ue,m:Kt,M:ee,p:s,S:re,U:Xt,w:Vt,W:$t,x:c,X:l,y:Wt,Y:Bt,Z:Jt,"%":oe};return t}function It(n,t,e){var r=0>n?"-":"",u=(r?-n:n)+"",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function Yt(n){return new RegExp("^(?:"+n.map(ta.requote).join("|")+")","i")}function Zt(n){for(var t=new l,e=-1,r=n.length;++e68?1900:2e3)}function Kt(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function Qt(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function ne(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function te(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function ee(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function re(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function ue(n,t,e){fc.lastIndex=0;var r=fc.exec(t.slice(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function ie(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=ga(t)/60|0,u=ga(t)%60;return e+It(r,"0",2)+It(u,"0",2)}function oe(n,t,e){hc.lastIndex=0;var r=hc.exec(t.slice(e,e+1));return r?e+r[0].length:-1}function ae(n){for(var t=n.length,e=-1;++e=0?1:-1,a=o*e,c=Math.cos(t),l=Math.sin(t),s=i*l,f=u*c+s*Math.cos(a),h=s*o*Math.sin(a);yc.add(Math.atan2(h,f)),r=n,u=c,i=l}var t,e,r,u,i;Mc.point=function(o,a){Mc.point=n,r=(t=o)*Da,u=Math.cos(a=(e=a)*Da/2+qa/4),i=Math.sin(a)},Mc.lineEnd=function(){n(t,e)}}function pe(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function ve(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function de(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function me(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function ye(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function Me(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function xe(n){return[Math.atan2(n[1],n[0]),tt(n[2])]}function be(n,t){return ga(n[0]-t[0])a;++a)u.point((e=n[a])[0],e[1]);return void u.lineEnd()}var c=new qe(e,n,null,!0),l=new qe(e,null,c,!1);c.o=l,i.push(c),o.push(l),c=new qe(r,n,null,!1),l=new qe(r,null,c,!0),c.o=l,i.push(c),o.push(l)}}),o.sort(t),ze(i),ze(o),i.length){for(var a=0,c=e,l=o.length;l>a;++a)o[a].e=c=!c;for(var s,f,h=i[0];;){for(var g=h,p=!0;g.v;)if((g=g.n)===h)return;s=g.z,u.lineStart();do{if(g.v=g.o.v=!0,g.e){if(p)for(var a=0,l=s.length;l>a;++a)u.point((f=s[a])[0],f[1]);else r(g.x,g.n.x,1,u);g=g.n}else{if(p){s=g.p.z;for(var a=s.length-1;a>=0;--a)u.point((f=s[a])[0],f[1])}else r(g.x,g.p.x,-1,u);g=g.p}g=g.o,s=g.z,p=!p}while(!g.v);u.lineEnd()}}}function ze(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r0){for(b||(i.polygonStart(),b=!0),i.lineStart();++o1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Te))}var g,p,v,d=t(i),m=u.invert(r[0],r[1]),y={point:o,lineStart:c,lineEnd:l,polygonStart:function(){y.point=s,y.lineStart=f,y.lineEnd=h,g=[],p=[]},polygonEnd:function(){y.point=o,y.lineStart=c,y.lineEnd=l,g=ta.merge(g);var n=Fe(m,p);g.length?(b||(i.polygonStart(),b=!0),Ce(g,De,n,e,i)):n&&(b||(i.polygonStart(),b=!0),i.lineStart(),e(null,null,1,i),i.lineEnd()),b&&(i.polygonEnd(),b=!1),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},M=Re(),x=t(M),b=!1;return y}}function Te(n){return n.length>1}function Re(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:b,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function De(n,t){return((n=n.x)[0]<0?n[1]-Ra-Ca:Ra-n[1])-((t=t.x)[0]<0?t[1]-Ra-Ca:Ra-t[1])}function Pe(n){var t,e=0/0,r=0/0,u=0/0;return{lineStart:function(){n.lineStart(),t=1},point:function(i,o){var a=i>0?qa:-qa,c=ga(i-e);ga(c-qa)0?Ra:-Ra),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(a,r),n.point(i,r),t=0):u!==a&&c>=qa&&(ga(e-u)Ca?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*o)):(t+r)/2}function je(n,t,e,r){var u;if(null==n)u=e*Ra,r.point(-qa,u),r.point(0,u),r.point(qa,u),r.point(qa,0),r.point(qa,-u),r.point(0,-u),r.point(-qa,-u),r.point(-qa,0),r.point(-qa,u);else if(ga(n[0]-t[0])>Ca){var i=n[0]a;++a){var l=t[a],s=l.length;if(s)for(var f=l[0],h=f[0],g=f[1]/2+qa/4,p=Math.sin(g),v=Math.cos(g),d=1;;){d===s&&(d=0),n=l[d];var m=n[0],y=n[1]/2+qa/4,M=Math.sin(y),x=Math.cos(y),b=m-h,_=b>=0?1:-1,w=_*b,S=w>qa,k=p*M;if(yc.add(Math.atan2(k*_*Math.sin(w),v*x+k*Math.cos(w))),i+=S?b+_*La:b,S^h>=e^m>=e){var E=de(pe(f),pe(n));Me(E);var A=de(u,E);Me(A);var N=(S^b>=0?-1:1)*tt(A[2]);(r>N||r===N&&(E[0]||E[1]))&&(o+=S^b>=0?1:-1)}if(!d++)break;h=m,p=M,v=x,f=n}}return(-Ca>i||Ca>i&&0>yc)^1&o}function He(n){function t(n,t){return Math.cos(n)*Math.cos(t)>i}function e(n){var e,i,c,l,s;return{lineStart:function(){l=c=!1,s=1},point:function(f,h){var g,p=[f,h],v=t(f,h),d=o?v?0:u(f,h):v?u(f+(0>f?qa:-qa),h):0;if(!e&&(l=c=v)&&n.lineStart(),v!==c&&(g=r(e,p),(be(e,g)||be(p,g))&&(p[0]+=Ca,p[1]+=Ca,v=t(p[0],p[1]))),v!==c)s=0,v?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(a&&e&&o^v){var m;d&i||!(m=r(p,e,!0))||(s=0,o?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!v||e&&be(e,p)||n.point(p[0],p[1]),e=p,c=v,i=d},lineEnd:function(){c&&n.lineEnd(),e=null},clean:function(){return s|(l&&c)<<1}}}function r(n,t,e){var r=pe(n),u=pe(t),o=[1,0,0],a=de(r,u),c=ve(a,a),l=a[0],s=c-l*l;if(!s)return!e&&n;var f=i*c/s,h=-i*l/s,g=de(o,a),p=ye(o,f),v=ye(a,h);me(p,v);var d=g,m=ve(p,d),y=ve(d,d),M=m*m-y*(ve(p,p)-1);if(!(0>M)){var x=Math.sqrt(M),b=ye(d,(-m-x)/y);if(me(b,p),b=xe(b),!e)return b;var _,w=n[0],S=t[0],k=n[1],E=t[1];w>S&&(_=w,w=S,S=_);var A=S-w,N=ga(A-qa)A;if(!N&&k>E&&(_=k,k=E,E=_),C?N?k+E>0^b[1]<(ga(b[0]-w)qa^(w<=b[0]&&b[0]<=S)){var z=ye(d,(-m+x)/y);return me(z,p),[b,xe(z)]}}}function u(t,e){var r=o?n:qa-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),o=i>0,a=ga(i)>Ca,c=gr(n,6*Da);return Le(t,e,c,o?[0,-n]:[-qa,n-qa])}function Oe(n,t,e,r){return function(u){var i,o=u.a,a=u.b,c=o.x,l=o.y,s=a.x,f=a.y,h=0,g=1,p=s-c,v=f-l;if(i=n-c,p||!(i>0)){if(i/=p,0>p){if(h>i)return;g>i&&(g=i)}else if(p>0){if(i>g)return;i>h&&(h=i)}if(i=e-c,p||!(0>i)){if(i/=p,0>p){if(i>g)return;i>h&&(h=i)}else if(p>0){if(h>i)return;g>i&&(g=i)}if(i=t-l,v||!(i>0)){if(i/=v,0>v){if(h>i)return;g>i&&(g=i)}else if(v>0){if(i>g)return;i>h&&(h=i)}if(i=r-l,v||!(0>i)){if(i/=v,0>v){if(i>g)return;i>h&&(h=i)}else if(v>0){if(h>i)return;g>i&&(g=i)}return h>0&&(u.a={x:c+h*p,y:l+h*v}),1>g&&(u.b={x:c+g*p,y:l+g*v}),u}}}}}}function Ie(n,t,e,r){function u(r,u){return ga(r[0]-n)0?0:3:ga(r[0]-e)0?2:1:ga(r[1]-t)0?1:0:u>0?3:2}function i(n,t){return o(n.x,t.x)}function o(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(a){function c(n){for(var t=0,e=d.length,r=n[1],u=0;e>u;++u)for(var i,o=1,a=d[u],c=a.length,l=a[0];c>o;++o)i=a[o],l[1]<=r?i[1]>r&&Q(l,i,n)>0&&++t:i[1]<=r&&Q(l,i,n)<0&&--t,l=i;return 0!==t}function l(i,a,c,l){var s=0,f=0;if(null==i||(s=u(i,c))!==(f=u(a,c))||o(i,a)<0^c>0){do l.point(0===s||3===s?n:e,s>1?r:t);while((s=(s+c+4)%4)!==f)}else l.point(a[0],a[1])}function s(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function f(n,t){s(n,t)&&a.point(n,t)}function h(){C.point=p,d&&d.push(m=[]),S=!0,w=!1,b=_=0/0}function g(){v&&(p(y,M),x&&w&&A.rejoin(),v.push(A.buffer())),C.point=f,w&&a.lineEnd()}function p(n,t){n=Math.max(-Tc,Math.min(Tc,n)),t=Math.max(-Tc,Math.min(Tc,t));var e=s(n,t);if(d&&m.push([n,t]),S)y=n,M=t,x=e,S=!1,e&&(a.lineStart(),a.point(n,t));else if(e&&w)a.point(n,t);else{var r={a:{x:b,y:_},b:{x:n,y:t}};N(r)?(w||(a.lineStart(),a.point(r.a.x,r.a.y)),a.point(r.b.x,r.b.y),e||a.lineEnd(),k=!1):e&&(a.lineStart(),a.point(n,t),k=!1)}b=n,_=t,w=e}var v,d,m,y,M,x,b,_,w,S,k,E=a,A=Re(),N=Oe(n,t,e,r),C={point:f,lineStart:h,lineEnd:g,polygonStart:function(){a=A,v=[],d=[],k=!0},polygonEnd:function(){a=E,v=ta.merge(v);var t=c([n,r]),e=k&&t,u=v.length;(e||u)&&(a.polygonStart(),e&&(a.lineStart(),l(null,null,1,a),a.lineEnd()),u&&Ce(v,i,t,l,a),a.polygonEnd()),v=d=m=null}};return C}}function Ye(n){var t=0,e=qa/3,r=ir(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*qa/180,e=n[1]*qa/180):[t/qa*180,e/qa*180]},u}function Ze(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),o-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),o=Math.sqrt(i)/u;return e.invert=function(n,t){var e=o-t;return[Math.atan2(n,e)/u,tt((i-(n*n+e*e)*u*u)/(2*u))]},e}function Ve(){function n(n,t){Dc+=u*n-r*t,r=n,u=t}var t,e,r,u;Hc.point=function(i,o){Hc.point=n,t=r=i,e=u=o},Hc.lineEnd=function(){n(t,e)}}function Xe(n,t){Pc>n&&(Pc=n),n>jc&&(jc=n),Uc>t&&(Uc=t),t>Fc&&(Fc=t)}function $e(){function n(n,t){o.push("M",n,",",t,i)}function t(n,t){o.push("M",n,",",t),a.point=e}function e(n,t){o.push("L",n,",",t)}function r(){a.point=n}function u(){o.push("Z")}var i=Be(4.5),o=[],a={point:n,lineStart:function(){a.point=t},lineEnd:r,polygonStart:function(){a.lineEnd=u},polygonEnd:function(){a.lineEnd=r,a.point=n},pointRadius:function(n){return i=Be(n),a},result:function(){if(o.length){var n=o.join("");return o=[],n}}};return a}function Be(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function We(n,t){_c+=n,wc+=t,++Sc}function Je(){function n(n,r){var u=n-t,i=r-e,o=Math.sqrt(u*u+i*i);kc+=o*(t+n)/2,Ec+=o*(e+r)/2,Ac+=o,We(t=n,e=r)}var t,e;Ic.point=function(r,u){Ic.point=n,We(t=r,e=u)}}function Ge(){Ic.point=We}function Ke(){function n(n,t){var e=n-r,i=t-u,o=Math.sqrt(e*e+i*i);kc+=o*(r+n)/2,Ec+=o*(u+t)/2,Ac+=o,o=u*n-r*t,Nc+=o*(r+n),Cc+=o*(u+t),zc+=3*o,We(r=n,u=t)}var t,e,r,u;Ic.point=function(i,o){Ic.point=n,We(t=r=i,e=u=o)},Ic.lineEnd=function(){n(t,e)}}function Qe(n){function t(t,e){n.moveTo(t+o,e),n.arc(t,e,o,0,La)}function e(t,e){n.moveTo(t,e),a.point=r}function r(t,e){n.lineTo(t,e)}function u(){a.point=t}function i(){n.closePath()}var o=4.5,a={point:t,lineStart:function(){a.point=e},lineEnd:u,polygonStart:function(){a.lineEnd=i},polygonEnd:function(){a.lineEnd=u,a.point=t},pointRadius:function(n){return o=n,a},result:b};return a}function nr(n){function t(n){return(a?r:e)(n)}function e(t){return rr(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){M=0/0,S.point=i,t.lineStart()}function i(e,r){var i=pe([e,r]),o=n(e,r);u(M,x,y,b,_,w,M=o[0],x=o[1],y=e,b=i[0],_=i[1],w=i[2],a,t),t.point(M,x)}function o(){S.point=e,t.lineEnd()}function c(){r(),S.point=l,S.lineEnd=s}function l(n,t){i(f=n,h=t),g=M,p=x,v=b,d=_,m=w,S.point=i}function s(){u(M,x,y,b,_,w,g,p,f,v,d,m,a,t),S.lineEnd=o,o()}var f,h,g,p,v,d,m,y,M,x,b,_,w,S={point:e,lineStart:r,lineEnd:o,polygonStart:function(){t.polygonStart(),S.lineStart=c
2 | },polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,a,c,l,s,f,h,g,p,v,d,m){var y=s-t,M=f-e,x=y*y+M*M;if(x>4*i&&d--){var b=a+g,_=c+p,w=l+v,S=Math.sqrt(b*b+_*_+w*w),k=Math.asin(w/=S),E=ga(ga(w)-1)i||ga((y*z+M*q)/x-.5)>.3||o>a*g+c*p+l*v)&&(u(t,e,r,a,c,l,N,C,E,b/=S,_/=S,w,d,m),m.point(N,C),u(N,C,E,b,_,w,s,f,h,g,p,v,d,m))}}var i=.5,o=Math.cos(30*Da),a=16;return t.precision=function(n){return arguments.length?(a=(i=n*n)>0&&16,t):Math.sqrt(i)},t}function tr(n){var t=nr(function(t,e){return n([t*Pa,e*Pa])});return function(n){return or(t(n))}}function er(n){this.stream=n}function rr(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function ur(n){return ir(function(){return n})()}function ir(n){function t(n){return n=a(n[0]*Da,n[1]*Da),[n[0]*h+c,l-n[1]*h]}function e(n){return n=a.invert((n[0]-c)/h,(l-n[1])/h),n&&[n[0]*Pa,n[1]*Pa]}function r(){a=Ae(o=lr(m,M,x),i);var n=i(v,d);return c=g-n[0]*h,l=p+n[1]*h,u()}function u(){return s&&(s.valid=!1,s=null),t}var i,o,a,c,l,s,f=nr(function(n,t){return n=i(n,t),[n[0]*h+c,l-n[1]*h]}),h=150,g=480,p=250,v=0,d=0,m=0,M=0,x=0,b=Lc,_=y,w=null,S=null;return t.stream=function(n){return s&&(s.valid=!1),s=or(b(o,f(_(n)))),s.valid=!0,s},t.clipAngle=function(n){return arguments.length?(b=null==n?(w=n,Lc):He((w=+n)*Da),u()):w},t.clipExtent=function(n){return arguments.length?(S=n,_=n?Ie(n[0][0],n[0][1],n[1][0],n[1][1]):y,u()):S},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(v=n[0]%360*Da,d=n[1]%360*Da,r()):[v*Pa,d*Pa]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Da,M=n[1]%360*Da,x=n.length>2?n[2]%360*Da:0,r()):[m*Pa,M*Pa,x*Pa]},ta.rebind(t,f,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function or(n){return rr(n,function(t,e){n.point(t*Da,e*Da)})}function ar(n,t){return[n,t]}function cr(n,t){return[n>qa?n-La:-qa>n?n+La:n,t]}function lr(n,t,e){return n?t||e?Ae(fr(n),hr(t,e)):fr(n):t||e?hr(t,e):cr}function sr(n){return function(t,e){return t+=n,[t>qa?t-La:-qa>t?t+La:t,e]}}function fr(n){var t=sr(n);return t.invert=sr(-n),t}function hr(n,t){function e(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,l=Math.sin(t),s=l*r+a*u;return[Math.atan2(c*i-s*o,a*r-l*u),tt(s*i+c*o)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),o=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),a=Math.cos(n)*e,c=Math.sin(n)*e,l=Math.sin(t),s=l*i-c*o;return[Math.atan2(c*i+l*o,a*r+s*u),tt(s*r-a*u)]},e}function gr(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,o,a){var c=o*t;null!=u?(u=pr(e,u),i=pr(e,i),(o>0?i>u:u>i)&&(u+=o*La)):(u=n+o*La,i=n-.5*c);for(var l,s=u;o>0?s>i:i>s;s-=c)a.point((l=xe([e,-r*Math.cos(s),-r*Math.sin(s)]))[0],l[1])}}function pr(n,t){var e=pe(t);e[0]-=n,Me(e);var r=nt(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Ca)%(2*Math.PI)}function vr(n,t,e){var r=ta.range(n,t-Ca,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function dr(n,t,e){var r=ta.range(n,t-Ca,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function mr(n){return n.source}function yr(n){return n.target}function Mr(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),o=Math.cos(r),a=Math.sin(r),c=u*Math.cos(n),l=u*Math.sin(n),s=o*Math.cos(e),f=o*Math.sin(e),h=2*Math.asin(Math.sqrt(it(r-t)+u*o*it(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*c+t*s,u=e*l+t*f,o=e*i+t*a;return[Math.atan2(u,r)*Pa,Math.atan2(o,Math.sqrt(r*r+u*u))*Pa]}:function(){return[n*Pa,t*Pa]};return p.distance=h,p}function xr(){function n(n,u){var i=Math.sin(u*=Da),o=Math.cos(u),a=ga((n*=Da)-t),c=Math.cos(a);Yc+=Math.atan2(Math.sqrt((a=o*Math.sin(a))*a+(a=r*i-e*o*c)*a),e*i+r*o*c),t=n,e=i,r=o}var t,e,r;Zc.point=function(u,i){t=u*Da,e=Math.sin(i*=Da),r=Math.cos(i),Zc.point=n},Zc.lineEnd=function(){Zc.point=Zc.lineEnd=b}}function br(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),o=Math.cos(u);return[Math.atan2(n*i,r*o),Math.asin(r&&e*i/r)]},e}function _r(n,t){function e(n,t){o>0?-Ra+Ca>t&&(t=-Ra+Ca):t>Ra-Ca&&(t=Ra-Ca);var e=o/Math.pow(u(t),i);return[e*Math.sin(i*n),o-e*Math.cos(i*n)]}var r=Math.cos(n),u=function(n){return Math.tan(qa/4+n/2)},i=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(u(t)/u(n)),o=r*Math.pow(u(n),i)/i;return i?(e.invert=function(n,t){var e=o-t,r=K(i)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/i,2*Math.atan(Math.pow(o/r,1/i))-Ra]},e):Sr}function wr(n,t){function e(n,t){var e=i-t;return[e*Math.sin(u*n),i-e*Math.cos(u*n)]}var r=Math.cos(n),u=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),i=r/u+n;return ga(u)u;u++){for(;r>1&&Q(n[e[r-2]],n[e[r-1]],n[u])<=0;)--r;e[r++]=u}return e.slice(0,r)}function zr(n,t){return n[0]-t[0]||n[1]-t[1]}function qr(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Lr(n,t,e,r){var u=n[0],i=e[0],o=t[0]-u,a=r[0]-i,c=n[1],l=e[1],s=t[1]-c,f=r[1]-l,h=(a*(c-l)-f*(u-i))/(f*o-a*s);return[u+h*o,c+h*s]}function Tr(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Rr(){tu(this),this.edge=this.site=this.circle=null}function Dr(n){var t=el.pop()||new Rr;return t.site=n,t}function Pr(n){Xr(n),Qc.remove(n),el.push(n),tu(n)}function Ur(n){var t=n.circle,e=t.x,r=t.cy,u={x:e,y:r},i=n.P,o=n.N,a=[n];Pr(n);for(var c=i;c.circle&&ga(e-c.circle.x)s;++s)l=a[s],c=a[s-1],Kr(l.edge,c.site,l.site,u);c=a[0],l=a[f-1],l.edge=Jr(c.site,l.site,null,u),Vr(c),Vr(l)}function jr(n){for(var t,e,r,u,i=n.x,o=n.y,a=Qc._;a;)if(r=Fr(a,o)-i,r>Ca)a=a.L;else{if(u=i-Hr(a,o),!(u>Ca)){r>-Ca?(t=a.P,e=a):u>-Ca?(t=a,e=a.N):t=e=a;break}if(!a.R){t=a;break}a=a.R}var c=Dr(n);if(Qc.insert(t,c),t||e){if(t===e)return Xr(t),e=Dr(t.site),Qc.insert(c,e),c.edge=e.edge=Jr(t.site,c.site),Vr(t),void Vr(e);if(!e)return void(c.edge=Jr(t.site,c.site));Xr(t),Xr(e);var l=t.site,s=l.x,f=l.y,h=n.x-s,g=n.y-f,p=e.site,v=p.x-s,d=p.y-f,m=2*(h*d-g*v),y=h*h+g*g,M=v*v+d*d,x={x:(d*y-g*M)/m+s,y:(h*M-v*y)/m+f};Kr(e.edge,l,p,x),c.edge=Jr(l,n,null,x),e.edge=Jr(n,p,null,x),Vr(t),Vr(e)}}function Fr(n,t){var e=n.site,r=e.x,u=e.y,i=u-t;if(!i)return r;var o=n.P;if(!o)return-1/0;e=o.site;var a=e.x,c=e.y,l=c-t;if(!l)return a;var s=a-r,f=1/i-1/l,h=s/l;return f?(-h+Math.sqrt(h*h-2*f*(s*s/(-2*l)-c+l/2+u-i/2)))/f+r:(r+a)/2}function Hr(n,t){var e=n.N;if(e)return Fr(e,t);var r=n.site;return r.y===t?r.x:1/0}function Or(n){this.site=n,this.edges=[]}function Ir(n){for(var t,e,r,u,i,o,a,c,l,s,f=n[0][0],h=n[1][0],g=n[0][1],p=n[1][1],v=Kc,d=v.length;d--;)if(i=v[d],i&&i.prepare())for(a=i.edges,c=a.length,o=0;c>o;)s=a[o].end(),r=s.x,u=s.y,l=a[++o%c].start(),t=l.x,e=l.y,(ga(r-t)>Ca||ga(u-e)>Ca)&&(a.splice(o,0,new Qr(Gr(i.site,s,ga(r-f)Ca?{x:f,y:ga(t-f)Ca?{x:ga(e-p)Ca?{x:h,y:ga(t-h)Ca?{x:ga(e-g)=-za)){var g=c*c+l*l,p=s*s+f*f,v=(f*g-l*p)/h,d=(c*p-s*g)/h,f=d+a,m=rl.pop()||new Zr;m.arc=n,m.site=u,m.x=v+o,m.y=f+Math.sqrt(v*v+d*d),m.cy=f,n.circle=m;for(var y=null,M=tl._;M;)if(m.yd||d>=a)return;if(h>p){if(i){if(i.y>=l)return}else i={x:d,y:c};e={x:d,y:l}}else{if(i){if(i.yr||r>1)if(h>p){if(i){if(i.y>=l)return}else i={x:(c-u)/r,y:c};e={x:(l-u)/r,y:l}}else{if(i){if(i.yg){if(i){if(i.x>=a)return}else i={x:o,y:r*o+u};e={x:a,y:r*a+u}}else{if(i){if(i.xi||f>o||r>h||u>g)){if(p=n.point){var p,v=t-n.x,d=e-n.y,m=v*v+d*d;if(c>m){var y=Math.sqrt(c=m);r=t-y,u=e-y,i=t+y,o=e+y,a=p}}for(var M=n.nodes,x=.5*(s+h),b=.5*(f+g),_=t>=x,w=e>=b,S=w<<1|_,k=S+4;k>S;++S)if(n=M[3&S])switch(3&S){case 0:l(n,s,f,x,b);break;case 1:l(n,x,f,h,b);break;case 2:l(n,s,b,x,g);break;case 3:l(n,x,b,h,g)}}}(n,r,u,i,o),a}function gu(n,t){n=ta.rgb(n),t=ta.rgb(t);var e=n.r,r=n.g,u=n.b,i=t.r-e,o=t.g-r,a=t.b-u;return function(n){return"#"+xt(Math.round(e+i*n))+xt(Math.round(r+o*n))+xt(Math.round(u+a*n))}}function pu(n,t){var e,r={},u={};for(e in n)e in t?r[e]=mu(n[e],t[e]):u[e]=n[e];for(e in t)e in n||(u[e]=t[e]);return function(n){for(e in r)u[e]=r[e](n);return u}}function vu(n,t){return n=+n,t=+t,function(e){return n*(1-e)+t*e}}function du(n,t){var e,r,u,i=il.lastIndex=ol.lastIndex=0,o=-1,a=[],c=[];for(n+="",t+="";(e=il.exec(n))&&(r=ol.exec(t));)(u=r.index)>i&&(u=t.slice(i,u),a[o]?a[o]+=u:a[++o]=u),(e=e[0])===(r=r[0])?a[o]?a[o]+=r:a[++o]=r:(a[++o]=null,c.push({i:o,x:vu(e,r)})),i=ol.lastIndex;return ir;++r)a[(e=c[r]).i]=e.x(n);return a.join("")})}function mu(n,t){for(var e,r=ta.interpolators.length;--r>=0&&!(e=ta.interpolators[r](n,t)););return e}function yu(n,t){var e,r=[],u=[],i=n.length,o=t.length,a=Math.min(n.length,t.length);for(e=0;a>e;++e)r.push(mu(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;o>e;++e)u[e]=t[e];return function(n){for(e=0;a>e;++e)u[e]=r[e](n);return u}}function Mu(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function xu(n){return function(t){return 1-n(1-t)}}function bu(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function _u(n){return n*n}function wu(n){return n*n*n}function Su(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function ku(n){return function(t){return Math.pow(t,n)}}function Eu(n){return 1-Math.cos(n*Ra)}function Au(n){return Math.pow(2,10*(n-1))}function Nu(n){return 1-Math.sqrt(1-n*n)}function Cu(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/La*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*La/t)}}function zu(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function qu(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Lu(n,t){n=ta.hcl(n),t=ta.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,o=t.c-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return st(e+i*n,r+o*n,u+a*n)+""}}function Tu(n,t){n=ta.hsl(n),t=ta.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,o=t.s-r,a=t.l-u;return isNaN(o)&&(o=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return ct(e+i*n,r+o*n,u+a*n)+""}}function Ru(n,t){n=ta.lab(n),t=ta.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,o=t.a-r,a=t.b-u;return function(n){return ht(e+i*n,r+o*n,u+a*n)+""}}function Du(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Pu(n){var t=[n.a,n.b],e=[n.c,n.d],r=ju(t),u=Uu(t,e),i=ju(Fu(e,t,-u))||0;t[0]*e[1]180?s+=360:s-l>180&&(l+=360),u.push({i:r.push(r.pop()+"rotate(",null,")")-2,x:vu(l,s)})):s&&r.push(r.pop()+"rotate("+s+")"),f!=h?u.push({i:r.push(r.pop()+"skewX(",null,")")-2,x:vu(f,h)}):h&&r.push(r.pop()+"skewX("+h+")"),g[0]!=p[0]||g[1]!=p[1]?(e=r.push(r.pop()+"scale(",null,",",null,")"),u.push({i:e-4,x:vu(g[0],p[0])},{i:e-2,x:vu(g[1],p[1])})):(1!=p[0]||1!=p[1])&&r.push(r.pop()+"scale("+p+")"),e=u.length,function(n){for(var t,i=-1;++i=0;)e.push(u[r])}function Qu(n,t){for(var e=[n],r=[];null!=(n=e.pop());)if(r.push(n),(i=n.children)&&(u=i.length))for(var u,i,o=-1;++oe;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function si(n){return n.reduce(fi,0)}function fi(n,t){return n+t[1]}function hi(n,t){return gi(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function gi(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function pi(n){return[ta.min(n),ta.max(n)]}function vi(n,t){return n.value-t.value}function di(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function mi(n,t){n._pack_next=t,t._pack_prev=n}function yi(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function Mi(n){function t(n){s=Math.min(n.x-n.r,s),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(l=e.length)){var e,r,u,i,o,a,c,l,s=1/0,f=-1/0,h=1/0,g=-1/0;if(e.forEach(xi),r=e[0],r.x=-r.r,r.y=0,t(r),l>1&&(u=e[1],u.x=u.r,u.y=0,t(u),l>2))for(i=e[2],wi(r,u,i),t(i),di(r,i),r._pack_prev=i,di(i,u),u=r._pack_next,o=3;l>o;o++){wi(r,u,i=e[o]);var p=0,v=1,d=1;for(a=u._pack_next;a!==u;a=a._pack_next,v++)if(yi(a,i)){p=1;break}if(1==p)for(c=r._pack_prev;c!==a._pack_prev&&!yi(c,i);c=c._pack_prev,d++);p?(d>v||v==d&&u.ro;o++)i=e[o],i.x-=m,i.y-=y,M=Math.max(M,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=M,e.forEach(bi)}}function xi(n){n._pack_next=n._pack_prev=n}function bi(n){delete n._pack_next,delete n._pack_prev}function _i(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,o=u.length;++i=0;)t=u[i],t.z+=e,t.m+=e,e+=t.s+(r+=t.c)}function Ci(n,t,e){return n.a.parent===t.parent?n.a:e}function zi(n){return 1+ta.max(n,function(n){return n.y})}function qi(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Li(n){var t=n.children;return t&&t.length?Li(t[0]):n}function Ti(n){var t,e=n.children;return e&&(t=e.length)?Ti(e[t-1]):n}function Ri(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function Di(n,t){var e=n.x+t[3],r=n.y+t[0],u=n.dx-t[1]-t[3],i=n.dy-t[0]-t[2];return 0>u&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function Pi(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Ui(n){return n.rangeExtent?n.rangeExtent():Pi(n.range())}function ji(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Fi(n,t){var e,r=0,u=n.length-1,i=n[r],o=n[u];return i>o&&(e=r,r=u,u=e,e=i,i=o,o=e),n[r]=t.floor(i),n[u]=t.ceil(o),n}function Hi(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:ml}function Oi(n,t,e,r){var u=[],i=[],o=0,a=Math.min(n.length,t.length)-1;for(n[a]2?Oi:ji,c=r?Iu:Ou;return o=u(n,t,c,e),a=u(t,n,c,mu),i}function i(n){return o(n)}var o,a;return i.invert=function(n){return a(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(Du)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return Xi(n,t)},i.tickFormat=function(t,e){return $i(n,t,e)},i.nice=function(t){return Zi(n,t),u()},i.copy=function(){return Ii(n,t,e,r)},u()}function Yi(n,t){return ta.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Zi(n,t){return Fi(n,Hi(Vi(n,t)[2]))}function Vi(n,t){null==t&&(t=10);var e=Pi(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Xi(n,t){return ta.range.apply(ta,Vi(n,t))}function $i(n,t,e){var r=Vi(n,t);if(e){var u=ic.exec(e);if(u.shift(),"s"===u[8]){var i=ta.formatPrefix(Math.max(ga(r[0]),ga(r[1])));return u[7]||(u[7]="."+Bi(i.scale(r[2]))),u[8]="f",e=ta.format(u.join("")),function(n){return e(i.scale(n))+i.symbol}}u[7]||(u[7]="."+Wi(u[8],r)),e=u.join("")}else e=",."+Bi(r[2])+"f";return ta.format(e)}function Bi(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function Wi(n,t){var e=Bi(t[2]);return n in yl?Math.abs(e-Bi(Math.max(ga(t[0]),ga(t[1]))))+ +("e"!==n):e-2*("%"===n)}function Ji(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function o(t){return n(u(t))}return o.invert=function(t){return i(n.invert(t))},o.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),o):r},o.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),o):t},o.nice=function(){var t=Fi(r.map(u),e?Math:xl);return n.domain(t),r=t.map(i),o},o.ticks=function(){var n=Pi(r),o=[],a=n[0],c=n[1],l=Math.floor(u(a)),s=Math.ceil(u(c)),f=t%1?2:t;if(isFinite(s-l)){if(e){for(;s>l;l++)for(var h=1;f>h;h++)o.push(i(l)*h);o.push(i(l))}else for(o.push(i(l));l++0;h--)o.push(i(l)*h);for(l=0;o[l]c;s--);o=o.slice(l,s)}return o},o.tickFormat=function(n,t){if(!arguments.length)return Ml;arguments.length<2?t=Ml:"function"!=typeof t&&(t=ta.format(t));var r,a=Math.max(.1,n/o.ticks().length),c=e?(r=1e-12,Math.ceil):(r=-1e-12,Math.floor);return function(n){return n/i(c(u(n)+r))<=a?t(n):""}},o.copy=function(){return Ji(n.copy(),t,e,r)},Yi(o,n)}function Gi(n,t,e){function r(t){return n(u(t))}var u=Ki(t),i=Ki(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return Xi(e,n)},r.tickFormat=function(n,t){return $i(e,n,t)},r.nice=function(n){return r.domain(Zi(e,n))},r.exponent=function(o){return arguments.length?(u=Ki(t=o),i=Ki(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return Gi(n.copy(),t,e)},Yi(r,n)}function Ki(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function Qi(n,t){function e(e){return i[((u.get(e)||("range"===t.t?u.set(e,n.push(e)):0/0))-1)%i.length]}function r(t,e){return ta.range(n.length).map(function(n){return t+e*n})}var u,i,o;return e.domain=function(r){if(!arguments.length)return n;n=[],u=new l;for(var i,o=-1,a=r.length;++oe?[0/0,0/0]:[e>0?a[e-1]:n[0],et?0/0:t/i+n,[t,t+1/i]},r.copy=function(){return to(n,t,e)},u()}function eo(n,t){function e(e){return e>=e?t[ta.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return eo(n,t)},e}function ro(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Xi(n,t)},t.tickFormat=function(t,e){return $i(n,t,e)},t.copy=function(){return ro(n)},t}function uo(){return 0}function io(n){return n.innerRadius}function oo(n){return n.outerRadius}function ao(n){return n.startAngle}function co(n){return n.endAngle}function lo(n){return n&&n.padAngle}function so(n,t,e,r){return(n-e)*t-(t-r)*n>0?0:1}function fo(n,t,e,r,u){var i=n[0]-t[0],o=n[1]-t[1],a=(u?r:-r)/Math.sqrt(i*i+o*o),c=a*o,l=-a*i,s=n[0]+c,f=n[1]+l,h=t[0]+c,g=t[1]+l,p=(s+h)/2,v=(f+g)/2,d=h-s,m=g-f,y=d*d+m*m,M=e-r,x=s*g-h*f,b=(0>m?-1:1)*Math.sqrt(M*M*y-x*x),_=(x*m-d*b)/y,w=(-x*d-m*b)/y,S=(x*m+d*b)/y,k=(-x*d+m*b)/y,E=_-p,A=w-v,N=S-p,C=k-v;return E*E+A*A>N*N+C*C&&(_=S,w=k),[[_-c,w-l],[_*e/M,w*e/M]]}function ho(n){function t(t){function o(){l.push("M",i(n(s),a))}for(var c,l=[],s=[],f=-1,h=t.length,g=Et(e),p=Et(r);++f1&&u.push("H",r[0]),u.join("")}function mo(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t1){a=t[1],i=n[c],c++,r+="C"+(u[0]+o[0])+","+(u[1]+o[1])+","+(i[0]-a[0])+","+(i[1]-a[1])+","+i[0]+","+i[1];for(var l=2;l9&&(u=3*t/Math.sqrt(u),o[a]=u*e,o[a+1]=u*r));for(a=-1;++a<=c;)u=(n[Math.min(c,a+1)][0]-n[Math.max(0,a-1)][0])/(6*(1+o[a]*o[a])),i.push([u||0,o[a]*u||0]);return i}function To(n){return n.length<3?go(n):n[0]+_o(n,Lo(n))}function Ro(n){for(var t,e,r,u=-1,i=n.length;++ur)return s();var u=i[i.active];u&&(--i.count,delete i[i.active],u.event&&u.event.interrupt.call(n,n.__data__,u.index)),i.active=r,o.event&&o.event.start.call(n,n.__data__,t),o.tween.forEach(function(e,r){(r=r.call(n,n.__data__,t))&&v.push(r)}),h=o.ease,f=o.duration,ta.timer(function(){return p.c=l(e||1)?Ne:l,1},0,a)}function l(e){if(i.active!==r)return 1;for(var u=e/f,a=h(u),c=v.length;c>0;)v[--c].call(n,a);return u>=1?(o.event&&o.event.end.call(n,n.__data__,t),s()):void 0}function s(){return--i.count?delete i[r]:delete n[e],1}var f,h,g=o.delay,p=ec,v=[];return p.t=g+a,u>=g?c(u-g):void(p.c=c)},0,a)}}function Bo(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate("+(isFinite(r)?r:e(n))+",0)"})}function Wo(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate(0,"+(isFinite(r)?r:e(n))+")"})}function Jo(n){return n.toISOString()}function Go(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=ta.bisect(Vl,u);return i==Vl.length?[t.year,Vi(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/Vl[i-1]1?{floor:function(t){for(;e(t=n.floor(t));)t=Ko(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=Ko(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Pi(r.domain()),i=null==n?u(e,10):"number"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],Ko(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return Go(n.copy(),t,e)},Yi(r,n)}function Ko(n){return new Date(n)}function Qo(n){return JSON.parse(n.responseText)}function na(n){var t=ua.createRange();return t.selectNode(ua.body),t.createContextualFragment(n.responseText)}var ta={version:"3.5.4"},ea=[].slice,ra=function(n){return ea.call(n)},ua=this.document;if(ua)try{ra(ua.documentElement.childNodes)[0].nodeType}catch(ia){ra=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}if(Date.now||(Date.now=function(){return+new Date}),ua)try{ua.createElement("DIV").style.setProperty("opacity",0,"")}catch(oa){var aa=this.Element.prototype,ca=aa.setAttribute,la=aa.setAttributeNS,sa=this.CSSStyleDeclaration.prototype,fa=sa.setProperty;aa.setAttribute=function(n,t){ca.call(this,n,t+"")},aa.setAttributeNS=function(n,t,e){la.call(this,n,t,e+"")},sa.setProperty=function(n,t,e){fa.call(this,n,t+"",e)}}ta.ascending=e,ta.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:0/0},ta.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u=r){e=r;break}for(;++ur&&(e=r)}else{for(;++u=r){e=r;break}for(;++ur&&(e=r)}return e},ta.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u=r){e=r;break}for(;++ue&&(e=r)}else{for(;++u=r){e=r;break}for(;++ue&&(e=r)}return e},ta.extent=function(n,t){var e,r,u,i=-1,o=n.length;if(1===arguments.length){for(;++i=r){e=u=r;break}for(;++ir&&(e=r),r>u&&(u=r))}else{for(;++i=r){e=u=r;break}for(;++ir&&(e=r),r>u&&(u=r))}return[e,u]},ta.sum=function(n,t){var e,r=0,i=n.length,o=-1;if(1===arguments.length)for(;++o1?c/(s-1):void 0},ta.deviation=function(){var n=ta.variance.apply(this,arguments);return n?Math.sqrt(n):n};var ha=i(e);ta.bisectLeft=ha.left,ta.bisect=ta.bisectRight=ha.right,ta.bisector=function(n){return i(1===n.length?function(t,r){return e(n(t),r)}:n)},ta.shuffle=function(n,t,e){(i=arguments.length)<3&&(e=n.length,2>i&&(t=0));for(var r,u,i=e-t;i;)u=Math.random()*i--|0,r=n[i+t],n[i+t]=n[u+t],n[u+t]=r;return n},ta.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},ta.pairs=function(n){for(var t,e=0,r=n.length-1,u=n[0],i=new Array(0>r?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},ta.zip=function(){if(!(r=arguments.length))return[];for(var n=-1,t=ta.min(arguments,o),e=new Array(t);++n=0;)for(r=n[u],t=r.length;--t>=0;)e[--o]=r[t];return e};var ga=Math.abs;ta.range=function(n,t,e){if(arguments.length<3&&(e=1,arguments.length<2&&(t=n,n=0)),(t-n)/e===1/0)throw new Error("infinite range");var r,u=[],i=a(ga(e)),o=-1;if(n*=i,t*=i,e*=i,0>e)for(;(r=n+e*++o)>t;)u.push(r/i);else for(;(r=n+e*++o)=i.length)return r?r.call(u,o):e?o.sort(e):o;for(var c,s,f,h,g=-1,p=o.length,v=i[a++],d=new l;++g