Ich habe nach einer soliden Lösung gesucht, mit der ich eine Webkarte erstellen und Vektorpolygone überlagern kann, ohne dass es für immer dauert, solche Daten zu laden , um zu ermöglichen, dass jedes Polygon bei einem Schwebeflugereignis eine andere Farbe anzeigt.
Soweit mir bekannt ist, gibt es drei spezielle Optionen, um dies über Canvas, SVG und Flash zu erreichen.
Flash scheint die beste Lösung zu sein, wenn es auf Apple iPhones / iPads funktioniert, da es das schnellste Rendering und die sauberste Anzeige bietet. Canvas scheint die zweitbeste Wahl zu sein, dauert jedoch SEHR lange, wenn Hunderte von Polygonen auf einer Karte angezeigt werden, während das Rendern von SVG noch länger dauert.
Ich habe fast die Hoffnung verloren, eine Lösung für dieses Problem zu finden, aber heute bin ich auf eine Firma namens GISCloud http://www.giscloud.com gestoßen (derzeit in der Beta mit kostenloser Registrierung).
Diese Firma hat es irgendwie geschafft, einen erstaunlichen Weg zu finden, um Hunderte von Vektoren auf einer Karte in nahezu Echtzeit zu rendern. Ich war erstaunt über ihre Herangehensweise und meine Frage an die Community bezieht sich darauf, wie wir ihre Herangehensweise für die Verwendung mit vorhandenen Technologien wie Broschüren, Openlayern, Wachs nachbilden können.
Überzeugen Sie sich selbst von dieser erstaunlichen Demo: http://www.giscloud.com/map/284/africa
Stellen Sie sicher, dass Sie den Mauszeiger über eines der Polygone auf der Seite halten, und testen Sie die Zoom-Steuerelemente, um festzustellen, ob es sich bei diesen Polygonen tatsächlich um Vektoren handelt.
Was mir beim Betrachten von Anfragen mit Firebug aufgefallen ist, dass die Map bestimmte JSON-Dateien anfordert. Es scheint, dass abhängig von der Zoomstufe / dem Zoombereich mehrere JSON-Dateien angefordert werden.
Ich möchte hier auch erwähnen, dass giscloud nach dem Laden der Daten auf der Seite, die über einem Vektor schweben, sofort die Farbe ändert, ohne eine neue Anforderung zu erstellen.
BEISPIELE
- http://cft1.giscloud.com/t/1316509973/map284/layer1156/3/3/3.json
- http://cft1.giscloud.com/t/1316509973/map284/layer1156/3/5/3.json
- http://cft1.giscloud.com/t/1316509973/map284/layer1156/3/4/4.json
- http://cft1.giscloud.com/t/1316509973/map284/layer1156/3/3/4.json
- http://cft1.giscloud.com/t/1316509973/map284/layer1156/3/5/4.json
Ich gehe davon aus, dass die URL-Struktur der Standard-Tiling-Service-Logik folgt (zum Beispiel ist der drittletzte Ordner die Zoomstufe ...).
Auf jeden Fall habe ich die tatsächlichen Daten dieser JSON-Dateien analysiert und es scheint, dass die von ihnen verwendete Logik einer Art Logik folgt, mit der sie ihre Vektoren nur auf der Grundlage dieser Datenwerte erstellen:
- width / height: Sie definieren die Breite und Höhe der Daten, die in jeder JSON-Anfrage geliefert werden
- Pixel: Hier definieren sie Pixelwerte, von denen ich annehme, dass sie sich auf einige allgemeine x / y-Pixelkoordinaten für verallgemeinerte Punktebenen beziehen. Ich vermute, sie haben irgendwie eine Möglichkeit, die Region abhängig von der Zoomstufe automatisch zu vereinfachen. Ich gehe davon aus, dass sie Pixelkoordinaten verwenden. Ich vermute, dass sie die Größe der zu ladenden Daten im Vergleich zu Lat / Long-Daten drastisch reduzieren.
- Stile: Hier definieren sie zwei RGB-CSS-Werte. "F" repräsentiert die Farbe der Polygondatei und "S" repräsentiert die Farbe der Polygonumrandung.
- geom: hier denke ich, definieren sie irgendwie spezifisch jedes polygon innerhalb der zu ladenden kachel , wo solche daten basierend auf dem kartencontainerfenster definiert werden. Interessant ist auch, dass jeder Eintrag einen "S" -Wert hat, von dem ich annehme, dass er als optionales Attribut oder als Feature-Link-Wert verwendet wird. Am Ende jedes Eintrags befindet sich hier ein Bereich, der zusammen mit eine bestimmte Vektor-ID zu definieren scheint Die Layer-ID, die ich errate, wird verwendet, um die Daten aus jeder aufgerufenen JSON-Kachel-Anfrage zu verknüpfen.
Ich gehe auch davon aus, dass sie irgendwie eine Möglichkeit gefunden haben, die Daten, die für jede Kachel geladen werden müssen, abhängig von der Größe der Daten, die für die angeforderte Kachel geladen werden müssten, automatisch zu bestimmen und aufzuteilen.
Hier ist eine extrahierte Aufschlüsselung einer dieser Anforderungen:
{"width":256,"height":256,"tile":
{"pixels":
[0,6461,-1,0,5,148,0,509,-1,10715,-1,1,-1,251,-1,1,-1,1,-1,251,-2,3,-1,255,-1,249,-2,5,-2,247,-1,509,-3,251,-1,2,-2,253,-2,252,-2,254,-1,255,-1,254,-1,255,-1,1276,-2,13,-1,233,-1,2,-1,253,-1,1,-1,255,-1,247,-1,1306,-1,1533,-1,1269,-1,1276,-1,2303,-1]},
"styles":
[{"f":"rgb(99,230,101)","s":"rgb(5,148,0)","lw":"0"}],
"geom":
[
{"s":0,"p":[4,143,5,144,3,146,1,146,2,143,4,143],"c":"layer1156_5098"},
{"s":0,"p":[-2,143,0,140,2,141,2,144,1,146,-2,144,-2,143],"c":"layer1156_5067"},
{"s":0,"p":[7,143,5,144,4,143,2,143,2,141,5,138,6,139,5,141,7,143],"c":"layer1156_5051"},
{"s":0,"p":[10,141,11,137,12,137,14,137,12,142,9,143,9,142,10,141],"c":"layer1156_5041"},
{"s":0,"p":[1,136,0,140,-2,143,-2,136,1,136],"c":"layer1156_5038"},
{"s":0,"p":[8,143,5,141,5,137,8,136,10,137,10,141,8,143],"c":"layer1156_5033"},
{"s":0,"p":[5,137,2,141,0,140,1,136,1,136,2,135,3,136,5,137],"c":"layer1156_5028"},
{"s":0,"p":[10,134,12,136,11,138,8,135,10,134],"c":"layer1156_5020"},
{"s":0,"p":[-2,133,0,136,-2,136,-2,133],"c":"layer1156_5005"},
{...}
...
]
}
Wie können wir die gleiche (oder eine ähnliche) Geschwindigkeit mit Postgis nachbilden (was ich anscheinend auch benutze)?
quelle
Antworten:
Ich habe diese Technik in der Vergangenheit gesehen. Es wurde mir von Zain Memon (aus Trulia) erklärt, der mitgeholfen hat, als Michal Migurski TileStache erstellte. Zain ging darauf ein und erklärte seine Trulia-Demo, die diese Technik bei einem unserer älteren SF GeoMeetup-Meetings vor einiger Zeit verwendet . In der Tat, wenn Sie nächste Woche in SF sind (dies ist mein lahmer Versuch an einem Stecker, wird er dies berühren , also zögern Sie nicht, sich zu zeigen :)
OK, jetzt zur Erklärung.
Erstens suchen Sie etwas an der falschen Stelle, wenn Sie die obigen json-Dateien betrachten.
Lassen Sie mich erklären (so kurz ich kann), warum.
Die Kacheln werden wie normale gerenderte Kacheln weitergereicht, keine große Sache, wir wissen, wie das geht, und deshalb muss ich das nicht erklären.
Wenn Sie es in Firebug überprüfen, werden Sie feststellen, dass Sie auch eine ganze Reihe von Bildern erhalten, die leer zu sein scheinen, wie dieses .
Warum ist es leer? Es ist nicht. Die Pixel enthalten Daten - nur keine herkömmlichen sichtbaren Bilddaten. Sie verwenden eine sehr clevere Technik, um Daten, die in den Pixeln selbst codiert sind, weiterzuleiten.
In den letzten zehn Jahren wurden Lesbarkeits- und Portabilitätsdaten von Formaten auf Kosten der Speichereffizienz abgewogen.
Nehmen Sie dieses Beispiel für XML-Beispieldaten:
OK, wie viele Bisse, um dies zu übertragen? Vorausgesetzt, wir haben utf8 (1 Byte pro Zeichen im Umgang mit diesem Inhalt). Nun, wir haben ungefähr 176 Zeichen (ohne Tabulatoren oder Leerzeichen zu zählen), was diese 176 Bytes ergibt (dies ist aus verschiedenen Gründen, die ich der Einfachheit halber weglassen werde, optimistisch). Wohlgemerkt, das sind 2 Punkte!
Trotzdem behauptet ein kluger Arsch, der nicht versteht, wovon er spricht, dass "json Ihnen eine höhere Komprimierung gibt".
Gut, lassen Sie uns den gleichen XML-Unsinn wie json verwenden:
Wie viele Bytes hier? Sagen Sie ~ 115 Zeichen. Ich habe sogar ein bisschen geschummelt und es kleiner gemacht.
Angenommen, mein Bereich umfasst 256 x 256 Pixel und ich habe eine Zoomstufe, die so hoch ist, dass jedes Feature als ein Pixel gerendert wird und ich so viele Features habe, dass es voll ist. Wie viele Daten brauche ich, um diese 65.536 Funktionen zu zeigen?
54 Zeichen (oder utf Bytes - und ich ignoriere sogar einige andere Dinge) pro "Feature" -Eintrag multipliziert mit 65.536 = 3.538.944 oder etwa 3,3 MB
Ich denke, du verstehst das Bild.
Aber so transportieren wir Daten in einer serviceorientierten Architektur. Lesbarer aufgeblähter Mist.
Was wäre, wenn ich alles in einem binären Schema transportieren wollte, das ich selbst erfunden habe? Sagen Sie stattdessen, dass ich diese Informationen in einem Einzelbandbild (dh Schwarzweiß) codiert habe. Und ich entschied, dass 0 verkauft bedeutet und 1 verfügbar bedeutet und 2 bedeutet, dass ich es nicht weiß. Heck, in einem 1-Byte, ich habe 256 Optionen, die ich verwenden kann - und ich verwende nur zwei oder drei von ihnen für dieses Beispiel.
Was sind die Lagerkosten dafür? 256 x 256 x 1 (nur ein Band). 65.536 Bytes oder 0,06 MB. Dabei werden nicht einmal andere Komprimierungstechniken berücksichtigt, die ich aus mehreren Jahrzehnten Forschung im Bereich der Bildkomprimierung kostenlos erhalte.
An dieser Stelle sollten Sie sich fragen, warum nicht einfach Daten im Binärformat gesendet werden, anstatt sie an json zu serialisieren. Zunächst stellt sich heraus, dass Javascript viel Zeit für den Transport von Binärdaten in Anspruch nimmt, weshalb die Leute dies historisch nicht getan haben.
Eine großartige Arbeit wurde von einigen Leuten verwendet, als die neuen Funktionen von HTML5 herauskamen, insbesondere Canvas . Was ist das für eine großartige Abhilfe? Es hat sich herausgestellt, dass Sie Daten über die Leitung senden können, die auf einem scheinbaren Bild codiert ist, und dieses Bild dann in eine HTML5-Zeichenfläche verschieben können, mit der Sie die Pixel direkt bearbeiten können ! Jetzt haben Sie die Möglichkeit, diese Daten zu erfassen, sie clientseitig zu dekodieren und die JSON-Objekte im Client zu generieren.
Halte einen Moment inne und denke darüber nach.
Sie haben die Möglichkeit, eine große Menge aussagekräftiger georeferenzierter Daten in einem hochkomprimierten Format zu codieren, das um Größenordnungen kleiner ist als alles, was traditionell in Webanwendungen durchgeführt wird, und sie in Javascript zu bearbeiten.
Die HTML-Zeichenfläche muss nicht einmal zum Zeichnen verwendet werden, sondern wird nur als binärer Dekodierungsmechanismus verwendet!
Darum geht es in all den Bildern, die Sie in Firebug sehen. Ein Bild mit den Daten, die für jede heruntergeladene Kachel codiert sind. Sie sind super klein, haben aber aussagekräftige Daten.
Wie verschlüsseln Sie diese auf der Serverseite? Nun, Sie müssen die Daten auf der Serverseite verallgemeinern und eine aussagekräftige Kachel für jede Zoomstufe erstellen, in der die Daten codiert sind. Derzeit müssen Sie dazu Ihre eigene rollen - eine Open-Source-Lösung ist nicht im Lieferumfang enthalten, Sie verfügen jedoch über alle Tools, die Sie dazu benötigen. PostGIS übernimmt die Generalisierung über GEOS. Mit TileCache können Sie die Kacheln zwischenspeichern und die Kachelgenerierung auslösen. Auf der Clientseite müssen Sie HTML5 Canvas verwenden, um die speziellen "gefälschten Kacheln" weiterzuleiten. Anschließend können Sie mit OpenLayers echte clientseitige Javascript-Objekte erstellen, die die Vektoren mit Mouse-Over-Effekten darstellen.
Wenn Sie mehr Daten codieren müssen, denken Sie daran, dass Sie immer RGBA-Bilder pro Pixel generieren können (dies ergibt 4 Bytes pro Pixel oder 4.294.967.296 Zahlen, die Sie pro Pixel darstellen können ). Ich kann mir verschiedene Möglichkeiten vorstellen, das zu nutzen :)
Update : Beantwortung der unten stehenden QGIS-Frage.
QGIS hat wie die meisten anderen Desktop-GIS keine festen Zoomstufen. Sie haben die Flexibilität, in jedem Maßstab zu zoomen und nur zu rendern. Können sie Daten aus WMS- oder Kacheln-basierten Quellen anzeigen? Sicher können sie das, aber die meiste Zeit sind sie wirklich dumm: In einem anderen Ausmaß zoomen, den Begrenzungsrahmen berechnen, die erforderlichen Kacheln berechnen, sie greifen, sie zeigen. Meistens ignorieren sie andere Dinge, wie z. B. HTTP-Header-Caches, die dazu führten, dass sie nicht erneut abrufen mussten. Manchmal implementieren sie einen einfachen Cache-Mechanismus (speichern Sie die Kachel, wenn Sie danach fragen, suchen Sie nach der Kachel, fragen Sie nicht danach). Das reicht aber nicht.
Bei dieser Technik müssen die Kacheln und Vektoren in jeder Zoomstufe neu abgerufen werden . Warum? Weil die Vektoren verallgemeinert wurden, um Zoomstufen aufzunehmen.
Was den ganzen Trick angeht, die Kacheln auf eine HTML5-Zeichenfläche zu legen, damit Sie auf die Puffer zugreifen können, ist das alles nicht erforderlich. Mit QGIS können Sie Code in Python und C ++ schreiben. Beide Sprachen bieten eine hervorragende Unterstützung für den Umgang mit Binärpuffern. Daher ist diese Problemumgehung für diese Plattform wirklich irrelevant.
* UPDATE 2 **:
Zunächst wurde die Frage gestellt, wie die verallgemeinerten Vektorkacheln erstellt werden sollen (Baby-Schritt 1, bevor die Ergebnisse in Bilder serialisiert werden können). Vielleicht habe ich nicht genug geklärt. Mit Tilestache können Sie effektive "Vektorkacheln" Ihrer Daten in jeder Zoomstufe erstellen (es gibt sogar eine Option, mit der Sie die Daten entweder beschneiden oder nicht beschneiden können, wenn sie die Kachelgrenze überschreiten). Dadurch werden die Vektoren in verschiedenen Zoomstufen in Kacheln aufgeteilt. Ich würde die Option "Nicht beschneiden" wählen (aber es wird eine beliebige Kachel ausgewählt, die mehr Fläche abdeckt). Dann können Sie jeden Vektor durch die GEOS-Generalisierungsoption mit einer großen Zahl versorgen. Tatsächlich möchten Sie, dass die Polylinien und Polygone in sich zusammenfallen, da Sie sie in diesem Stadium aus der Zoomstufe entfernen können irrelevant. Mit Tilestache können Sie sogar einfache Pythonic-Datenprovider schreiben, in die Sie diese Logik einfügen können. In diesem Stadium können Sie wählen, ob Sie sie als JSON-Dateien (wie einige der afrikanischen Kartenbeispiele) oder als serialisierte Geometrien in den PNGs (wie andere der oben genannten Beispiele (oder der Trulia)) bereitstellen möchten.
quelle
Direkt vom Entwickler Dino Ravnic auf einer kürzlich veröffentlichten Mailingliste :
Es klingt also so, als ob die Client-Seite der einfache Teil ist. Es ist beeindruckend, dass die Daten ohne Zwischenspeicherung gerendert werden.
Er erwähnt auch einen Hosting-Service , der für Sie von Interesse sein kann. Möglicherweise möchten Sie die Kosten für den Versuch, diese wiederherzustellen, mit den Kosten für die Verwendung eines vorgefertigten Service abwägen.
quelle
Wie ich in der OSGeo-Liste beschrieben habe, liegt der Schlüssel darin, Daten als Vektor-JSON-Kacheln zu liefern, die Pixel für Subpixel-Geometrie und verallgemeinerte Geometrie für die Features enthalten, die auf einer bestimmten Ebene tatsächlich sichtbar sind. Die Leistung ist hervorragend, da mit dieser Technik alle unnötigen Vektorinformationen eliminiert werden und nur die Vektoren übrig bleiben, die tatsächlich eine visuelle Auswirkung auf die Karte haben. Pixel sollen die Lücken füllen und anstelle dieser Subpixelvektoren platziert werden. Das ist es in Bezug auf das Kachelformat.
Auf der Backend-Seite befindet sich das wahre Schwerheben. Wir verwenden weder TileStache noch eine andere Karten-Engine, da wir unsere eigene geschrieben haben, die mit einer Reihe von Optimierungen solche Vektorgrafiken in Echtzeit erstellen kann.
Zuerst haben wir Kartenkacheln als SWF-Dateien bereitgestellt und in letzter Zeit die Ausgabe in JSON aktiviert, damit die Grafiken mit HTML5 Canvas gerendert werden können. Im Folgenden finden Sie eine Benchmark, die diese Art der Vektortechnologie mit der Rastertechnologie (Mapnik) vergleicht. Für einen fairen Vergleich suchen Sie die Ergebnisse nur im CGI-Modus.
http://www.giscloud.com/blog/realtime-map-tile-rendering-benchmark-rasters-vs-vectors/
Wir planen, diese Technologie als Hosting-Service für Kartenkacheln bereitzustellen. Die Idee ist, Ihre Geodaten in der Cloud zu hosten und über HTML5 mit hoher Geschwindigkeit in jeden Karten-Client zu übertragen, ohne dass die Kacheln vorab zwischengespeichert werden müssen. Wenn Sie an dieser Beta teilnehmen möchten, können Sie uns hier kontaktieren: http://www.giscloud.com/contact/
quelle
Vor kurzem wurde im OSGeo Open Layers-Forum eine sehr ähnliche Frage gestellt , in der die GIS Cloud-Entwickler ihren Ansatz beschreiben. Dabei handelt es sich um eine interessante Mischung aus GeoJSON-Geometrien und statischen Pixeln. Sie generieren tatsächlich alle Vektorkacheln im laufenden Betrieb, anstatt einen vorgefertigten Cache aus GeoJSON-Dateien zu verwenden.
Esri hat einen ähnlichen Ansatz mit ArcGIS Server und Feature Layern implementiert, mit denen die Geometrien im laufenden Betrieb verallgemeinert und als JSON über den Draht gesendet werden können.
Für eine einfache Methode, die Sie jetzt tatsächlich implementieren können, können Sie mit Tilestache (das PostGIS unterstützt ) Vektorkacheln erstellen und diese in Polymaps verwenden . Polymaps verwendet SVG, aber die Leistung ist recht gut , und es gelten CSS-Regeln für die Formatierung von Kartenelementen, sodass das Rendern von Features ganz Ihnen überlassen bleibt . Hier ist ein Blog - Post über etwas arbeiten ähnlich dem , was ihr bittet.
quelle
Ich habe mit OpenLayers über Canvas gespielt und vernünftige Ergebnisse erzielt.
Wie in den anderen Antworten erwähnt: Um Vektoren im Flug zu liefern und anzuzeigen, müssen sie für jede Zoomstufe und jeden Datensatz verallgemeinert werden. Sie können auch die Google-Polylinienkodierung verwenden, um die Größe erheblich zu verringern.
Ich habe einen einfachen Liefermechanismus verwendet. Jede Geometrie war eine JavaScript-Funktion in einer JavaScript-HTTP-Antwort. Nicht so fortschrittlich wie die fliesenbasierte Vektorlieferung, aber einfach und Open Source!
Ich habe Google Maps v3 mit Canvas nicht ausprobiert, aber ich habe ein paar beeindruckende Demos der New York Times gesehen .
quelle
Ich weiß nicht genau, welche Lösung von dieser Firma verwendet wird (Sie könnten sie vielleicht direkt fragen), aber ich habe eine Idee.
Die Schlüssellösung zur Verbesserung der Netzwerkübertragung und der Rendergeschwindigkeit von Vektordaten besteht darin, sie entsprechend der Zoomstufe zu verallgemeinern: Das Übertragen und Rendern von Tausenden von Objekten, die für eine viel niedrigere Zoomstufe ausgelegt sind, ist häufig sehr zeitaufwendig (und außerdem) nutzlos, weil die endgültige Anzeige normalerweise nicht lesbar ist (siehe zum Beispiel dieses Bild ). Um dies zu implementieren, muss Ihre Postgis-Serverdatenbank mehrere Maßstäbe haben : Für jede Zoomstufe sollte eine Darstellung des Objekts vorhanden sein, das für diese Zoomstufe geeignet ist. Diese verschiedenen Darstellungen können unter Verwendung von Generalisierungstechniken automatisch berechnet werden. Darüber hinaus sollten die vom Server an den Client gesendeten Vektordaten nicht nur von der räumlichen Ausdehnung, sondern auch von der Zoomstufe abhängen: Der Server sendet je nach Zoomstufe geeignete Daten. Dies ist der Ansatz, der in diesem ausgezeichneten Artikel vertreten wird :-)
quelle
Es gibt ein interessantes Papier, eine Demo und einen Quellcode einer von der Stanford Visualization Group entwickelten Software, die Datenwürfel für jede Kachel verwendet, um einen großen geografischen Datensatz zu visualisieren und zu untersuchen. Es kann nur für Punktdatensätze verwendet werden, kann aber eine interessante Möglichkeit sein.
http://vis.stanford.edu/papers/immens
Die Vizzualität mit ihrer CartoDB-Plattform und der Bibliothek mit dem Namen Torque experimentiert auch damit, wie ein hohes Datenvolumen gezeichnet werden kann.
http://cartodb.github.io/torque/
https://github.com/CartoDB/torque/tree/new_torque
quelle