2013-06-11 7 views
7

Ich baue mich, ähnlich wie dieses Beispiel einen glatten Übergang zwischen Alber/orthographisch in einem Mini-App möchte tun tun:Wie reibungslosen Übergang für Karte Reprojektion in d3 js

http://mbostock.github.io/d3/talk/20111018/#27

Es jedoch gebrochen, mit einem ziemlich abgehackt Übergang der Karte Pfade in v3 scheint, wie dieser glatte Übergang:

https://www.evernote.com/shard/s236/sh/46b002bd-9c5b-4e9b-87ef-270c303eb677/2eaeebb267a3fc59df5a8447bbbcc58b/res/37917835-5aad-4509-b534-31a3e3034762/Worst_Tornado_Outbreaks_of_All_Time-20130611-074050.jpg.jpg?resizeSmall&width=832

-Code ist ziemlich geradlinig, ich die Karte initialisieren, wie albers, dann ortho run() um es zu aktualisieren.

function ortho() { 
    var self = this, 
    h = 1000, 
    w = document.width; 

    this.projection = d3.geo.orthographic() 
    .scale(500) 
    .translate([ (w - 300)/2, h/2]) 
    .clipAngle(90) 
    .rotate([90, 0, 0]) 
    .precision(.1); 

    this.path = d3.geo.path() 
    .projection(this.projection); 

    //update path WITH transition 
    d3.selectAll('path') 
    .transition() 
    .duration(900) 
    .attr('d', app.path); 

} 

Die Karte wechselt von Albers zu orthographisch, aber der Übergang ist nicht glatt. Irgendwelche Gedanken wären großartig.

Antwort

17

Wenn Sie den Pfad mit dem naiven String-Interpolator von D3 interpolieren (d3.interpolateString), müssen die Anzahl der Koordinaten im Startpfad und die Anzahl der Koordinaten im Endpfad exakt übereinstimmen, einschließlich in der gleichen Reihenfolge. Dies ist aber aufgrund von clipping, cutting und resampling fast nie der Fall. Shape interpolation ist möglich (mit multiplestrategies), aber es ist ein schweres Problem, im allgemeinen Fall zu lösen. Siehe this explanation (Teil der Path Transitions) für warum naive Interpolation nicht ausreicht.

Anstatt den Pfad zu interpolieren, interpolieren Sie die Projektion. Die Interpolation der Projektion erfordert keine exakte Übereinstimmung zwischen den Koordinaten und vermeidet daher Interpolationsartefakte. Sehen Sie diese Beispiele für eine Demonstration:

Wie im ersten Beispiel gezeigt, hier ist eine Implementierung können Sie:

function interpolatedProjection(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); 
} 

Erstellen Sie die interpolierte Projektion mit tw o Projektionen a und b, und stellen Sie dann das interpolierte Alpha auf einen Wert zwischen 0 (für a) und 1 (für b) ein.

+3

Ist es möglich, den clipAngle auf diese Weise zu interpolieren? Keines der Beispiele demonstriert dies - ich versuche, von orthographisch/90 zu equirectangular/180 überzugehen und es gibt viele seltsame Artefakte – Casey