d3-plugins icon indicating copy to clipboard operation
d3-plugins copied to clipboard

d3.geo.interpolatedProjection

Open mbostock opened this issue 12 years ago • 6 comments

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

mbostock avatar Jun 11 '13 17:06 mbostock

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

jasondavies avatar Jun 11 '13 18:06 jasondavies

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.

mbostock avatar Jun 11 '13 22:06 mbostock

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 avatar Jun 11 '13 22:06 jasondavies

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 avatar Jun 11 '13 22:06 jasondavies

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

jasondavies avatar Jun 13 '13 12:06 jasondavies

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 ;-)

iamvdo avatar Nov 08 '16 16:11 iamvdo