2016-05-05 10 views
2

Ich möchte eine Karte erstellen, die auf der Z-Achse geneigt ist, als ob man sie flach auf einen Tisch gelegt hätte. Kein Problem: Verwenden Sie Mike Bostocks Ansatz custom projection, definieren Sie eine einfache Transformation, die zurückgeht, wenn sie nach oben geht, nennen Sie es einen Tag.d3 - Darf ich irgendwie zwei Projektionen erstellen oder eine Projektion projizieren?

Außer im Prozess erfuhr ich, dass d3 zum Albers USA Vorsprung wurde in Verzug, und dass meine benutzerdefinierten Projektion setzen Alaska und Hawaii zurück zu ihren richtigen Platzierungen (was ich nicht will.)

Auch Ich hatte nicht realisiert, dass Puerto Rico nicht auf der Albers USA Projektion war, also würde ich eigentlich gerne auf Albers USA + PR wechseln.

Ich würde es vorziehen, die Projektion nicht neu zu machen, wenn ich es helfen kann, weil ich eines Tages einen Albers finden werde, der auch die verschiedenen anderen US-Territorien hat.

Sind Projektionen irgendwie zusammensetzbar?

Antwort

2

Ohne die genauen Details Ihrer Implementierung zu kennen, habe ich forked Mike Bostock Block AlbersUSA + PR, um eine Möglichkeit zu zeigen, dass dies getan werden könnte.

In seinem Kern verwendet dies die Albers USA Projektion, die Puerto Rico wie gewünscht enthält. Dies ist ein normaler D3 projection:

var albersUsaPrProj = albersUsaPr() 
    .scale(1070) 
    .translate([width/2, height/2]); 

Als nächstes ich umgesetzt haben ein eher na ï Projektion auf dem Tisch habe, die eine gewisse Verfeinerung brauchen könnte, sollte aber ausreichen, um Sie zu erhalten begonnen. Dieser verwendet d3.geo.transform(), um einen Stream-Wrapper für die Berechnungen zu erstellen, die zum Projizieren der Karte auf dem Desktop benötigt werden. Die eingewickelte stream listener muss nur die point Methode implementieren, die mit den x, y Bildschirmkoordinaten, die die Ergebnisse aus der Geo Projektion sind, aufgerufen werden.

// The scale is used for convenient calculations only. 
var yScale = d3.scale.linear() 
       .domain([0,height]) 
       .range([0.25,1]); 

var desktopProj = d3.geo.transform({ 
    point: function(x,y) { 
    this.stream.point((x - 0.5*width) * yScale(y) + (0.5*width), y); 
    } 
}); 

Beiden Vorsprünge sind leicht in einen neuen Stream wrapper kombiniert, indem ein Objekt zu schaffen, das .stream() Verfahren.

var combinedProj = { 
    stream: function(s) { 
     return albersUsaPrProj.stream(desktopProj.stream(s)); 
    } 
}; 

Gemäß der Dokumentation auf projection.stream(listener):

Gibt einen vorspringenden Stream Wrapper für den angegebenen Zuhörer. Jede Geometrie, die zum Wrapper gestreamt wird, wird projiziert, bevor sie zum umschlossenen Listener gestreamt wird.

Dies wird zunächst albersUsaPrProj nehmen lassen Pflege der Projektion Albers USA und Plan, danach strömen die resultierende Bildschirm desktopProj koordiniert.

über den Strom-Transformation für mehr Kontrolle, die Projektions kann als ein Objekt festgelegt werden, der den Strom Methode implementiert:

Diese kombinierte Vorsprung kann dann an path.projection([projection]) geben werden. (Siehe Beispiel.) Die stream-Methode verwendet einen Ausgabestream als Eingabe und gibt einen umschlossenen Stream zurück, der die Eingabegeometrie projiziert. mit anderen Worten implementiert es projection.stream.

Dies gibt uns den letzten Aufruf als

var path = d3.geo.path() 
    .projection(combinedProj); 
+0

Herrliche. Ich glaube, dass ich genau das brauche. SO lässt mich eine Stunde warten, um das Kopfgeld zu vergeben. –

+0

Übrigens: Kennen Sie eine Formulierung für eine Variante wie Albers + PR, die alle US-Territorien umfasst, oder ist + PR die beste, die ich bekommen werde, und muss ich die anderen selbst bewegen? –

+0

@JohnHaugeland Ich bin mir nicht sicher, in welchen anderen US-Territorien Sie sich bewegen müssen, wenn Sie Albers US + PR verwenden, da diese Projektion das Festland der USA, Alaska, Hawaii und Puerto Rico darstellen wird. Wenn ich mich nicht völlig irre, sollte das ziemlich genau die von den USA beanspruchten Gebiete einschließen ;-) – altocumulus