Matrixtransformation: Konvertierung von SVG-Pfadkoordinaten in das Leaflet-Koordinatensystem

9

Die kurze Version: Wie kann ich einer Leaflet-Map SVG-Pfade so hinzufügen, dass die Pfade aktualisiert werden, wenn sich die Kartenkoordinaten ändern (z. B. bei Zoomänderung oder Folie)?

Die lange Version: Hallo, ich habe ein topographisches Bild das enthält Gebäudeumrisse. Nach der Georefixierung des Bildes habe ich Photoshop verwendet, um die Rasterdaten in SVG . Ich kenne die Geokoordinaten der Begrenzungsbox, die den SVG-Umfang beschreiben, und kenne die internen Koordinaten von SVG-Pfadelementen. Ich frage mich, wie ich die Gebäude, die in den Pfadelementen des obigen SVG beschrieben sind, jetzt zu einer Leaflet-Map hinzufügen kann.

Hier ist eine Geige, die die Begrenzungsbox des SVG-Bildes in Rot und die Gebäude in Blau zeigt: Ссылка Wie du kannst Sehen Sie, die Gebäude sind noch nicht richtig in Bezug auf die Begrenzungsbox ausgerichtet.

Mein ursprünglicher Plan zum Ausrichten der Gebäude bestand darin, ein einmaliges Skript zu verwenden, um die Pfadelemente aus dem SVG-Koordinatensystem in Breitenkoordinaten zu konvertieren, lange Koordinaten und dann die Gebäude auf der Karte mit der Polylinienfunktion zu zeichnen Begrenzungsbox:

%Vor%

Das Problem bei diesem Ansatz besteht darin, dass Leaflet-Polylinien keine Bezier-Kurven zeichnen können, die in den obigen SVG-Pfadelementen vorhanden sind. Als Workaround dachte ich, ich könnte lineare Annäherungen für die Bezier-Kurven verwenden, obwohl dies zu einer ordentlichen Menge an Arbeit werden könnte.

Schließlich erkannte ich, dass das SVG für die Bounding Box in der obigen Fiedel Bezier-Kurven verwendet, was mir den Gedanken gab, dass ich stattdessen Matrixtransformationen verwenden könnte, um den Koordinatenraum der Gebäude-SVGs in den Leaflet-Koordinatenraum zu transponieren. Die obige Fiedel benutzt eine Sample-Matrix-Transformations-CSS-Regel, um die Gebäudeebene zu transformieren.

Bevor ich weiter in dieses Kaninchenloch ging, wollte ich fragen: Was glauben andere, ist der beste Weg, die Wege, die die Gebäude in der SVG oben beschreiben, in die Leaflet-Karte in der Geige einzutragen? Ich wäre sehr dankbar für jeden Rat, den andere zu dieser Frage anbieten können!

PROGRESS: Ich habe beschlossen, dieses Problem zu vereinfachen und herauszufinden, wie man mit einer Matrixtransformation ein div ("A") in das Seitenverhältnis eines anderen div ("B") umwandelt. Dabei habe ich ein kleines Python-Skript erstellt, das die Pixelkoordinaten des Eingabe-Divs A und die gewünschten Ausgabe-Div-Bs als Eingabe verwendet Pixelkoordinaten. Dieses Skript erzeugt die Transformationsmatrix X so, dass AX = B ist. Das Skript ist intern dokumentiert und hat eine begleitende Geige .

Ich habe auch ein gist erstellt, das die Transformationsmatrix ableitet, um Punkte aus dem SVG-Raum in geeignete Lat-Koordinaten zu projizieren . Im schlimmsten Fall kann ich die SVG-Pfadelemente partitionieren, das Skalarprodukt jedes Punktes mit der Transformationsmatrix kombinieren und Polylinien mit Flugblättern zeichnen, um die Gebäude zu zeichnen. Das wird aber die Bezier-Kurven verlieren ...

    
duhaime 02.07.2016, 02:08
quelle

3 Antworten

2

Das hat ein bisschen nachgedacht, aber ich habe eine Lösung gefunden.

Nach dem Lesen erkannte ich, dass man Punkte von einem Koordinatenraum (z. B. dem SVG-Koordinatenraum) zu einem anderen (z. B. und dem Längen- / Breitenkoordinatenraum) transponieren kann, indem man eine Transformationsmatrix identifiziert und dann jeden Punkt multipliziert Eingabebereich (SVG) durch diese Transformationsmatrix. Diese Operation transponiert den gegebenen Punkt an die entsprechende Stelle in der Karte.

