diff --git a/Makefile b/Makefile index 0e386da7..ad27c6c7 100644 --- a/Makefile +++ b/Makefile @@ -36,9 +36,9 @@ d3.custom.js: \ src/end.js d3.core.js: \ + src/compat/date.js \ + src/compat/style.js \ src/core/core.js \ - src/core/date.js \ - src/core/object.js \ src/core/array.js \ src/core/this.js \ src/core/functor.js \ @@ -185,6 +185,7 @@ d3.geo.js: \ src/geo/mercator.js \ src/geo/path.js \ src/geo/bounds.js \ + src/geo/greatCircle.js \ src/end.js d3.csv.js: \ diff --git a/d3.geo.js b/d3.geo.js index 0dc051e1..4c4f4ac7 100644 --- a/d3.geo.js +++ b/d3.geo.js @@ -17,7 +17,7 @@ d3.geo.azimuthal = function() { sx1 = Math.sin(x1), cy1 = Math.cos(y1), sy1 = Math.sin(y1), - k = mode == "stereographic" ? 1 / (1 + sy0 * sy1 + cy0 * cy1 * cx1) : 1, + k = mode === "stereographic" ? 1 / (1 + sy0 * sy1 + cy0 * cy1 * cx1) : 1, x = k * cy1 * sx1, y = k * (sy0 * cy1 * cx1 - cy0 * sy1); return [ @@ -26,9 +26,22 @@ d3.geo.azimuthal = function() { ]; } + azimuthal.invert = function(coordinates) { + var x = (coordinates[0] - translate[0]) / scale, + y = (coordinates[1] - translate[1]) / scale, + p = Math.sqrt(x * x + y * y), + c = mode === "stereographic" ? 2 * Math.atan(p) : Math.asin(p), + sc = Math.sin(c), + cc = Math.cos(c); + return [ + (x0 + Math.atan2(x * sc, p * cy0 * cc + y * sy0 * sc)) / d3_radians, + Math.asin(cc * sy0 - (y * sc * cy0) / p) / d3_radians + ]; + }; + azimuthal.mode = function(x) { if (!arguments.length) return mode; - mode = x; + mode = x + ""; return azimuthal; }; @@ -79,6 +92,18 @@ d3.geo.albers = function() { ]; } + albers.invert = function(coordinates) { + var x = (coordinates[0] - translate[0]) / scale, + y = (coordinates[1] - translate[1]) / scale, + p0y = p0 + y, + t = Math.atan2(x, p0y), + p = Math.sqrt(x * x + p0y * p0y); + return [ + (lng0 + t / n) / d3_radians, + Math.asin((C - p * p * n * n) / (2 * n)) / d3_radians + ]; + }; + function reload() { var phi1 = d3_radians * parallels[0], phi2 = d3_radians * parallels[1], @@ -177,14 +202,23 @@ d3.geo.mercator = function() { translate = [480, 250]; function mercator(coordinates) { - var x = (coordinates[0]) / 360, - y = (-180 / Math.PI * Math.log(Math.tan(Math.PI / 4 + coordinates[1] * Math.PI / 360))) / 360; + var x = coordinates[0] / 360, + y = -(Math.log(Math.tan(Math.PI / 4 + coordinates[1] * d3_radians / 2)) / d3_radians) / 360; return [ scale * x + translate[0], scale * Math.max(-.5, Math.min(.5, y)) + translate[1] ]; } + mercator.invert = function(coordinates) { + var x = (coordinates[0] - translate[0]) / scale, + y = (coordinates[1] - translate[1]) / scale; + return [ + 360 * x, + 2 * Math.atan(Math.exp(-360 * y * d3_radians)) / d3_radians - 90 + ]; + }; + mercator.scale = function(x) { if (!arguments.length) return scale; scale = +x; @@ -564,4 +598,95 @@ function d3_geo_boundsPolygon(o, f) { f.apply(null, a[i]); } } +// From http://williams.best.vwh.net/avform.htm#Intermediate +d3.geo.greatCircle = function() { + var source = d3_geo_greatCircleSource, + target = d3_geo_greatCircleTarget, + n = 100, + radius = 6371; // Mean radius of Earth, in km. + // TODO: breakAtDateLine? + + function greatCircle(d, i) { + var from = source.call(this, d, i), + to = target.call(this, d, i), + x0 = from[0] * d3_radians, + y0 = from[1] * d3_radians, + x1 = to[0] * d3_radians, + y1 = to[1] * d3_radians, + cx0 = Math.cos(x0), sx0 = Math.sin(x0), + cy0 = Math.cos(y0), sy0 = Math.sin(y0), + cx1 = Math.cos(x1), sx1 = Math.sin(x1), + cy1 = Math.cos(y1), sy1 = Math.sin(y1), + d = Math.acos(sy0 * sy1 + cy0 * cy1 * Math.cos(x1 - x0)), + sd = Math.sin(d), + f = d / (n - 1), + e = -f, + path = [], + i = -1; + + while (++i < n) { + e += f; + var A = Math.sin(d - e) / sd, + B = Math.sin(e) / sd, + x = A * cy0 * cx0 + B * cy1 * cx1, + y = A * cy0 * sx0 + B * cy1 * sx1, + z = A * sy0 + B * sy1; + path[i] = [ + Math.atan2(y, x) / d3_radians, + Math.atan2(z, Math.sqrt(x * x + y * y)) / d3_radians + ]; + } + + return path; + } + + greatCircle.source = function(x) { + if (!arguments.length) return source; + source = x; + return greatCircle; + }; + + greatCircle.target = function(x) { + if (!arguments.length) return target; + target = x; + return greatCircle; + }; + + greatCircle.n = function(x) { + if (!arguments.length) return n; + n = +x; + return greatCircle; + }; + + greatCircle.radius = function(x) { + if (!arguments.length) return radius; + radius = +x; + return greatCircle; + }; + + // Haversine formula for great-circle distance. + greatCircle.distance = function(d, i) { + var from = source.call(this, d, i), + to = target.call(this, d, i), + x0 = from[0] * d3_radians, + y0 = from[1] * d3_radians, + x1 = to[0] * d3_radians, + y1 = to[1] * d3_radians, + sy = Math.sin((y1 - y0) / 2), + sx = Math.sin((x1 - x0) / 2), + a = sy * sy + Math.cos(y0) * Math.cos(y1) * sx * sx; + + return radius * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + }; + + return greatCircle; +}; + +function d3_geo_greatCircleSource(d) { + return d.source; +} + +function d3_geo_greatCircleTarget(d) { + return d.target; +} })(); diff --git a/d3.geo.min.js b/d3.geo.min.js index 3f380b54..8b8aa9be 100644 --- a/d3.geo.min.js +++ b/d3.geo.min.js @@ -1 +1 @@ -(function(){function m(a,b){for(var c=a.coordinates[0],d=0,e=c.length;d50?b:f<-140?c:g<21?d:a)(e)}var a=d3.geo.albers(),b=d3.geo.albers().origin([-160,60]).parallels([55,65]),c=d3.geo.albers().origin([-160,20]).parallels([8,18]),d=d3.geo.albers().origin([-60,10]).parallels([8,18]);e.scale=function(f){if(!arguments.length)return a.scale();a.scale(f),b.scale(f*.6),c.scale(f),d.scale(f*1.5);return e.translate(a.translate())},e.translate=function(f){if(!arguments.length)return a.translate();var g=a.scale()/1e3,h=f[0],i=f[1];a.translate(f),b.translate([h-400*g,i+170*g]),c.translate([h-190*g,i+200*g]),d.translate([h+580*g,i+430*g]);return e};return e.scale(a.scale())};var a=Math.PI/180;d3.geo.mercator=function(){function c(c){var d=c[0]/360,e=-180/Math.PI*Math.log(Math.tan(Math.PI/4+c[1]*Math.PI/360))/360;return[a*d+b[0],a*Math.max(-0.5,Math.min(.5,e))+b[1]]}var a=500,b=[480,250];c.scale=function(b){if(!arguments.length)return a;a=+b;return c},c.translate=function(a){if(!arguments.length)return b;b=[+a[0],+a[1]];return c};return c},d3.geo.path=function(){function n(a){return Math.abs(d3.geom.polygon(a.map(f)).area())}function l(a){var b=d3.geom.polygon(a[0].map(f)),c=b.centroid(1),d=c[0],e=c[1],g=Math.abs(b.area()),h=0,i=a.length;while(++hd&&(d=a),ef&&(f=e)});return[[b,c],[d,f]]};var f={Feature:g,FeatureCollection:h,LineString:i,MultiLineString:j,MultiPoint:i,MultiPolygon:k,Point:l,Polygon:m}})() \ No newline at end of file +(function(){function o(a){return a.target}function n(a){return a.source}function m(a,b){for(var c=a.coordinates[0],d=0,e=c.length;d50?b:f<-140?c:g<21?d:a)(e)}var a=d3.geo.albers(),b=d3.geo.albers().origin([-160,60]).parallels([55,65]),c=d3.geo.albers().origin([-160,20]).parallels([8,18]),d=d3.geo.albers().origin([-60,10]).parallels([8,18]);e.scale=function(f){if(!arguments.length)return a.scale();a.scale(f),b.scale(f*.6),c.scale(f),d.scale(f*1.5);return e.translate(a.translate())},e.translate=function(f){if(!arguments.length)return a.translate();var g=a.scale()/1e3,h=f[0],i=f[1];a.translate(f),b.translate([h-400*g,i+170*g]),c.translate([h-190*g,i+200*g]),d.translate([h+580*g,i+430*g]);return e};return e.scale(a.scale())};var a=Math.PI/180;d3.geo.mercator=function(){function d(d){var e=d[0]/360,f=-(Math.log(Math.tan(Math.PI/4+d[1]*a/2))/a)/360;return[b*e+c[0],b*Math.max(-0.5,Math.min(.5,f))+c[1]]}var b=500,c=[480,250];d.invert=function(d){var e=(d[0]-c[0])/b,f=(d[1]-c[1])/b;return[360*e,2*Math.atan(Math.exp(-360*f*a))/a-90]},d.scale=function(a){if(!arguments.length)return b;b=+a;return d},d.translate=function(a){if(!arguments.length)return c;c=[+a[0],+a[1]];return d};return d},d3.geo.path=function(){function n(a){return Math.abs(d3.geom.polygon(a.map(f)).area())}function l(a){var b=d3.geom.polygon(a[0].map(f)),c=b.centroid(1),d=c[0],e=c[1],g=Math.abs(b.area()),h=0,i=a.length;while(++hd&&(d=a),ef&&(f=e)});return[[b,c],[d,f]]};var f={Feature:g,FeatureCollection:h,LineString:i,MultiLineString:j,MultiPoint:i,MultiPolygon:k,Point:l,Polygon:m};d3.geo.greatCircle=function(){function f(e,f){var g=b.call(this,e,f),h=c.call(this,e,f),i=g[0]*a,j=g[1]*a,k=h[0]*a,l=h[1]*a,m=Math.cos(i),n=Math.sin(i),o=Math.cos(j),p=Math.sin(j),q=Math.cos(k),r=Math.sin(k),s=Math.cos(l),t=Math.sin(l),e=Math.acos(p*t+o*s*Math.cos(k-i)),u=Math.sin(e),v=e/(d-1),w=-v,x=[],f=-1;while(++f id) return stop(); lock.active = id; @@ -1791,7 +1795,7 @@ function d3_transition(groups, id) { } event.start.dispatch.call(node, d, i); - d3.timer(tick, 0, then); + if (!tick(elapsed)) d3.timer(tick, 0, then); return 1; } @@ -1910,12 +1914,12 @@ d3_transitionPrototype.attrTween = function(name, tween) { return this.tween("attr." + name, name.local ? attrTweenNS : attrTween); }; d3_transitionPrototype.style = function(name, value, priority) { - if (arguments.length < 3) priority = null; + if (arguments.length < 3) priority = ""; return this.styleTween(name, d3_transitionTween(value), priority); }; d3_transitionPrototype.styleTween = function(name, tween, priority) { - if (arguments.length < 3) priority = null; + if (arguments.length < 3) priority = ""; return this.tween("style." + name, function(d, i) { var f = tween.call(this, d, i, window.getComputedStyle(this, null).getPropertyValue(name)); return f && function(t) { @@ -2368,23 +2372,24 @@ d3.scale.sqrt = function() { return d3.scale.pow().exponent(.5); }; d3.scale.ordinal = function() { - return d3_scale_ordinal({}, 0, {t: "range", x: []}); + return d3_scale_ordinal([], {t: "range", x: []}); }; -function d3_scale_ordinal(domain, size, ranger) { - var range, +function d3_scale_ordinal(domain, ranger) { + var index, + range, rangeBand; function scale(x) { - return range[((domain[x] || (domain[x] = ++size)) - 1) % range.length]; + return range[((index[x] || (index[x] = domain.push(x))) - 1) % range.length]; } scale.domain = function(x) { - if (!arguments.length) return d3.keys(domain); - domain = {}; - size = 0; + if (!arguments.length) return domain; + domain = []; + index = {}; var i = -1, n = x.length, xi; - while (++i < n) if (!domain[xi = x[i]]) domain[xi] = ++size; + while (++i < n) if (!index[xi = x[i]]) index[xi] = domain.push(xi); return scale[ranger.t](ranger.x, ranger.p); }; @@ -2400,8 +2405,8 @@ function d3_scale_ordinal(domain, size, ranger) { if (arguments.length < 2) padding = 0; var start = x[0], stop = x[1], - step = (stop - start) / (size - 1 + padding); - range = size < 2 ? [(start + stop) / 2] : d3.range(start + step * padding / 2, stop + step / 2, step); + step = (stop - start) / (domain.length - 1 + padding); + range = domain.length < 2 ? [(start + stop) / 2] : d3.range(start + step * padding / 2, stop + step / 2, step); rangeBand = 0; ranger = {t: "rangePoints", x: x, p: padding}; return scale; @@ -2411,7 +2416,7 @@ function d3_scale_ordinal(domain, size, ranger) { if (arguments.length < 2) padding = 0; var start = x[0], stop = x[1], - step = (stop - start) / (size + padding); + step = (stop - start) / (domain.length + padding); range = d3.range(start + step * padding, stop, step); rangeBand = step * (1 - padding); ranger = {t: "rangeBands", x: x, p: padding}; @@ -2422,8 +2427,8 @@ function d3_scale_ordinal(domain, size, ranger) { if (arguments.length < 2) padding = 0; var start = x[0], stop = x[1], - step = Math.floor((stop - start) / (size + padding)), - err = stop - start - (size - padding) * step; + step = Math.floor((stop - start) / (domain.length + padding)), + err = stop - start - (domain.length - padding) * step; range = d3.range(start + Math.round(err / 2), stop, step); rangeBand = Math.round(step * (1 - padding)); ranger = {t: "rangeRoundBands", x: x, p: padding}; @@ -2435,12 +2440,10 @@ function d3_scale_ordinal(domain, size, ranger) { }; scale.copy = function() { - var copy = {}, x; - for (x in domain) copy[x] = domain[x]; - return d3_scale_ordinal(copy, size, ranger); + return d3_scale_ordinal(domain, ranger); }; - return scale[ranger.t](ranger.x, ranger.p); + return scale.domain(domain); }; /* * This product includes color specifications and designs developed by Cynthia diff --git a/d3.layout.js b/d3.layout.js index 835aaa9d..6cc1d716 100644 --- a/d3.layout.js +++ b/d3.layout.js @@ -233,15 +233,15 @@ d3.layout.force = function() { /* Barnes-Hut criterion. */ if ((x2 - x1) * dn < theta) { var k = kc * quad.count * dn * dn; - node.x += dx * k; - node.y += dy * k; + node.px -= dx * k; + node.py -= dy * k; return true; } if (quad.point && isFinite(dn)) { var k = kc * dn * dn; - node.x += dx * k; - node.y += dy * k; + node.px -= dx * k; + node.py -= dy * k; } } }; @@ -250,12 +250,13 @@ d3.layout.force = function() { function tick() { var n = nodes.length, m = links.length, - q = d3.geom.quadtree(nodes), + q, i, // current index o, // current object s, // current source t, // current target l, // current distance + k, // current force x, // x-distance y; // y-distance @@ -270,30 +271,32 @@ d3.layout.force = function() { l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l; x *= l; y *= l; - t.x -= x / t.weight; - t.y -= y / t.weight; - s.x += x / s.weight; - s.y += y / s.weight; + t.x -= x * (k = s.weight / (t.weight + s.weight)); + t.y -= y * k; + s.x += x * (k = 1 - k); + s.y += y * k; } } // apply gravity forces - var kg = alpha * gravity; - x = size[0] / 2; - y = size[1] / 2; - i = -1; while (++i < n) { - o = nodes[i]; - o.x += (x - o.x) * kg; - o.y += (y - o.y) * kg; + if (k = alpha * gravity) { + x = size[0] / 2; + y = size[1] / 2; + i = -1; if (k) while (++i < n) { + o = nodes[i]; + o.x += (x - o.x) * k; + o.y += (y - o.y) * k; + } } - // compute quadtree center of mass - d3_layout_forceAccumulate(q); - - // apply charge forces - var kc = alpha * charge; - i = -1; while (++i < n) { - q.visit(repulse(nodes[i], kc)); + // compute quadtree center of mass and apply charge forces + if (k = alpha * charge) { + d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes)); + i = -1; while (++i < n) { + if (!(o = nodes[i]).fixed) { + q.visit(repulse(o, k)); + } + } } // position verlet integration diff --git a/d3.layout.min.js b/d3.layout.min.js index fca91d78..0deabfac 100644 --- a/d3.layout.min.js +++ b/d3.layout.min.js @@ -1 +1 @@ -(function(){function bc(a,b){var c=a.x+b[3],d=a.y+b[0],e=a.dx-b[1]-b[3],f=a.dy-b[0]-b[2];e<0&&(c+=e/2,e=0),f<0&&(d+=f/2,f=0);return{x:c,y:d,dx:e,dy:f}}function bb(a){return{x:a.x,y:a.y,dx:a.dx,dy:a.dy}}function ba(a,b,c){return a._tree.ancestor.parent==b.parent?a._tree.ancestor:c}function _(a,b,c){a=a._tree,b=b._tree;var d=c/(b.number-a.number);a.change+=d,b.change-=d,b.shift+=c,b.prelim+=c,b.mod+=c}function $(a){var b=0,c=0,d=a.children,e=d.length,f;while(--e>=0)f=d[e]._tree,f.prelim+=b,f.mod+=b,b+=f.shift+(c+=f.change)}function Z(a,b){function c(a,d){var e=a.children;if(e){var f,g=null,h=-1,i=e.length;while(++h0&&(a=d)}return a}function U(a){return a.children?a.children[a.children.length-1]:a._tree.thread}function T(a){return a.children?a.children[0]:a._tree.thread}function S(a,b){return a.parent==b.parent?1:2}function R(a){var b=a.children;return b?R(b[b.length-1]):a}function Q(a){var b=a.children;return b?Q(b[0]):a}function P(a){return a.reduce(function(a,b){return a+b.x},0)/a.length}function O(a){return 1+d3.max(a,function(a){return a.y})}function N(a,b,c){var d=b.r+c.r,e=a.r+c.r,f=b.x-a.x,g=b.y-a.y,h=Math.sqrt(f*f+g*g),i=(e*e+h*h-d*d)/(2*e*h),j=Math.acos(i),k=i*e,l=Math.sin(j)*e;f/=h,g/=h,c.x=a.x+k*f+l*g,c.y=a.y+k*g-l*f}function M(a,b,c,d){var e=a.children;a.x=b+=d*a.x,a.y=c+=d*a.y,a.r*=d;if(e){var f=-1,g=e.length;while(++f1){h=a[1],h.x=h.r,h.y=0,l(h);if(f>2){i=a[2],N(g,h,i),l(i),F(g,i),g._pack_prev=i,F(i,h),h=g._pack_next;for(var m=3;m0?(G(g,j),h=j,m--):(G(j,h),g=j,m--)}}}var q=(b+c)/2,r=(d+e)/2,s=0;for(var m=0;m.001}function G(a,b){a._pack_next=b,b._pack_prev=a}function F(a,b){var c=a._pack_next;a._pack_next=b,b._pack_prev=a,b._pack_next=c,c._pack_prev=b}function E(a,b){return a.value-b.value}function C(a){return d3.merge(a.map(function(a){return(a.children||[]).map(function(b){return{source:a,target:b}})}))}function B(a,b){return b.value-a.value}function A(a){return a.value}function z(a){return a.children}function y(a,b){a.sort=d3.rebind(a,b.sort),a.children=d3.rebind(a,b.children),a.links=C,a.value=d3.rebind(a,b.value),a.nodes=function(b){D=!0;return(a.nodes=a)(b)};return a}function x(a){return[d3.min(a),d3.max(a)]}function w(a,b){var c=-1,d=+a[0],e=(a[1]-d)/b,f=[];while(++c<=b)f[c]=e*c+d;return f}function v(a,b){return w(a,Math.ceil(Math.log(b.length)/Math.LN2+1))}function u(a,b){return a+b[1]}function t(a){return a.reduce(u,0)}function s(a){var b=1,c=0,d=a[0][1],e,f=a.length;for(;bd&&(c=b,d=e);return c}function p(a,b,c){a.y0=b,a.y=c}function o(a){return a.y}function n(a){return a.x}function m(a){return 1}function l(a){return 20}function k(a){var b=0,c=0;a.count=0;if(!a.leaf){var d=a.nodes,e=d.length,f=-1,g;while(++fe&&(e=h),d.push(h)}for(g=0;g=i[0]&&o<=i[1]&&(k=g[d3.bisect(j,o,1,m)-1],k.y+=n,k.push(e[f]));return g}var a=!0,b=Number,c=x,d=v;e.value=function(a){if(!arguments.length)return b;b=a;return e},e.range=function(a){if(!arguments.length)return c;c=d3.functor(a);return e},e.bins=function(a){if(!arguments.length)return d;d=typeof a=="number"?function(b){return w(b,a)}:d3.functor(a);return e},e.frequency=function(b){if(!arguments.length)return a;a=!!b;return e};return e},d3.layout.hierarchy=function(){function g(a){var b=[];e(a,0,b);return b}function f(a,b){var d=a.children,e=0;if(d){var h=-1,i=d.length,j=b+1;while(++h0&&(_(ba(g,a,d),a,m),i+=m,j+=m),k+=g._tree.mod,i+=e._tree.mod,l+=h._tree.mod,j+=f._tree.mod;g&&!U(f)&&(f._tree.thread=g,f._tree.mod+=k-j),e&&!T(h)&&(h._tree.thread=e,h._tree.mod+=i-l,d=a)}return d}function i(a,b){a.x=a._tree.prelim+b;var c=a.children;if(c){var d=-1,e=c.length;b+=a._tree.mod;while(++dd.dy)j=j?d.dy:0;while(++fd.dx)j=j?d.dx:0;while(++fe&&(e=d)}c*=c,b*=b;return c?Math.max(b*e*h/c,c/(b*f*h)):Infinity}function k(a){if(!!a.children){var b=e(a),c=a.children.slice(),d,f=[];i(c,b.dx*b.dy/a.value),f.area=0;while(d=c.pop())f.push(d),f.area+=d.area,d.z!=null&&(m(f,d.z?b.dx:b.dy,b,!c.length),f.length=f.area=0);a.children.forEach(k)}}function j(a){if(!!a.children){var b=e(a),c=[],d=a.children.slice(),f,g=Infinity,h,k=Math.min(b.dx,b.dy),n;i(d,b.dx*b.dy/a.value),c.area=0;while((n=d.length)>0)c.push(f=d[n-1]),c.area+=f.area,(h=l(c,k))<=g?(d.pop(),g=h):(c.area-=c.pop().area,m(c,k,b,!1),k=Math.min(b.dx,b.dy),c.length=c.area=0,g=Infinity);c.length&&(m(c,k,b,!0),c.length=c.area=0),a.children.forEach(j)}}function i(a,b){var c=-1,d=a.length,e,f;while(++c=0)f=d[e]._tree,f.prelim+=b,f.mod+=b,b+=f.shift+(c+=f.change)}function Z(a,b){function c(a,d){var e=a.children;if(e){var f,g=null,h=-1,i=e.length;while(++h0&&(a=d)}return a}function U(a){return a.children?a.children[a.children.length-1]:a._tree.thread}function T(a){return a.children?a.children[0]:a._tree.thread}function S(a,b){return a.parent==b.parent?1:2}function R(a){var b=a.children;return b?R(b[b.length-1]):a}function Q(a){var b=a.children;return b?Q(b[0]):a}function P(a){return a.reduce(function(a,b){return a+b.x},0)/a.length}function O(a){return 1+d3.max(a,function(a){return a.y})}function N(a,b,c){var d=b.r+c.r,e=a.r+c.r,f=b.x-a.x,g=b.y-a.y,h=Math.sqrt(f*f+g*g),i=(e*e+h*h-d*d)/(2*e*h),j=Math.acos(i),k=i*e,l=Math.sin(j)*e;f/=h,g/=h,c.x=a.x+k*f+l*g,c.y=a.y+k*g-l*f}function M(a,b,c,d){var e=a.children;a.x=b+=d*a.x,a.y=c+=d*a.y,a.r*=d;if(e){var f=-1,g=e.length;while(++f1){h=a[1],h.x=h.r,h.y=0,l(h);if(f>2){i=a[2],N(g,h,i),l(i),F(g,i),g._pack_prev=i,F(i,h),h=g._pack_next;for(var m=3;m0?(G(g,j),h=j,m--):(G(j,h),g=j,m--)}}}var q=(b+c)/2,r=(d+e)/2,s=0;for(var m=0;m.001}function G(a,b){a._pack_next=b,b._pack_prev=a}function F(a,b){var c=a._pack_next;a._pack_next=b,b._pack_prev=a,b._pack_next=c,c._pack_prev=b}function E(a,b){return a.value-b.value}function C(a){return d3.merge(a.map(function(a){return(a.children||[]).map(function(b){return{source:a,target:b}})}))}function B(a,b){return b.value-a.value}function A(a){return a.value}function z(a){return a.children}function y(a,b){a.sort=d3.rebind(a,b.sort),a.children=d3.rebind(a,b.children),a.links=C,a.value=d3.rebind(a,b.value),a.nodes=function(b){D=!0;return(a.nodes=a)(b)};return a}function x(a){return[d3.min(a),d3.max(a)]}function w(a,b){var c=-1,d=+a[0],e=(a[1]-d)/b,f=[];while(++c<=b)f[c]=e*c+d;return f}function v(a,b){return w(a,Math.ceil(Math.log(b.length)/Math.LN2+1))}function u(a,b){return a+b[1]}function t(a){return a.reduce(u,0)}function s(a){var b=1,c=0,d=a[0][1],e,f=a.length;for(;bd&&(c=b,d=e);return c}function p(a,b,c){a.y0=b,a.y=c}function o(a){return a.y}function n(a){return a.x}function m(a){return 1}function l(a){return 20}function k(a){var b=0,c=0;a.count=0;if(!a.leaf){var d=a.nodes,e=d.length,f=-1,g;while(++fe&&(e=h),d.push(h)}for(g=0;g=i[0]&&o<=i[1]&&(k=g[d3.bisect(j,o,1,m)-1],k.y+=n,k.push(e[f]));return g}var a=!0,b=Number,c=x,d=v;e.value=function(a){if(!arguments.length)return b;b=a;return e},e.range=function(a){if(!arguments.length)return c;c=d3.functor(a);return e},e.bins=function(a){if(!arguments.length)return d;d=typeof a=="number"?function(b){return w(b,a)}:d3.functor(a);return e},e.frequency=function(b){if(!arguments.length)return a;a=!!b;return e};return e},d3.layout.hierarchy=function(){function g(a){var b=[];e(a,0,b);return b}function f(a,b){var d=a.children,e=0;if(d){var h=-1,i=d.length,j=b+1;while(++h0&&(_(ba(g,a,d),a,m),i+=m,j+=m),k+=g._tree.mod,i+=e._tree.mod,l+=h._tree.mod,j+=f._tree.mod;g&&!U(f)&&(f._tree.thread=g,f._tree.mod+=k-j),e&&!T(h)&&(h._tree.thread=e,h._tree.mod+=i-l,d=a)}return d}function i(a,b){a.x=a._tree.prelim+b;var c=a.children;if(c){var d=-1,e=c.length;b+=a._tree.mod;while(++dd.dy)j=j?d.dy:0;while(++fd.dx)j=j?d.dx:0;while(++fe&&(e=d)}c*=c,b*=b;return c?Math.max(b*e*h/c,c/(b*f*h)):Infinity}function k(a){if(!!a.children){var b=e(a),c=a.children.slice(),d,f=[];i(c,b.dx*b.dy/a.value),f.area=0;while(d=c.pop())f.push(d),f.area+=d.area,d.z!=null&&(m(f,d.z?b.dx:b.dy,b,!c.length),f.length=f.area=0);a.children.forEach(k)}}function j(a){if(!!a.children){var b=e(a),c=[],d=a.children.slice(),f,g=Infinity,h,k=Math.min(b.dx,b.dy),n;i(d,b.dx*b.dy/a.value),c.area=0;while((n=d.length)>0)c.push(f=d[n-1]),c.area+=f.area,(h=l(c,k))<=g?(d.pop(),g=h):(c.area-=c.pop().area,m(c,k,b,!1),k=Math.min(b.dx,b.dy),c.length=c.area=0,g=Infinity);c.length&&(m(c,k,b,!0),c.length=c.area=0),a.children.forEach(j)}}function i(a,b){var c=-1,d=a.length,e,f;while(++c1){var d=bm(a.domain()),e,f=-1,g=b.length,h=(b[1]-b[0])/++c,i,j;while(++f0;)(j=+b[f]-i*h)>=d[0]&&e.push(j);for(--f,i=0;++i9&&(f=c*3/Math.sqrt(f),g[h]=f*d,g[h+1]=f*e));h=-1;while(++h<=i)f=(a[Math.min(i,h+1)][0]-a[Math.max(0,h-1)][0])/(6*(1+g[h]*g[h])),b.push([f||0,g[h]*f||0]);return b}function cl(a){var b=0,c=a.length-1,d=[],e=a[0],f=a[1],g=d[0]=ck(e,f);while(++b1){h=b[1],f=a[i],i++,d+="C"+(e[0]+g[0])+","+(e[1]+g[1])+","+(f[0]-h[0])+","+(f[1]-h[1])+","+f[0]+","+f[1];for(var j=2;j0;j--)e.push(c(f)*j)}else{for(;fi;g--);e=e.slice(f,g)}return e},d.tickFormat=function(){return bA},d.copy=function(){return bx(a.copy(),b)};return bq(d,a)}function bw(a,b,c,d){var e=[],f=[],g=0,h=a.length;while(++g=c.delay&&(c.flush=c.callback(a)),c=c.next;var d=bj()-b;d>24?(isFinite(d)&&(clearTimeout(bh),bh=setTimeout(bi,d)),bg=0):(bg=1,bk(bi))}function be(a){for(var b=0,c=this.length;b0)k[--g].call(l,d);if(b===1){r(),bc=c,e.end.dispatch.call(l,h,i),bc=0;return 1}}function p(){if(o.active>c)return r();o.active=c;for(var a in d)(a=d[a].call(l,h,i))&&k.push(a);e.start.dispatch.call(l,h,i),d3.timer(q,0,g);return 1}var k=[],l=this,m=b[j][i].delay,n=b[j][i].duration,o=l.__transition__||(l.__transition__={active:0,count:0});++o.count,m<=a?p():d3.timer(p,m,g)});return 1},0,g);return b}function Y(a){arguments.length||(a=d3.ascending);return function(b,c){return a(b&&b.__data__,c&&c.__data__)}}function W(b){a(b,X);return b}function V(a){return{__data__:a}}function U(a){return function(){return R(a,this)}}function T(a){return function(){return Q(a,this)}}function P(b){a(b,S);return b}function O(a,b,c){function g(a){return Math.round(f(a)*255)}function f(a){a>360?a-=360:a<0&&(a+=360);return a<60?d+(e-d)*a/60:a<180?e:a<240?d+(e-d)*(240-a)/60:d}var d,e;a=a%360,a<0&&(a+=360),b=b<0?0:b>1?1:b,c=c<0?0:c>1?1:c,e=c<=.5?c*(1+b):c+b-c*b,d=2*c-e;return E(g(a+120),g(a),g(a-120))}function N(a,b,c){this.h=a,this.s=b,this.l=c}function M(a,b,c){return new N(a,b,c)}function J(a){var b=parseFloat(a);return a.charAt(a.length-1)==="%"?Math.round(b*2.55):b}function I(a,b,c){var d=Math.min(a/=255,b/=255,c/=255),e=Math.max(a,b,c),f=e-d,g,h,i=(e+d)/2;f?(h=i<.5?f/(e+d):f/(2-e-d),a==e?g=(b-c)/f+(b=0?a.substring(b):(b=a.length,""),d=[];while(b>0)d.push(a.substring(b-=3,b+3));return d.reverse().join(",")+c}function j(a){return a+""}function g(a){var b={},c=[];b.add=function(a){for(var d=0;db?1:a>=b?0:NaN},d3.descending=function(a,b){return ba?1:b>=a?0:NaN},d3.min=function(a,b){var c=-1,d=a.length,e,f;if(arguments.length===1){while(++cf&&(e=f)}else{while(++cf&&(e=f)}return e},d3.max=function(a,b){var c=-1,d=a.length,e,f;if(arguments.length===1){while(++ce&&(e=f)}else{while(++ce&&(e=f)}return e},d3.sum=function(a,b){var c=0,d=a.length,e,f=-1;if(arguments.length===1)while(++f>1;a[e]>1;b0&&(e=f);return e},d3.last=function(a,b){var c=0,d=a.length,e=a[0],f;arguments.length===1&&(b=d3.ascending);while(++c=b.length)return a;var e=[],f=c[d++],h;for(h in a)e.push({key:h,values:g(a[h],d)});f&&e.sort(function(a,b){return f(a.key,b.key)});return e}function f(c,g){if(g>=b.length)return e?e.call(a,c):d?c.sort(d):c;var h=-1,i=c.length,j=b[g++],k,l,m={};while(++hb)d.push(f);else while((f=a+c*++e)=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/,i={g:function(a,b){return a.toPrecision(b)},e:function(a,b){return a.toExponential(b)},f:function(a,b){return a.toFixed(b)},r:function(a,b){var c=1+Math.floor(1e-15+Math.log(a)/Math.LN10);return d3.round(a,b-c).toFixed(Math.max(0,Math.min(20,b-c)))}},l=s(2),m=s(3),n={linear:function(){return r},poly:s,quad:function(){return l},cubic:function(){return m},sin:function(){return t},exp:function(){return u},circle:function(){return v},elastic:w,back:x,bounce:function(){return y}},o={"in":function(a){return a},out:p,"in-out":q,"out-in":function(a){return q(p(a))}};d3.ease=function(a){var b=a.indexOf("-"),c=b>=0?a.substring(0,b):a,d=b>=0?a.substring(b+1):"in";return o[d](n[c].apply(null,Array.prototype.slice.call(arguments,1)))},d3.event=null,d3.interpolate=function(a,b){var c=d3.interpolators.length,d;while(--c>=0&&!(d=d3.interpolators[c](a,b)));return d},d3.interpolateNumber=function(a,b){b-=a;return function(c){return a+b*c}},d3.interpolateRound=function(a,b){b-=a;return function(c){return Math.round(a+b*c)}},d3.interpolateString=function(a,b){var c,d,e,f=0,g=0,h=[],i=[],j,k;z.lastIndex=0;for(d=0;c=z.exec(b);++d)c.index&&h.push(b.substring(f,g=c.index)),i.push({i:h.length,x:c[0]}),h.push(null),f=z.lastIndex;f0&&(a=a.substring(0,e));return arguments.length<2?(e=this.node()[d])&&e._:this.each(function(e,f){function h(a){var c=d3.event;d3.event=a;try{b.call(g,g.__data__,f)}finally{d3.event=c}}var g=this;g[d]&&g.removeEventListener(a,g[d],c),b&&g.addEventListener(a,g[d]=h,c),h._=b})},S.each=function(a){for(var b=-1,c=this.length;++b=bL?e?"M0,"+f+"A"+f+","+f+" 0 1,1 0,"+ -f+"A"+f+","+f+" 0 1,1 0,"+f+"M0,"+e+"A"+e+","+e+" 0 1,1 0,"+ -e+"A"+e+","+e+" 0 1,1 0,"+e+"Z":"M0,"+f+"A"+f+","+f+" 0 1,1 0,"+ -f+"A"+f+","+f+" 0 1,1 0,"+f+"Z":e?"M"+f*k+","+f*l+"A"+f+","+f+" 0 "+j+",1 "+f*m+","+f*n+"L"+e*m+","+e*n+"A"+e+","+e+" 0 "+j+",0 "+e*k+","+e*l+"Z":"M"+f*k+","+f*l+"A"+f+","+f+" 0 "+j+",1 "+f*m+","+f*n+"L0,0"+"Z"}var a=bM,b=bN,c=bO,d=bP;e.innerRadius=function(b){if(!arguments.length)return a;a=d3.functor(b);return e},e.outerRadius=function(a){if(!arguments.length)return b;b=d3.functor(a);return e},e.startAngle=function(a){if(!arguments.length)return c;c=d3.functor(a);return e},e.endAngle=function(a){if(!arguments.length)return d;d=d3.functor(a);return e},e.centroid=function(){var e=(a.apply(this,arguments)+b.apply(this,arguments))/2,f=(c.apply(this,arguments)+d.apply(this,arguments))/2+bK;return[Math.cos(f)*e,Math.sin(f)*e]};return e};var bK=-Math.PI/2,bL=2*Math.PI-1e-6;d3.svg.line=function(){return bQ(Object)};var bU={linear:bV,"step-before":bW,"step-after":bX,basis:cb,"basis-open":cc,"basis-closed":cd,bundle:ce,cardinal:b$,"cardinal-open":bY,"cardinal-closed":bZ,monotone:cn},cg=[0,2/3,1/3,0],ch=[0,1/3,2/3,0],ci=[0,1/6,2/3,1/6];d3.svg.line.radial=function(){var a=bQ(co);a.radius=a.x,delete a.x,a.angle=a.y,delete a.y;return a},d3.svg.area=function(){return cp(Object)},d3.svg.area.radial=function(){var a=cp(co);a.radius=a.x,delete a.x,a.innerRadius=a.x0,delete a.x0,a.outerRadius=a.x1,delete a.x1,a.angle=a.y,delete a.y,a.startAngle=a.y0,delete a.y0,a.endAngle=a.y1,delete a.y1;return a},d3.svg.chord=function(){function j(a,b,c,d){return"Q 0,0 "+d}function i(a,b){return"A"+a+","+a+" 0 0,1 "+b}function h(a,b){return a.a0==b.a0&&a.a1==b.a1}function g(a,b,f,g){var h=b.call(a,f,g),i=c.call(a,h,g),j=d.call(a,h,g)+bK,k=e.call(a,h,g)+bK;return{r:i,a0:j,a1:k,p0:[i*Math.cos(j),i*Math.sin(j)],p1:[i*Math.cos(k),i*Math.sin(k)]}}function f(c,d){var e=g(this,a,c,d),f=g(this,b,c,d);return"M"+e.p0+i(e.r,e.p1)+(h(e,f)?j(e.r,e.p1,e.r,e.p0):j(e.r,e.p1,f.r,f.p0)+i(f.r,f.p1)+j(f.r,f.p1,e.r,e.p0))+"Z"}var a=cs,b=ct,c=cu,d=bO,e=bP;f.radius=function(a){if(!arguments.length)return c;c=d3.functor(a);return f},f.source=function(b){if(!arguments.length)return a;a=d3.functor(b);return f},f.target=function(a){if(!arguments.length)return b;b=d3.functor(a);return f},f.startAngle=function(a){if(!arguments.length)return d;d=d3.functor(a);return f},f.endAngle=function(a){if(!arguments.length)return e;e=d3.functor(a);return f};return f},d3.svg.diagonal=function(){function d(d,e){var f=a.call(this,d,e),g=b.call(this,d,e),h=(f.y+g.y)/2,i=[f,{x:f.x,y:h},{x:g.x,y:h},g];i=i.map(c);return"M"+i[0]+"C"+i[1]+" "+i[2]+" "+i[3]}var a=cs,b=ct,c=cx;d.source=function(b){if(!arguments.length)return a;a=d3.functor(b);return d},d.target=function(a){if(!arguments.length)return b;b=d3.functor(a);return d},d.projection=function(a){if(!arguments.length)return c;c=a;return d};return d},d3.svg.diagonal.radial=function(){var a=d3.svg.diagonal(),b=cx,c=a.projection;a.projection=function(a){return arguments.length?c(cy(b=a)):b};return a},d3.svg.mouse=function(a){return cA(a,d3.event)};var cz=/WebKit/.test(navigator.userAgent)?-1:0;d3.svg.touches=function(a){var b=d3.event.touches;return b?Array.prototype.map.call(b,function(b){var c=cA(a,b);c.identifier=b.identifier;return c}):[]},d3.svg.symbol=function(){function c(c,d){return(cD[a.call(this,c,d)]||cD.circle)(b.call(this,c,d))}var a=cC,b=cB;c.type=function(b){if(!arguments.length)return a;a=d3.functor(b);return c},c.size=function(a){if(!arguments.length)return b;b=d3.functor(a);return c};return c};var cD={circle:function(a){var b=Math.sqrt(a/Math.PI);return"M0,"+b+"A"+b+","+b+" 0 1,1 0,"+ -b+"A"+b+","+b+" 0 1,1 0,"+b+"Z"},cross:function(a){var b=Math.sqrt(a/5)/2;return"M"+ -3*b+","+ -b+"H"+ -b+"V"+ -3*b+"H"+b+"V"+ -b+"H"+3*b+"V"+b+"H"+b+"V"+3*b+"H"+ -b+"V"+b+"H"+ -3*b+"Z"},diamond:function(a){var b=Math.sqrt(a/(2*cF)),c=b*cF;return"M0,"+ -b+"L"+c+",0"+" 0,"+b+" "+ -c+",0"+"Z"},square:function(a){var b=Math.sqrt(a)/2;return"M"+ -b+","+ -b+"L"+b+","+ -b+" "+b+","+b+" "+ -b+","+b+"Z"},"triangle-down":function(a){var b=Math.sqrt(a/cE),c=b*cE/2;return"M0,"+c+"L"+b+","+ -c+" "+ -b+","+ -c+"Z"},"triangle-up":function(a){var b=Math.sqrt(a/cE),c=b*cE/2;return"M0,"+ -c+"L"+b+","+c+" "+ -b+","+c+"Z"}};d3.svg.symbolTypes=d3.keys(cD);var cE=Math.sqrt(3),cF=Math.tan(30*Math.PI/180);d3.svg.axis=function(){function j(j){j.each(function(k,l,m){function F(a){return j.delay?a.transition().delay(j[m][l].delay).duration(j[m][l].duration).ease(j.ease()):a}var n=d3.select(this),o=a.ticks.apply(a,g),p=h==null?a.tickFormat.apply(a,g):h,q=cI(a,o,i),r=n.selectAll(".minor").data(q,String),s=r.enter().insert("svg:line","g").attr("class","tick minor").style("opacity",1e-6),t=F(r.exit()).style("opacity",1e-6).remove(),u=F(r).style("opacity",1),v=n.selectAll("g").data(o,String),w=v.enter().insert("svg:g","path").style("opacity",1e-6),x=F(v.exit()).style("opacity",1e-6).remove(),y=F(v).style("opacity",1),z,A=bm(a.range()),B=n.selectAll(".domain").data([]),C=B.enter().append("svg:path").attr("class","domain"),D=F(B),E=this.__chart__||a;this.__chart__=a.copy(),w.append("svg:line").attr("class","tick"),w.append("svg:text"),y.select("text").text(p);switch(b){case"bottom":z=cG,u.attr("y2",d),w.select("text").attr("dy",".71em").attr("text-anchor","middle"),y.select("line").attr("y2",c),y.select("text").attr("y",Math.max(c,0)+f),D.attr("d","M"+A[0]+","+e+"V0H"+A[1]+"V"+e);break;case"top":z=cG,u.attr("y2",-d),w.select("text").attr("text-anchor","middle"),y.select("line").attr("y2",-c),y.select("text").attr("y",-(Math.max(c,0)+f)),D.attr("d","M"+A[0]+","+ -e+"V0H"+A[1]+"V"+ -e);break;case"left":z=cH,u.attr("x2",-d),w.select("text").attr("dy",".32em").attr("text-anchor","end"),y.select("line").attr("x2",-c),y.select("text").attr("x",-(Math.max(c,0)+f)),D.attr("d","M"+ -e+","+A[0]+"H0V"+A[1]+"H"+ -e);break;case"right":z=cH,u.attr("x2",d),w.select("text").attr("dy",".32em"),y.select("line").attr("x2",c),y.select("text").attr("x",Math.max(c,0)+f),D.attr("d","M"+e+","+A[0]+"H0V"+A[1]+"H"+e)}w.call(z,E),y.call(z,a),x.call(z,a),s.call(z,E),u.call(z,a),t.call(z,a)})}var a=d3.scale.linear(),b="bottom",c=6,d=6,e=6,f=3,g=[10],h,i=0;j.scale=function(b){if(!arguments.length)return a;a=b;return j},j.orient=function(a){if(!arguments.length)return b;b=a;return j},j.ticks=function(){if(!arguments.length)return g;g=arguments;return j},j.tickFormat=function(a){if(!arguments.length)return h;h=a;return j},j.tickSize=function(a,b,f){if(!arguments.length)return c;var g=arguments.length-1;c=+a,d=g>1?+b:c,e=g>0?+arguments[g]:c;return j},j.tickPadding=function(a){if(!arguments.length)return f;f=+a;return j},j.tickSubdivide=function(a){if(!arguments.length)return i;i=+a;return j};return j},d3.behavior={},d3.behavior.drag=function(){function d(){c.apply(this,arguments),cP("dragstart")}function c(){cJ=a,cM=cQ((cK=this).parentNode),cN=0,cL=arguments}function b(){this.on("mousedown.drag",d).on("touchstart.drag",d),d3.select(window).on("mousemove.drag",cR).on("touchmove.drag",cR).on("mouseup.drag",cS,!0).on("touchend.drag",cS,!0).on("click.drag",cT,!0)}var a=d3.dispatch("drag","dragstart","dragend");b.on=function(c,d){a[c].add(d);return b};return b};var cJ,cK,cL,cM,cN,cO;d3.behavior.zoom=function(){function h(){d.apply(this,arguments);var b=dg(),c,e=Date.now();b.length===1&&e-cZ<300&&dl(1+Math.floor(a[2]),c=b[0],cY[c.identifier]),cZ=e}function g(){d.apply(this,arguments);var b=d3.svg.mouse(da);dl(d3.event.shiftKey?Math.ceil(a[2]-1):Math.floor(a[2]+1),b,de(b))}function f(){d.apply(this,arguments),cX||(cX=de(d3.svg.mouse(da))),dl(df()+a[2],d3.svg.mouse(da),cX)}function e(){d.apply(this,arguments),cW=de(d3.svg.mouse(da)),dc=!1,d3.event.preventDefault(),window.focus()}function d(){c$=a,c_=b.zoom.dispatch,da=this,db=arguments}function c(){this.on("mousedown.zoom",e).on("mousewheel.zoom",f).on("DOMMouseScroll.zoom",f).on("dblclick.zoom",g).on("touchstart.zoom",h),d3.select(window).on("mousemove.zoom",di).on("mouseup.zoom",dj).on("touchmove.zoom",dh).on("touchend.zoom",dg).on("click.zoom",dk,!0)}var a=[0,0,0],b=d3.dispatch("zoom");c.on=function(a,d){b[a].add(d);return c};return c};var cV,cW,cX,cY={},cZ=0,c$,c_,da,db,dc,dd})() \ No newline at end of file +(function(){function dp(a,b,c){function i(a,b){var c=a.__domain||(a.__domain=a.domain()),d=a.range().map(function(a){return(a-b)/h});a.domain(c).domain(d.map(a.invert))}var d=Math.pow(2,(db[2]=a)-c[2]),e=db[0]=b[0]-d*c[0],f=db[1]=b[1]-d*c[1],g=d3.event,h=Math.pow(2,a);d3.event={scale:h,translate:[e,f],transform:function(a,b){a&&i(a,e),b&&i(b,f)}};try{dc.apply(dd,de)}finally{d3.event=g}g.preventDefault()}function dn(){dg&&(d3.event.stopPropagation(),d3.event.preventDefault(),dg=!1)}function dm(){cZ&&(df&&(dg=!0),dl(),cZ=null)}function dl(){c$=null,cZ&&(df=!0,dp(db[2],d3.svg.mouse(dd),cZ))}function dk(){var a=d3.svg.touches(dd);switch(a.length){case 1:var b=a[0];dp(db[2],b,c_[b.identifier]);break;case 2:var c=a[0],d=a[1],e=[(c[0]+d[0])/2,(c[1]+d[1])/2],f=c_[c.identifier],g=c_[d.identifier],h=[(f[0]+g[0])/2,(f[1]+g[1])/2,f[2]];dp(Math.log(d3.event.scale)/Math.LN2+f[2],e,h)}}function dj(){var a=d3.svg.touches(dd),b=-1,c=a.length,d;while(++b1){var d=bp(a.domain()),e,f=-1,g=b.length,h=(b[1]-b[0])/++c,i,j;while(++f0;)(j=+b[f]-i*h)>=d[0]&&e.push(j);for(--f,i=0;++i9&&(f=c*3/Math.sqrt(f),g[h]=f*d,g[h+1]=f*e));h=-1;while(++h<=i)f=(a[Math.min(i,h+1)][0]-a[Math.max(0,h-1)][0])/(6*(1+g[h]*g[h])),b.push([f||0,g[h]*f||0]);return b}function co(a){var b=0,c=a.length-1,d=[],e=a[0],f=a[1],g=d[0]=cn(e,f);while(++b1){h=b[1],f=a[i],i++,d+="C"+(e[0]+g[0])+","+(e[1]+g[1])+","+(f[0]-h[0])+","+(f[1]-h[1])+","+f[0]+","+f[1];for(var j=2;j0;j--)e.push(c(f)*j)}else{for(;fi;g--);e=e.slice(f,g)}return e},d.tickFormat=function(){return bD},d.copy=function(){return bA(a.copy(),b)};return bt(d,a)}function bz(a,b,c,d){var e=[],f=[],g=0,h=a.length;while(++g=c.delay&&(c.flush=c.callback(a)),c=c.next;var d=bm()-b;d>24?(isFinite(d)&&(clearTimeout(bk),bk=setTimeout(bl,d)),bj=0):(bj=1,bn(bl))}function bh(a){for(var b=0,c=this.length;b0)k[--g].call(l,d);if(c===1){r(),bf=b,e.end.dispatch.call(l,h,i),bf=0;return 1}}function p(a){if(o.active>b)return r();o.active=b;for(var d in c)(d=c[d].call(l,h,i))&&k.push(d);e.start.dispatch.call(l,h,i),q(a)||d3.timer(q,0,g);return 1}var k=[],l=this,m=a[j][i].delay,n=a[j][i].duration,o=l.__transition__||(l.__transition__={active:0,count:0});++o.count,m<=d?p():d3.timer(p,m,g)});return 1},0,g);return a}function _(a){arguments.length||(a=d3.ascending);return function(b,c){return a(b&&b.__data__,c&&c.__data__)}}function Z(a){d(a,$);return a}function Y(a){return{__data__:a}}function X(a){return function(){return U(a,this)}}function W(a){return function(){return T(a,this)}}function S(a){d(a,V);return a}function R(a,b,c){function g(a){return Math.round(f(a)*255)}function f(a){a>360?a-=360:a<0&&(a+=360);return a<60?d+(e-d)*a/60:a<180?e:a<240?d+(e-d)*(240-a)/60:d}var d,e;a=a%360,a<0&&(a+=360),b=b<0?0:b>1?1:b,c=c<0?0:c>1?1:c,e=c<=.5?c*(1+b):c+b-c*b,d=2*c-e;return H(g(a+120),g(a),g(a-120))}function Q(a,b,c){this.h=a,this.s=b,this.l=c}function P(a,b,c){return new Q(a,b,c)}function M(a){var b=parseFloat(a);return a.charAt(a.length-1)==="%"?Math.round(b*2.55):b}function L(a,b,c){var d=Math.min(a/=255,b/=255,c/=255),e=Math.max(a,b,c),f=e-d,g,h,i=(e+d)/2;f?(h=i<.5?f/(e+d):f/(2-e-d),a==e?g=(b-c)/f+(b=0?a.substring(b):(b=a.length,""),d=[];while(b>0)d.push(a.substring(b-=3,b+3));return d.reverse().join(",")+c}function m(a){return a+""}function j(a){var b={},c=[];b.add=function(a){for(var d=0;db?1:a>=b?0:NaN},d3.descending=function(a,b){return ba?1:b>=a?0:NaN},d3.min=function(a,b){var c=-1,d=a.length,e,f;if(arguments.length===1){while(++cf&&(e=f)}else{while(++cf&&(e=f)}return e},d3.max=function(a,b){var c=-1,d=a.length,e,f;if(arguments.length===1){while(++ce&&(e=f)}else{while(++ce&&(e=f)}return e},d3.sum=function(a,b){var c=0,d=a.length,e,f=-1;if(arguments.length===1)while(++f>1;a[e]>1;b0&&(e=f);return e},d3.last=function(a,b){var c=0,d=a.length,e=a[0],f;arguments.length===1&&(b=d3.ascending);while(++c=b.length)return a;var e=[],f=c[d++],h;for(h in a)e.push({key:h,values:g(a[h],d)});f&&e.sort(function(a,b){return f(a.key,b.key)});return e}function f(c,g){if(g>=b.length)return e?e.call(a,c):d?c.sort(d):c;var h=-1,i=c.length,j=b[g++],k,l,m={};while(++hb)d.push(f);else while((f=a+c*++e)=^]))?([+\- ])?(#)?(0)?([0-9]+)?(,)?(\.[0-9]+)?([a-zA-Z%])?/,l={g:function(a,b){return a.toPrecision(b)},e:function(a,b){return a.toExponential(b)},f:function(a,b){return a.toFixed(b)},r:function(a,b){var c=1+Math.floor(1e-15+Math.log(a)/Math.LN10);return d3.round(a,b-c).toFixed(Math.max(0,Math.min(20,b-c)))}},o=v(2),p=v(3),q={linear:function(){return u},poly:v,quad:function(){return o},cubic:function(){return p},sin:function(){return w},exp:function(){return x},circle:function(){return y},elastic:z,back:A,bounce:function(){return B}},r={"in":function(a){return a},out:s,"in-out":t,"out-in":function(a){return t(s(a))}};d3.ease=function(a){var b=a.indexOf("-"),c=b>=0?a.substring(0,b):a,d=b>=0?a.substring(b+1):"in";return r[d](q[c].apply(null,Array.prototype.slice.call(arguments,1)))},d3.event=null,d3.interpolate=function(a,b){var c=d3.interpolators.length,d;while(--c>=0&&!(d=d3.interpolators[c](a,b)));return d},d3.interpolateNumber=function(a,b){b-=a;return function(c){return a+b*c}},d3.interpolateRound=function(a,b){b-=a;return function(c){return Math.round(a+b*c)}},d3.interpolateString=function(a,b){var c,d,e,f=0,g=0,h=[],i=[],j,k;C.lastIndex=0;for(d=0;c=C.exec(b);++d)c.index&&h.push(b.substring(f,g=c.index)),i.push({i:h.length,x:c[0]}),h.push(null),f=C.lastIndex;f0&&(a=a.substring(0,e));return arguments.length<2?(e=this.node()[d])&&e._:this.each(function(e,f){function h(a){var c=d3.event;d3.event=a;try{b.call(g,g.__data__,f)}finally{d3.event=c}}var g=this;g[d]&&g.removeEventListener(a,g[d],c),b&&g.addEventListener(a,g[d]=h,c),h._=b})},V.each=function(a){for(var b=-1,c=this.length;++b=bO?e?"M0,"+f+"A"+f+","+f+" 0 1,1 0,"+ -f+"A"+f+","+f+" 0 1,1 0,"+f+"M0,"+e+"A"+e+","+e+" 0 1,1 0,"+ -e+"A"+e+","+e+" 0 1,1 0,"+e+"Z":"M0,"+f+"A"+f+","+f+" 0 1,1 0,"+ -f+"A"+f+","+f+" 0 1,1 0,"+f+"Z":e?"M"+f*k+","+f*l+"A"+f+","+f+" 0 "+j+",1 "+f*m+","+f*n+"L"+e*m+","+e*n+"A"+e+","+e+" 0 "+j+",0 "+e*k+","+e*l+"Z":"M"+f*k+","+f*l+"A"+f+","+f+" 0 "+j+",1 "+f*m+","+f*n+"L0,0"+"Z"}var a=bP,b=bQ,c=bR,d=bS;e.innerRadius=function(b){if(!arguments.length)return a;a=d3.functor(b);return e},e.outerRadius=function(a){if(!arguments.length)return b;b=d3.functor(a);return e},e.startAngle=function(a){if(!arguments.length)return c;c=d3.functor(a);return e},e.endAngle=function(a){if(!arguments.length)return d;d=d3.functor(a);return e},e.centroid=function(){var e=(a.apply(this,arguments)+b.apply(this,arguments))/2,f=(c.apply(this,arguments)+d.apply(this,arguments))/2+bN;return[Math.cos(f)*e,Math.sin(f)*e]};return e};var bN=-Math.PI/2,bO=2*Math.PI-1e-6;d3.svg.line=function(){return bT(Object)};var bX={linear:bY,"step-before":bZ,"step-after":b$,basis:ce,"basis-open":cf,"basis-closed":cg,bundle:ch,cardinal:cb,"cardinal-open":b_,"cardinal-closed":ca,monotone:cq},cj=[0,2/3,1/3,0],ck=[0,1/3,2/3,0],cl=[0,1/6,2/3,1/6];d3.svg.line.radial=function(){var a=bT(cr);a.radius=a.x,delete a.x,a.angle=a.y,delete a.y;return a},d3.svg.area=function(){return cs(Object)},d3.svg.area.radial=function(){var a=cs(cr);a.radius=a.x,delete a.x,a.innerRadius=a.x0,delete a.x0,a.outerRadius=a.x1,delete a.x1,a.angle=a.y,delete a.y,a.startAngle=a.y0,delete a.y0,a.endAngle=a.y1,delete a.y1;return a},d3.svg.chord=function(){function j(a,b,c,d){return"Q 0,0 "+d}function i(a,b){return"A"+a+","+a+" 0 0,1 "+b}function h(a,b){return a.a0==b.a0&&a.a1==b.a1}function g(a,b,f,g){var h=b.call(a,f,g),i=c.call(a,h,g),j=d.call(a,h,g)+bN,k=e.call(a,h,g)+bN;return{r:i,a0:j,a1:k,p0:[i*Math.cos(j),i*Math.sin(j)],p1:[i*Math.cos(k),i*Math.sin(k)]}}function f(c,d){var e=g(this,a,c,d),f=g(this,b,c,d);return"M"+e.p0+i(e.r,e.p1)+(h(e,f)?j(e.r,e.p1,e.r,e.p0):j(e.r,e.p1,f.r,f.p0)+i(f.r,f.p1)+j(f.r,f.p1,e.r,e.p0))+"Z"}var a=cv,b=cw,c=cx,d=bR,e=bS;f.radius=function(a){if(!arguments.length)return c;c=d3.functor(a);return f},f.source=function(b){if(!arguments.length)return a;a=d3.functor(b);return f},f.target=function(a){if(!arguments.length)return b;b=d3.functor(a);return f},f.startAngle=function(a){if(!arguments.length)return d;d=d3.functor(a);return f},f.endAngle=function(a){if(!arguments.length)return e;e=d3.functor(a);return f};return f},d3.svg.diagonal=function(){function d(d,e){var f=a.call(this,d,e),g=b.call(this,d,e),h=(f.y+g.y)/2,i=[f,{x:f.x,y:h},{x:g.x,y:h},g];i=i.map(c);return"M"+i[0]+"C"+i[1]+" "+i[2]+" "+i[3]}var a=cv,b=cw,c=cA;d.source=function(b){if(!arguments.length)return a;a=d3.functor(b);return d},d.target=function(a){if(!arguments.length)return b;b=d3.functor(a);return d},d.projection=function(a){if(!arguments.length)return c;c=a;return d};return d},d3.svg.diagonal.radial=function(){var a=d3.svg.diagonal(),b=cA,c=a.projection;a.projection=function(a){return arguments.length?c(cB(b=a)):b};return a},d3.svg.mouse=function(a){return cD(a,d3.event)};var cC=/WebKit/.test(navigator.userAgent)?-1:0;d3.svg.touches=function(a){var b=d3.event.touches;return b?Array.prototype.map.call(b,function(b){var c=cD(a,b);c.identifier=b.identifier;return c}):[]},d3.svg.symbol=function(){function c(c,d){return(cG[a.call(this,c,d)]||cG.circle)(b.call(this,c,d))}var a=cF,b=cE;c.type=function(b){if(!arguments.length)return a;a=d3.functor(b);return c},c.size=function(a){if(!arguments.length)return b;b=d3.functor(a);return c};return c};var cG={circle:function(a){var b=Math.sqrt(a/Math.PI);return"M0,"+b+"A"+b+","+b+" 0 1,1 0,"+ -b+"A"+b+","+b+" 0 1,1 0,"+b+"Z"},cross:function(a){var b=Math.sqrt(a/5)/2;return"M"+ -3*b+","+ -b+"H"+ -b+"V"+ -3*b+"H"+b+"V"+ -b+"H"+3*b+"V"+b+"H"+b+"V"+3*b+"H"+ -b+"V"+b+"H"+ -3*b+"Z"},diamond:function(a){var b=Math.sqrt(a/(2*cI)),c=b*cI;return"M0,"+ -b+"L"+c+",0"+" 0,"+b+" "+ -c+",0"+"Z"},square:function(a){var b=Math.sqrt(a)/2;return"M"+ -b+","+ -b+"L"+b+","+ -b+" "+b+","+b+" "+ -b+","+b+"Z"},"triangle-down":function(a){var b=Math.sqrt(a/cH),c=b*cH/2;return"M0,"+c+"L"+b+","+ -c+" "+ -b+","+ -c+"Z"},"triangle-up":function(a){var b=Math.sqrt(a/cH),c=b*cH/2;return"M0,"+ -c+"L"+b+","+c+" "+ -b+","+c+"Z"}};d3.svg.symbolTypes=d3.keys(cG);var cH=Math.sqrt(3),cI=Math.tan(30*Math.PI/180);d3.svg.axis=function(){function j(j){j.each(function(k,l,m){function F(a){return j.delay?a.transition().delay(j[m][l].delay).duration(j[m][l].duration).ease(j.ease()):a}var n=d3.select(this),o=a.ticks.apply(a,g),p=h==null?a.tickFormat.apply(a,g):h,q=cL(a,o,i),r=n.selectAll(".minor").data(q,String),s=r.enter().insert("svg:line","g").attr("class","tick minor").style("opacity",1e-6),t=F(r.exit()).style("opacity",1e-6).remove(),u=F(r).style("opacity",1),v=n.selectAll("g").data(o,String),w=v.enter().insert("svg:g","path").style("opacity",1e-6),x=F(v.exit()).style("opacity",1e-6).remove(),y=F(v).style("opacity",1),z,A=bp(a.range()),B=n.selectAll(".domain").data([]),C=B.enter().append("svg:path").attr("class","domain"),D=F(B),E=this.__chart__||a;this.__chart__=a.copy(),w.append("svg:line").attr("class","tick"),w.append("svg:text"),y.select("text").text(p);switch(b){case"bottom":z=cJ,u.attr("y2",d),w.select("text").attr("dy",".71em").attr("text-anchor","middle"),y.select("line").attr("y2",c),y.select("text").attr("y",Math.max(c,0)+f),D.attr("d","M"+A[0]+","+e+"V0H"+A[1]+"V"+e);break;case"top":z=cJ,u.attr("y2",-d),w.select("text").attr("text-anchor","middle"),y.select("line").attr("y2",-c),y.select("text").attr("y",-(Math.max(c,0)+f)),D.attr("d","M"+A[0]+","+ -e+"V0H"+A[1]+"V"+ -e);break;case"left":z=cK,u.attr("x2",-d),w.select("text").attr("dy",".32em").attr("text-anchor","end"),y.select("line").attr("x2",-c),y.select("text").attr("x",-(Math.max(c,0)+f)),D.attr("d","M"+ -e+","+A[0]+"H0V"+A[1]+"H"+ -e);break;case"right":z=cK,u.attr("x2",d),w.select("text").attr("dy",".32em"),y.select("line").attr("x2",c),y.select("text").attr("x",Math.max(c,0)+f),D.attr("d","M"+e+","+A[0]+"H0V"+A[1]+"H"+e)}w.call(z,E),y.call(z,a),x.call(z,a),s.call(z,E),u.call(z,a),t.call(z,a)})}var a=d3.scale.linear(),b="bottom",c=6,d=6,e=6,f=3,g=[10],h,i=0;j.scale=function(b){if(!arguments.length)return a;a=b;return j},j.orient=function(a){if(!arguments.length)return b;b=a;return j},j.ticks=function(){if(!arguments.length)return g;g=arguments;return j},j.tickFormat=function(a){if(!arguments.length)return h;h=a;return j},j.tickSize=function(a,b,f){if(!arguments.length)return c;var g=arguments.length-1;c=+a,d=g>1?+b:c,e=g>0?+arguments[g]:c;return j},j.tickPadding=function(a){if(!arguments.length)return f;f=+a;return j},j.tickSubdivide=function(a){if(!arguments.length)return i;i=+a;return j};return j},d3.behavior={},d3.behavior.drag=function(){function d(){c.apply(this,arguments),cS("dragstart")}function c(){cM=a,cP=cT((cN=this).parentNode),cQ=0,cO=arguments}function b(){this.on("mousedown.drag",d).on("touchstart.drag",d),d3.select(window).on("mousemove.drag",cU).on("touchmove.drag",cU).on("mouseup.drag",cV,!0).on("touchend.drag",cV,!0).on("click.drag",cW,!0)}var a=d3.dispatch("drag","dragstart","dragend");b.on=function(c,d){a[c].add(d);return b};return b};var cM,cN,cO,cP,cQ,cR;d3.behavior.zoom=function(){function h(){d.apply(this,arguments);var b=dj(),c,e=Date.now();b.length===1&&e-da<300&&dp(1+Math.floor(a[2]),c=b[0],c_[c.identifier]),da=e}function g(){d.apply(this,arguments);var b=d3.svg.mouse(dd);dp(d3.event.shiftKey?Math.ceil(a[2]-1):Math.floor(a[2]+1),b,dh(b))}function f(){d.apply(this,arguments),c$||(c$=dh(d3.svg.mouse(dd))),dp(di()+a[2],d3.svg.mouse(dd),c$)}function e(){d.apply(this,arguments),cZ=dh(d3.svg.mouse(dd)),df=!1,d3.event.preventDefault(),window.focus()}function d(){db=a,dc=b.zoom.dispatch,dd=this,de=arguments}function c(){this.on("mousedown.zoom",e).on("mousewheel.zoom",f).on("DOMMouseScroll.zoom",f).on("dblclick.zoom",g).on("touchstart.zoom",h),d3.select(window).on("mousemove.zoom",dl).on("mouseup.zoom",dm).on("touchmove.zoom",dk).on("touchend.zoom",dj).on("click.zoom",dn,!0)}var a=[0,0,0],b=d3.dispatch("zoom");c.on=function(a,d){b[a].add(d);return c};return c};var cY,cZ,c$,c_={},da=0,db,dc,dd,de,df,dg})() \ No newline at end of file diff --git a/examples/force/force.js b/examples/force/force.js index aad2d47f..fbf905e6 100644 --- a/examples/force/force.js +++ b/examples/force/force.js @@ -9,7 +9,8 @@ var vis = d3.select("#chart") d3.json("miserables.json", function(json) { var force = d3.layout.force() - .charge(-60) + .charge(-120) + .linkDistance(30) .nodes(json.nodes) .links(json.links) .size([w, h]) diff --git a/src/core/date.js b/src/compat/date.js similarity index 100% rename from src/core/date.js rename to src/compat/date.js diff --git a/src/compat/style.js b/src/compat/style.js new file mode 100644 index 00000000..45addc2f --- /dev/null +++ b/src/compat/style.js @@ -0,0 +1,9 @@ +try { + document.createElement("div").style.setProperty("opacity", 0, ""); +} catch (error) { + var d3_style_prototype = CSSStyleDeclaration.prototype, + d3_style_setProperty = d3_style_prototype.setProperty; + d3_style_prototype.setProperty = function(name, value, priority) { + d3_style_setProperty.call(this, name, value + "", priority); + }; +} diff --git a/src/core/core.js b/src/core/core.js index c7257cf5..ba1070fc 100644 --- a/src/core/core.js +++ b/src/core/core.js @@ -1 +1 @@ -d3 = {version: "2.0.4"}; // semver +d3 = {version: "2.1.0"}; // semver diff --git a/src/core/object.js b/src/core/object.js deleted file mode 100644 index a284decc..00000000 --- a/src/core/object.js +++ /dev/null @@ -1,5 +0,0 @@ -if (!Object.create) Object.create = function(o) { - /** @constructor */ function f() {} - f.prototype = o; - return new f; -}; diff --git a/src/core/transition-style.js b/src/core/transition-style.js index def903e3..7e21269f 100644 --- a/src/core/transition-style.js +++ b/src/core/transition-style.js @@ -1,10 +1,10 @@ d3_transitionPrototype.style = function(name, value, priority) { - if (arguments.length < 3) priority = null; + if (arguments.length < 3) priority = ""; return this.styleTween(name, d3_transitionTween(value), priority); }; d3_transitionPrototype.styleTween = function(name, tween, priority) { - if (arguments.length < 3) priority = null; + if (arguments.length < 3) priority = ""; return this.tween("style." + name, function(d, i) { var f = tween.call(this, d, i, window.getComputedStyle(this, null).getPropertyValue(name)); return f && function(t) { diff --git a/src/core/transition.js b/src/core/transition.js index 04d2ef9b..dd756469 100644 --- a/src/core/transition.js +++ b/src/core/transition.js @@ -39,7 +39,7 @@ function d3_transition(groups, id) { delay <= elapsed ? start() : d3.timer(start, delay, then); - function start() { + function start(elapsed) { if (lock.active > id) return stop(); lock.active = id; @@ -50,7 +50,7 @@ function d3_transition(groups, id) { } event.start.dispatch.call(node, d, i); - d3.timer(tick, 0, then); + if (!tick(elapsed)) d3.timer(tick, 0, then); return 1; } diff --git a/src/geo/albers.js b/src/geo/albers.js index 88bffdbe..0d002354 100644 --- a/src/geo/albers.js +++ b/src/geo/albers.js @@ -21,6 +21,18 @@ d3.geo.albers = function() { ]; } + albers.invert = function(coordinates) { + var x = (coordinates[0] - translate[0]) / scale, + y = (coordinates[1] - translate[1]) / scale, + p0y = p0 + y, + t = Math.atan2(x, p0y), + p = Math.sqrt(x * x + p0y * p0y); + return [ + (lng0 + t / n) / d3_radians, + Math.asin((C - p * p * n * n) / (2 * n)) / d3_radians + ]; + }; + function reload() { var phi1 = d3_radians * parallels[0], phi2 = d3_radians * parallels[1], diff --git a/src/geo/azimuthal.js b/src/geo/azimuthal.js index 92943480..495c9f62 100644 --- a/src/geo/azimuthal.js +++ b/src/geo/azimuthal.js @@ -16,7 +16,7 @@ d3.geo.azimuthal = function() { sx1 = Math.sin(x1), cy1 = Math.cos(y1), sy1 = Math.sin(y1), - k = mode == "stereographic" ? 1 / (1 + sy0 * sy1 + cy0 * cy1 * cx1) : 1, + k = mode === "stereographic" ? 1 / (1 + sy0 * sy1 + cy0 * cy1 * cx1) : 1, x = k * cy1 * sx1, y = k * (sy0 * cy1 * cx1 - cy0 * sy1); return [ @@ -25,9 +25,22 @@ d3.geo.azimuthal = function() { ]; } + azimuthal.invert = function(coordinates) { + var x = (coordinates[0] - translate[0]) / scale, + y = (coordinates[1] - translate[1]) / scale, + p = Math.sqrt(x * x + y * y), + c = mode === "stereographic" ? 2 * Math.atan(p) : Math.asin(p), + sc = Math.sin(c), + cc = Math.cos(c); + return [ + (x0 + Math.atan2(x * sc, p * cy0 * cc + y * sy0 * sc)) / d3_radians, + Math.asin(cc * sy0 - (y * sc * cy0) / p) / d3_radians + ]; + }; + azimuthal.mode = function(x) { if (!arguments.length) return mode; - mode = x; + mode = x + ""; return azimuthal; }; diff --git a/src/geo/greatCircle.js b/src/geo/greatCircle.js new file mode 100644 index 00000000..a5408267 --- /dev/null +++ b/src/geo/greatCircle.js @@ -0,0 +1,91 @@ +// From http://williams.best.vwh.net/avform.htm#Intermediate +d3.geo.greatCircle = function() { + var source = d3_geo_greatCircleSource, + target = d3_geo_greatCircleTarget, + n = 100, + radius = 6371; // Mean radius of Earth, in km. + // TODO: breakAtDateLine? + + function greatCircle(d, i) { + var from = source.call(this, d, i), + to = target.call(this, d, i), + x0 = from[0] * d3_radians, + y0 = from[1] * d3_radians, + x1 = to[0] * d3_radians, + y1 = to[1] * d3_radians, + cx0 = Math.cos(x0), sx0 = Math.sin(x0), + cy0 = Math.cos(y0), sy0 = Math.sin(y0), + cx1 = Math.cos(x1), sx1 = Math.sin(x1), + cy1 = Math.cos(y1), sy1 = Math.sin(y1), + d = Math.acos(sy0 * sy1 + cy0 * cy1 * Math.cos(x1 - x0)), + sd = Math.sin(d), + f = d / (n - 1), + e = -f, + path = [], + i = -1; + + while (++i < n) { + e += f; + var A = Math.sin(d - e) / sd, + B = Math.sin(e) / sd, + x = A * cy0 * cx0 + B * cy1 * cx1, + y = A * cy0 * sx0 + B * cy1 * sx1, + z = A * sy0 + B * sy1; + path[i] = [ + Math.atan2(y, x) / d3_radians, + Math.atan2(z, Math.sqrt(x * x + y * y)) / d3_radians + ]; + } + + return path; + } + + greatCircle.source = function(x) { + if (!arguments.length) return source; + source = x; + return greatCircle; + }; + + greatCircle.target = function(x) { + if (!arguments.length) return target; + target = x; + return greatCircle; + }; + + greatCircle.n = function(x) { + if (!arguments.length) return n; + n = +x; + return greatCircle; + }; + + greatCircle.radius = function(x) { + if (!arguments.length) return radius; + radius = +x; + return greatCircle; + }; + + // Haversine formula for great-circle distance. + greatCircle.distance = function(d, i) { + var from = source.call(this, d, i), + to = target.call(this, d, i), + x0 = from[0] * d3_radians, + y0 = from[1] * d3_radians, + x1 = to[0] * d3_radians, + y1 = to[1] * d3_radians, + sy = Math.sin((y1 - y0) / 2), + sx = Math.sin((x1 - x0) / 2), + a = sy * sy + Math.cos(y0) * Math.cos(y1) * sx * sx; + + return radius * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a)); + }; + + return greatCircle; +}; + +function d3_geo_greatCircleSource(d) { + return d.source; +} + +function d3_geo_greatCircleTarget(d) { + return d.target; +} diff --git a/src/geo/mercator.js b/src/geo/mercator.js index 9494d711..dea7ca62 100644 --- a/src/geo/mercator.js +++ b/src/geo/mercator.js @@ -3,14 +3,23 @@ d3.geo.mercator = function() { translate = [480, 250]; function mercator(coordinates) { - var x = (coordinates[0]) / 360, - y = (-180 / Math.PI * Math.log(Math.tan(Math.PI / 4 + coordinates[1] * Math.PI / 360))) / 360; + var x = coordinates[0] / 360, + y = -(Math.log(Math.tan(Math.PI / 4 + coordinates[1] * d3_radians / 2)) / d3_radians) / 360; return [ scale * x + translate[0], scale * Math.max(-.5, Math.min(.5, y)) + translate[1] ]; } + mercator.invert = function(coordinates) { + var x = (coordinates[0] - translate[0]) / scale, + y = (coordinates[1] - translate[1]) / scale; + return [ + 360 * x, + 2 * Math.atan(Math.exp(-360 * y * d3_radians)) / d3_radians - 90 + ]; + }; + mercator.scale = function(x) { if (!arguments.length) return scale; scale = +x; diff --git a/src/layout/force.js b/src/layout/force.js index 544bc463..8ecee9c3 100644 --- a/src/layout/force.js +++ b/src/layout/force.js @@ -27,15 +27,15 @@ d3.layout.force = function() { /* Barnes-Hut criterion. */ if ((x2 - x1) * dn < theta) { var k = kc * quad.count * dn * dn; - node.x += dx * k; - node.y += dy * k; + node.px -= dx * k; + node.py -= dy * k; return true; } if (quad.point && isFinite(dn)) { var k = kc * dn * dn; - node.x += dx * k; - node.y += dy * k; + node.px -= dx * k; + node.py -= dy * k; } } }; @@ -44,12 +44,13 @@ d3.layout.force = function() { function tick() { var n = nodes.length, m = links.length, - q = d3.geom.quadtree(nodes), + q, i, // current index o, // current object s, // current source t, // current target l, // current distance + k, // current force x, // x-distance y; // y-distance @@ -64,30 +65,32 @@ d3.layout.force = function() { l = alpha * strengths[i] * ((l = Math.sqrt(l)) - distances[i]) / l; x *= l; y *= l; - t.x -= x / t.weight; - t.y -= y / t.weight; - s.x += x / s.weight; - s.y += y / s.weight; + t.x -= x * (k = s.weight / (t.weight + s.weight)); + t.y -= y * k; + s.x += x * (k = 1 - k); + s.y += y * k; } } // apply gravity forces - var kg = alpha * gravity; - x = size[0] / 2; - y = size[1] / 2; - i = -1; while (++i < n) { - o = nodes[i]; - o.x += (x - o.x) * kg; - o.y += (y - o.y) * kg; + if (k = alpha * gravity) { + x = size[0] / 2; + y = size[1] / 2; + i = -1; if (k) while (++i < n) { + o = nodes[i]; + o.x += (x - o.x) * k; + o.y += (y - o.y) * k; + } } - // compute quadtree center of mass - d3_layout_forceAccumulate(q); - - // apply charge forces - var kc = alpha * charge; - i = -1; while (++i < n) { - q.visit(repulse(nodes[i], kc)); + // compute quadtree center of mass and apply charge forces + if (k = alpha * charge) { + d3_layout_forceAccumulate(q = d3.geom.quadtree(nodes)); + i = -1; while (++i < n) { + if (!(o = nodes[i]).fixed) { + q.visit(repulse(o, k)); + } + } } // position verlet integration diff --git a/src/scale/ordinal.js b/src/scale/ordinal.js index 19d7d481..09fac56c 100644 --- a/src/scale/ordinal.js +++ b/src/scale/ordinal.js @@ -1,21 +1,22 @@ d3.scale.ordinal = function() { - return d3_scale_ordinal({}, 0, {t: "range", x: []}); + return d3_scale_ordinal([], {t: "range", x: []}); }; -function d3_scale_ordinal(domain, size, ranger) { - var range, +function d3_scale_ordinal(domain, ranger) { + var index, + range, rangeBand; function scale(x) { - return range[((domain[x] || (domain[x] = ++size)) - 1) % range.length]; + return range[((index[x] || (index[x] = domain.push(x))) - 1) % range.length]; } scale.domain = function(x) { - if (!arguments.length) return d3.keys(domain); - domain = {}; - size = 0; + if (!arguments.length) return domain; + domain = []; + index = {}; var i = -1, n = x.length, xi; - while (++i < n) if (!domain[xi = x[i]]) domain[xi] = ++size; + while (++i < n) if (!index[xi = x[i]]) index[xi] = domain.push(xi); return scale[ranger.t](ranger.x, ranger.p); }; @@ -31,8 +32,8 @@ function d3_scale_ordinal(domain, size, ranger) { if (arguments.length < 2) padding = 0; var start = x[0], stop = x[1], - step = (stop - start) / (size - 1 + padding); - range = size < 2 ? [(start + stop) / 2] : d3.range(start + step * padding / 2, stop + step / 2, step); + step = (stop - start) / (domain.length - 1 + padding); + range = domain.length < 2 ? [(start + stop) / 2] : d3.range(start + step * padding / 2, stop + step / 2, step); rangeBand = 0; ranger = {t: "rangePoints", x: x, p: padding}; return scale; @@ -42,7 +43,7 @@ function d3_scale_ordinal(domain, size, ranger) { if (arguments.length < 2) padding = 0; var start = x[0], stop = x[1], - step = (stop - start) / (size + padding); + step = (stop - start) / (domain.length + padding); range = d3.range(start + step * padding, stop, step); rangeBand = step * (1 - padding); ranger = {t: "rangeBands", x: x, p: padding}; @@ -53,8 +54,8 @@ function d3_scale_ordinal(domain, size, ranger) { if (arguments.length < 2) padding = 0; var start = x[0], stop = x[1], - step = Math.floor((stop - start) / (size + padding)), - err = stop - start - (size - padding) * step; + step = Math.floor((stop - start) / (domain.length + padding)), + err = stop - start - (domain.length - padding) * step; range = d3.range(start + Math.round(err / 2), stop, step); rangeBand = Math.round(step * (1 - padding)); ranger = {t: "rangeRoundBands", x: x, p: padding}; @@ -66,10 +67,8 @@ function d3_scale_ordinal(domain, size, ranger) { }; scale.copy = function() { - var copy = {}, x; - for (x in domain) copy[x] = domain[x]; - return d3_scale_ordinal(copy, size, ranger); + return d3_scale_ordinal(domain, ranger); }; - return scale[ranger.t](ranger.x, ranger.p); + return scale.domain(domain); }; diff --git a/test/core/selection-style-test.js b/test/core/selection-style-test.js index 680056e0..83090dc2 100644 --- a/test/core/selection-style-test.js +++ b/test/core/selection-style-test.js @@ -17,7 +17,7 @@ suite.addBatch({ }, "sets a property as a number": function(body) { body.style("opacity", .3); - assert.equal(document.body.style["opacity"], ".3"); + assert.equal(document.body.style["opacity"], "0.3"); }, "sets a property as a function": function(body) { body.style("background-color", function() { return "orange"; }); @@ -57,8 +57,8 @@ suite.addBatch({ }, "sets a property as a number": function(div) { div.style("opacity", .5); - assert.equal(div[0][0].style["opacity"], ".5"); - assert.equal(div[0][1].style["opacity"], ".5"); + assert.equal(div[0][0].style["opacity"], "0.5"); + assert.equal(div[0][1].style["opacity"], "0.5"); }, "sets a property as a function": function(div) { div.style("background-color", d3.interpolateRgb("orange", "yellow")); diff --git a/test/env.js b/test/env.js index cfbdefad..be0cadeb 100644 --- a/test/env.js +++ b/test/env.js @@ -1,6 +1,7 @@ document = require("jsdom").jsdom(""); window = document.createWindow(); navigator = window.navigator; +CSSStyleDeclaration = window.CSSStyleDeclaration; require("../lib/sizzle/sizzle"); Sizzle = window.Sizzle; diff --git a/test/geo/albers-test.js b/test/geo/albers-test.js new file mode 100644 index 00000000..afcde0cc --- /dev/null +++ b/test/geo/albers-test.js @@ -0,0 +1,57 @@ +require("../env"); +require("../../d3"); +require("../../d3.geo"); + +var vows = require("vows"), + assert = require("assert"); + +var suite = vows.describe("d3.geo.albers"); + +suite.addBatch({ + "albers": { + topic: function() { + return d3.geo.albers(); + }, + "Arctic": function(albers) { + var coords = albers([0, 85]); + assert.inDelta(coords[0], 1031.393796, 1e-6); + assert.inDelta(coords[1], -714.160436, 1e-6); + var lonlat = albers.invert(coords); + assert.inDelta(lonlat[0], 0, 1e-6); + assert.inDelta(lonlat[1], 85, 1e-6); + }, + "Antarctic": function(albers) { + var coords = albers([0, -85]); + assert.inDelta(coords[0], 2753.458335, 1e-6); + assert.inDelta(coords[1], 317.371122, 1e-6); + var lonlat = albers.invert(coords); + assert.inDelta(lonlat[0], 0, 1e-6); + assert.inDelta(lonlat[1], -85, 1e-6); + }, + "Hawaii": function(albers) { + var coords = albers([-180, 0]); + assert.inDelta(coords[0], -984.779405, 1e-6); + assert.inDelta(coords[1], 209.571197, 1e-6); + var lonlat = albers.invert(coords); + assert.inDelta(lonlat[0], -180, 1e-6); + assert.inDelta(lonlat[1], 0, 1e-6); + }, + "Phillipines": function(albers) { + var coords = albers([180, 0]); + assert.inDelta(coords[0], 894.435228, 1e-6); + assert.inDelta(coords[1], -2927.636630, 1e-6); + var lonlat = albers.invert(coords); + assert.inDelta(lonlat[0], 180, 1e-6); + assert.inDelta(lonlat[1], 0, 1e-6); + }, + "Inversion works for non-zero translation": function() { + var albers = d3.geo.albers().translate([123, 99]).scale(100), + coords = albers([0, 85]), + lonlat = albers.invert(coords); + assert.inDelta(lonlat[0], 0, 1e-6); + assert.inDelta(lonlat[1], 85, 1e-6); + } + } +}); + +suite.export(module); diff --git a/test/geo/azimuthal-test.js b/test/geo/azimuthal-test.js new file mode 100644 index 00000000..43563a39 --- /dev/null +++ b/test/geo/azimuthal-test.js @@ -0,0 +1,89 @@ +require("../env"); +require("../../d3"); +require("../../d3.geo"); + +var vows = require("vows"), + assert = require("assert"); + +var suite = vows.describe("d3.geo.azimuthal"); + +suite.addBatch({ + "azimuthal.stereographic": { + topic: function() { + return d3.geo.azimuthal().mode("stereographic").translate([0, 0]).scale(100); + }, + "Arctic": function(azimuthal) { + var coords = azimuthal([0, 85]); + assert.inDelta(coords[0], 0, 1e-6); + assert.inDelta(coords[1], -91.633117, 1e-6); + var lonlat = azimuthal.invert(coords); + assert.inDelta(lonlat[0], 0, 1e-6); + assert.inDelta(lonlat[1], 85, 1e-6); + }, + "Antarctic": function(azimuthal) { + var coords = azimuthal([0, -85]); + assert.inDelta(coords[0], 0, 1e-6); + assert.inDelta(coords[1], 91.633117, 1e-6); + var lonlat = azimuthal.invert(coords); + assert.inDelta(lonlat[0], 0, 1e-6); + assert.inDelta(lonlat[1], -85, 1e-6); + }, + "Hawaii": function(azimuthal) { + var coords = azimuthal([-180, 0]); + assert.equal(coords[0], -Infinity); + assert.isTrue(isNaN(coords[1])); + }, + "Phillipines": function(azimuthal) { + var coords = azimuthal([180, 0]); + assert.equal(coords[0], Infinity); + assert.isTrue(isNaN(coords[1])); + }, + "Inversion works for non-zero translation": function() { + var azimuthal = d3.geo.azimuthal().mode("stereographic").translate([123, 99]).scale(100), + coords = azimuthal([0, 85]), + lonlat = azimuthal.invert(coords); + assert.inDelta(lonlat[0], 0, 1e-6); + assert.inDelta(lonlat[1], 85, 1e-6); + } + }, + "azimuthal.orthographic": { + topic: function() { + return d3.geo.azimuthal().mode("orthographic").translate([0, 0]).scale(100); + }, + "Arctic": function(azimuthal) { + var coords = azimuthal([0, 85]); + assert.inDelta(coords[0], 0, 1e-6); + assert.inDelta(coords[1], -99.619469, 1e-6); + var lonlat = azimuthal.invert(coords); + assert.inDelta(lonlat[0], 0, 1e-6); + assert.inDelta(lonlat[1], 85, 1e-6); + }, + "Antarctic": function(azimuthal) { + var coords = azimuthal([0, -85]); + assert.inDelta(coords[0], 0, 1e-6); + assert.inDelta(coords[1], 99.619469, 1e-6); + var lonlat = azimuthal.invert(coords); + assert.inDelta(lonlat[0], 0, 1e-6); + assert.inDelta(lonlat[1], -85, 1e-6); + }, + "Hawaii": function(azimuthal) { + var coords = azimuthal([-180, 0]); + assert.inDelta(coords[0], 0, 1e-6); + assert.inDelta(coords[1], 0, 1e-6); + }, + "Phillipines": function(azimuthal) { + var coords = azimuthal([180, 0]); + assert.inDelta(coords[0], 0, 1e-6); + assert.inDelta(coords[1], 0, 1e-6); + }, + "Inversion works for non-zero translation": function() { + var azimuthal = d3.geo.azimuthal().mode("orthographic").translate([123, 99]).scale(100), + coords = azimuthal([0, 85]), + lonlat = azimuthal.invert(coords); + assert.inDelta(lonlat[0], 0, 1e-6); + assert.inDelta(lonlat[1], 85, 1e-6); + } + } +}); + +suite.export(module); diff --git a/test/geo/greatCircle-test.js b/test/geo/greatCircle-test.js new file mode 100644 index 00000000..085d5df7 --- /dev/null +++ b/test/geo/greatCircle-test.js @@ -0,0 +1,42 @@ +require("../env"); +require("../../d3"); +require("../../d3.geo"); + +var vows = require("vows"), + assert = require("assert"); + +var suite = vows.describe("d3.geo.greatCircle"); + +suite.addBatch({ + "greatCircle": { + topic: function() { + return d3.geo.greatCircle() + .n(12); + }, + "distance": function(circle) { + assert.equal(circle.distance({source: [0, 0], target: [0, 0]}), 0); + assert.inDelta(circle.distance({ + source: [118 + 24 / 60, 33 + 57 / 60], + target: [ 73 + 47 / 60, 40 + 38 / 60] + }), 3973, .5); + }, + "geodesic": function(circle) { + assert.inDelta(circle({source: [5, 52], target: [-120, 37]}), [ + [ 5, 52 ], + [ -3.805036, 57.05083], + [ -15.122869, 61.30118], + [ -29.396213, 64.34584], + [ -46.132729, 65.72409], + [ -63.394401, 65.15597], + [ -78.854311, 62.76337], + [ -91.401599, 58.96701], + [-101.190927, 54.21333], + [-108.843633, 48.83586], + [-114.961152, 43.05231], + [-120, 37 ] + ], .5); + } + } +}); + +suite.export(module); diff --git a/test/geo/mercator-test.js b/test/geo/mercator-test.js new file mode 100644 index 00000000..8970ffef --- /dev/null +++ b/test/geo/mercator-test.js @@ -0,0 +1,57 @@ +require("../env"); +require("../../d3"); +require("../../d3.geo"); + +var vows = require("vows"), + assert = require("assert"); + +var suite = vows.describe("d3.geo.mercator"); + +suite.addBatch({ + "mercator": { + topic: function() { + return d3.geo.mercator().translate([0, 0]).scale(100); + }, + "Arctic": function(mercator) { + var coords = mercator([0, 85]); + assert.inDelta(coords[0], 0, 1e-6); + assert.inDelta(coords[1], -49.8362085, 1e-6); + var lonlat = mercator.invert(coords); + assert.inDelta(lonlat[0], 0, 1e-6); + assert.inDelta(lonlat[1], 85, 1e-6); + }, + "Antarctic": function(mercator) { + var coords = mercator([0, -85]); + assert.inDelta(coords[0], 0, 1e-6); + assert.inDelta(coords[1], 49.8362085, 1e-6); + var lonlat = mercator.invert(coords); + assert.inDelta(lonlat[0], 0, 1e-6); + assert.inDelta(lonlat[1], -85, 1e-6); + }, + "Hawaii": function(mercator) { + var coords = mercator([-180, 0]); + assert.inDelta(coords[0], -50, 1e-6); + assert.inDelta(coords[1], 0, 1e-6); + var lonlat = mercator.invert(coords); + assert.inDelta(lonlat[0], -180, 1e-6); + assert.inDelta(lonlat[1], 0, 1e-6); + }, + "Phillipines": function(mercator) { + var coords = mercator([180, 0]); + assert.inDelta(coords[0], 50, 1e-6); + assert.inDelta(coords[1], 0, 1e-6); + var lonlat = mercator.invert(coords); + assert.inDelta(lonlat[0], 180, 1e-6); + assert.inDelta(lonlat[1], 0, 1e-6); + }, + "Inversion works for non-zero translation": function() { + var mercator = d3.geo.mercator().translate([123, 99]).scale(100), + coords = mercator([0, 85]), + lonlat = mercator.invert(coords); + assert.inDelta(lonlat[0], 0, 1e-6); + assert.inDelta(lonlat[1], 85, 1e-6); + } + } +}); + +suite.export(module); diff --git a/test/scale/ordinal-test.js b/test/scale/ordinal-test.js index bac05347..eb3a9207 100644 --- a/test/scale/ordinal-test.js +++ b/test/scale/ordinal-test.js @@ -29,17 +29,39 @@ suite.addBatch({ var x = ordinal().range(["foo", "bar"]); assert.equal(x(1), "foo"); assert.equal(x(0), "bar"); - assert.deepEqual(x.domain(), ["0", "1"]); + assert.deepEqual(x.domain(), [1, 0]); x.domain(["0", "1"]); assert.equal(x(0), "foo"); // it changed! assert.equal(x(1), "bar"); assert.deepEqual(x.domain(), ["0", "1"]); }, - "coerces domain values to strings": function(ordinal) { + "uniqueness is based on string coercion": function(ordinal) { + var x = ordinal().domain(["foo"]).range([42, 43, 44]); + assert.equal(x(new String("foo")), 42); + assert.equal(x({toString: function() { return "foo"; }}), 42); + assert.equal(x({toString: function() { return "bar"; }}), 43); + }, + "orders domain values by the order in which they are seen": function(ordinal) { + var x = ordinal(); + x("foo"); + x("bar"); + x("baz"); + assert.deepEqual(x.domain(), ["foo", "bar", "baz"]); + x.domain(["baz", "bar"]); + x("foo"); + assert.deepEqual(x.domain(), ["baz", "bar", "foo"]); + x.domain(["baz", "foo"]); + assert.deepEqual(x.domain(), ["baz", "foo"]); + x.domain([]); + x("foo"); + x("bar"); + assert.deepEqual(x.domain(), ["foo", "bar"]); + }, + "does not coerce domain values to strings": function(ordinal) { var x = ordinal().domain([0, 1]); - assert.deepEqual(x.domain(), ["0", "1"]); - assert.typeOf(x.domain()[0], "string"); - assert.typeOf(x.domain()[1], "string"); + assert.deepEqual(x.domain(), [0, 1]); + assert.typeOf(x.domain()[0], "number"); + assert.typeOf(x.domain()[1], "number"); } },