Permalink
Browse files

optimizations

  • Loading branch information...
1 parent f758edd commit b6238aaf89180653a8f660fb118cbf6861de8be2 Calvin Metcalf committed May 16, 2013
Showing with 71 additions and 55 deletions.
  1. +71 −55 cartogram.js
View
@@ -33,18 +33,25 @@
topology = copy(topology);
// objects are projected into screen coordinates
- var projectGeometry = projector(projection);
// project the arcs into screen space
- var tf = transformer(topology.transform),
- projectedArcs = topology.arcs.map(function(arc) {
- var x = 0, y = 0;
- return arc.map(function(coord) {
- coord[0] = (x += coord[0]);
- coord[1] = (y += coord[1]);
- return projection(tf(coord));
- });
- });
+ var tf = transformer(topology.transform),x,y,len1,i1,out1,len2=topology.arcs.length,i2=0,
+ projectedArcs = new Array(len2);
+ while(i2<len2){
+ x = 0;
+ y = 0;
+ len1 = topology.arcs[i2].length;
+ i1 = 0;
+ out1 = new Array(len1);
+ while(i1<len1){
+ topology.arcs[i2][i1][0] = (x += topology.arcs[i2][i1][0]);
+ topology.arcs[i2][i1][1] = (y += topology.arcs[i2][i1][1]);
+ out1[i1] = projection(tf(topology.arcs[i2][i1]));
+ i1++;
+ }
+ projectedArcs[i2++]=out1;
+
+ }
// path with identity projection
var path = d3.geo.path()
@@ -68,20 +75,21 @@
return objects;
}
- var i = 0,
- targetSizeError = 1;
+ var i = 0;
while (i++ < iterations) {
- var areas = objects.map(path.area),
- totalArea = d3.sum(areas),
- sizeErrors = [],
+ var areas = objects.map(path.area);
+ var totalArea = d3.sum(areas),
+ sizeErrorsTot =0,
+ sizeErrorsNum=0,
meta = objects.map(function(o, j) {
var area = Math.abs(areas[j]), // XXX: why do we have negative areas?
v = +values[j],
desired = totalArea * v / totalValue,
radius = Math.sqrt(area / Math.PI),
mass = Math.sqrt(desired / Math.PI) - radius,
sizeError = Math.max(area, desired) / Math.min(area, desired);
- sizeErrors.push(sizeError);
+ sizeErrorsTot+=sizeError;
+ sizeErrorsNum++;
// console.log(o.id, "@", j, "area:", area, "value:", v, "->", desired, radius, mass, sizeError);
return {
id: o.id,
@@ -95,51 +103,49 @@
};
});
- var sizeError = d3.mean(sizeErrors),
+ var sizeError = sizeErrorsTot/sizeErrorsNum,
forceReductionFactor = 1 / (1 + sizeError);
// console.log("meta:", meta);
// console.log(" total area:", totalArea);
// console.log(" force reduction factor:", forceReductionFactor, "mean error:", sizeError);
- projectedArcs.forEach(function(arc) {
- arc.forEach(function(coord) {
- // create an array of vectors: [x, y]
- var vectors = meta.map(function(d) {
- var centroid = d.centroid,
- mass = d.mass,
- radius = d.radius,
- theta = angle(centroid, coord),
- dist = distance(centroid, coord),
- Fij = (dist > radius)
- ? mass * radius / dist
- : mass *
- (Math.pow(dist, 2) / Math.pow(radius, 2)) *
- (4 - 3 * dist / radius);
- return [
- Fij * Math.cos(theta),
- Fij * Math.sin(theta)
- ];
- });
-
- // using Fij and angles, calculate vector sum
- var delta = vectors.reduce(function(a, b) {
- return [
- a[0] + b[0],
- a[1] + b[1]
- ];
- }, [0, 0]);
-
- delta[0] *= forceReductionFactor;
- delta[1] *= forceReductionFactor;
-
- coord[0] += delta[0];
- coord[1] += delta[1];
- });
- });
+ var len1,i1,delta,len2=projectedArcs.length,i2=0,delta,len3,i3,centroid,mass,radius,rSquared,dx,dy,distSquared,dist,Fij;
+ while(i2<len2){
+ len1=projectedArcs[i2].length;
+ i1=0;
+ while(i1<len1){
+ // create an array of vectors: [x, y]
+ delta = [0,0];
+ len3 = meta.length;
+ i3=0;
+ while(i3<len3) {
+ centroid = meta[i3].centroid;
+ mass = meta[i3].mass;
+ radius = meta[i3].radius;
+ rSquared = (radius*radius);
+ dx = projectedArcs[i2][i1][0] - centroid[0];
+ dy = projectedArcs[i2][i1][1] - centroid[1];
+ distSquared = dx * dx + dy * dy;
+ dist=Math.sqrt(distSquared);
+ Fij = (dist > radius)
+ ? mass * radius / dist
+ : mass *
+ (distSquared / rSquared) *
+ (4 - 3 * dist / radius);
+ delta[0]+=(Fij * cosArctan(dy,dx));
+ delta[1]+=(Fij * sinArctan(dy,dx));
+ i3++;
+ }
+ projectedArcs[i2][i1][0] += (delta[0]*forceReductionFactor);
+ projectedArcs[i2][i1][1] += (delta[1]*forceReductionFactor);
+ i1++;
+ }
+ i2++;
+ }
// break if we hit the target size error
- if (sizeError <= targetSizeError) break;
+ if (sizeError <= 1) break;
}
return {
@@ -265,7 +271,18 @@
return types[geom.type](geom.coordinates);
};
}
-
+ function cosArctan(dx,dy){
+ var div = dx/dy;
+ return (dy>0)?
+ (1/Math.sqrt(1+(div*div))):
+ (-1/Math.sqrt(1+(div*div)));
+ }
+ function sinArctan(dx,dy){
+ var div = dx/dy;
+ return (dy>0)?
+ (div/Math.sqrt(1+(div*div))):
+ (-div/Math.sqrt(1+(div*div)));
+ }
function copy(o) {
return (o instanceof Array)
? o.map(copy)
@@ -304,7 +321,6 @@
o.coordinates = geometryType[o.type](o.arcs);
return o;
}
-
var geometryType = {
LineString: line,
MultiLineString: polygon,

0 comments on commit b6238aa

Please sign in to comment.