Ich schrieb dieses Skript , um die erforderliche Transformationsmatrix zu berechnen. Das Skript nimmt als Parameter die Koordinaten der Bounding Box des SVG und die Bounding Box Koordinaten des georektifizierten Geotiffs, aus dem die SVG Elemente extrahiert wurden. Das Skript erzeugt die Transformationsmatrix und zeigt an, wie man Punkte im SVG-Raum mit der Matrix multiplizieren kann, um ihre geeigneten Längen- / Breitenkoordinaten zu finden.

Es gibt einen Haken - man muss die Punkte in der SVG ohne jegliche CSS-Transformation darstellen. Um eine einfache Darstellung der Position eines SVG-Punktes innerhalb des SVG zu erhalten, habe ich Pfadelemente im SVG in Polygon-Elemente umgewandelt mit dieses Tool , für das die Quelle frei verfügbar ist .

Falls andere eine ähnliche Aufgabe erledigen müssen, hier war der vollständige Workflow, den ich verwendet habe:

  1. Suchen Sie nach einer Rasterkarte (jpg / tiff) von Interesse.
  2. Korrigieren Sie die Karte mit QGIS, ArcGIS oder MapWarper. Dies erzeugt einen Geotiff.
  3. Downloaden und installieren Sie GDAL , eine leistungsstarke Geospatial-Bibliothek mit Python-Bindungen.
  4. Führen Sie in Adobe Illustrator eine Bildspur für ein interessantes Feature in Ihrem Geotiff (z. B. Gebäude) aus. Dies erzeugt eine Vektorschicht; Speichern Sie die Vektorebene als SVG-Datei.
  5. Wenn in Ihrem gespeicherten SVG <rect> oder andere geometrische Formen vorhanden sind, konvertieren Sie sie in Pfade und speichern Sie sie erneut.
  6. Identifizieren Sie die Bounding Box-Koordinaten Ihres SVG und des Geotiffs, das Sie als Eingabe für Illustrator eingegeben haben. Die Bounding Box der letzteren kann von GDAL erhalten werden, indem% cco_de% ausgeführt wird.
  7. Fügen Sie diese Bounding Box-Koordinaten in das oben erwähnte Skript ein. Partitionieren Sie dann Ihr SVG in ein Array von gdalinfo {your-geotiff-file.tif} -Elementen, und teilen Sie für jedes das Polygon in ein Array von Punkten. Multiplizieren Sie jeden Punkt mit der Transformationsmatrix, um die lat / long-Position des Punkts zu finden.
  8. Speichern Sie jeden Punkt jeder Form in einem geeigneten Geojson-Format, damit Sie die Daten in den Client laden können.

Was es wert ist, ist das Skript, das ich zum Generieren der Matrixtransformation und zum Transponieren von <polygon> -Elementpunkten in lat / long space verwendet hier . Bitte beachten Sie, dass einige Pfade im Skript für Ihre Situation aktualisiert werden müssen - z. Das Skript schiebt den Ausgabe-Geojson in einen S3-Bucket, den mein Labor verwaltet:)

Ich hoffe, das hilft jemandem, der sich dieser Aufgabe gestellt sieht! Ich bin ehrlich gesagt erstaunt, dass dies so viel Aufwand erfordert, und ich bin mir ziemlich sicher, dass es einen eleganteren Workflow geben muss ...

    
duhaime 08.09.2016 15:08
quelle
1

Ich habe diese Funktion zur Arbeit hinzugefügt, die ich zuvor auf Leaflet Maps durchgeführt habe. Dies kann für Ihre Anwendung gelten. Siehe: www.svgdiscovery.com/K/K04A.htm

Dies verwendet zwei wichtige Punkte, die sowohl für die Leaflet-Map als auch für die importierten SVG-Pfade gelten.

    
Francis Hemsher 12.07.2016 01:22
quelle
0

Im folgenden Beispiel werden Ihre Polylinienwerte verwendet, um den Ansatz zu demonstrieren, wie er für Svg-Pfade und andere Formen beim Zoomen / Schwenken der Leaflet-Map gelten würde. Grundsätzlich wird eine SVG-Schicht erstellt und alle SVG-Elemente werden hinzugefügt.

%Vor%
    
Francis Hemsher 02.07.2016 16:25
quelle