d3 / d3-plugins

[DEPRECATED] A repository for sharing D3.js V3 plugins.
https://github.com/d3/d3/wiki/Plugins
Other
1.81k stars 684 forks source link

d3.geo.interpolatedProjection #67

Open mbostock opened 11 years ago

mbostock commented 11 years ago

I wonder if this is worth adding:

d3.geo.interpolatedProjection = function(a, b) {
  var projection = d3.geo.projection(raw).scale(1),
      center = projection.center,
      translate = projection.translate,
      α;

  function raw(λ, φ) {
    var pa = a([λ *= 180 / Math.PI, φ *= 180 / Math.PI]), pb = b([λ, φ]);
    return [(1 - α) * pa[0] + α * pb[0], (α - 1) * pa[1] - α * pb[1]];
  }

  projection.alpha = function(_) {
    if (!arguments.length) return α;
    α = +_;
    var ca = a.center(), cb = b.center(),
        ta = a.translate(), tb = b.translate();
    center([(1 - α) * ca[0] + α * cb[0], (1 - α) * ca[1] + α * cb[1]]);
    translate([(1 - α) * ta[0] + α * tb[0], (1 - α) * ta[1] + α * tb[1]]);
    return projection;
  };

  delete projection.scale;
  delete projection.translate;
  delete projection.center;
  return projection.alpha(0);
};

Taken from http://bl.ocks.org/mbostock/5731632

jasondavies commented 11 years ago

Nice! A minor improvement could be to use d3.geo.interpolate for center.

mbostock commented 11 years ago

That reminds me, there’s a related problem where the interpolated projection can get out of sync with its a & b projections if their center or translate changes after alpha is set. I debate whether it’s a requirement that the interpolated projection be a “view” on its constituent projection, but at the same time there’s no way to take a snapshot of a projection so the alternative is to allow undefined behavior.

Maybe it would be cleaner to interpolate raw projection functions instead, but then you’d have to expose some other API for interpolating changes to scale, center, translate, rotate, etc. Also that would avoid trying to interpolate changes in clipping behavior, which isn’t possible.

jasondavies commented 11 years ago

Perhaps we should consider adding projection.copy(), similar to scale.copy()? I think we’ve come across other situations where it might have been useful in the past.

jasondavies commented 11 years ago

I’m not sure if it’s really possible to copy projections with custom streams though, like the current implementation of d3.geo.hammerRetroazimuthal.

jasondavies commented 11 years ago

Another idea could be to allow projection.center(null), which would disable center altogether.

iamvdo commented 8 years ago

Is there any improvement since then? I can't find any other solution to interpolate projections.

Btw, I find this solution pretty complex. For example, how to add an invert method, or how to animate clipAngle, etc. Also, why this fails with Mercator projection?

Maybe d3-geo (or d3-geo-projection) should add a built-in function?

If I'm totally off-topic, please let me know ;-)