Suite

Créer des polygones vectoriels avec des performances de rendu comme GISCloud ?


Je cherchais une solution solide qui me permettrait de créer une carte Web et superposer des polygones vectoriels sans prendre une éternité pour charger de telles données dans le but de me permettre de faire en sorte que chaque polygone affiche une couleur différente lors d'un événement de survol.

Pour autant que je sache, il existe 3 options spécifiques pour y parvenir via canvas, SVG, Flash.

Flash semble être la meilleure solution s'il fonctionnait sur les iphones/ipads Apple, car il semble fournir le rendu le plus rapide et l'affichage le plus propre. Canvas semble être le deuxième meilleur choix mais prend TRÈS longtemps si vous avez des centaines de polygones affichés sur une carte alors que SVG prend encore plus de temps à rendre.

je presque perdu espoir de trouver une solution à ce problème mais aujourd'hui, je suis tombé sur une entreprise appelée GISCloud http://www.giscloud.com (actuellement en version bêta avec inscription gratuite).

Cette société a réussi à trouver un moyen incroyable de rendre des centaines de vecteurs sur une carte en temps quasi réel. J'ai été émerveillé par leur approche et ma question à la communauté concerne la façon dont nous pouvons reproduire leur approche pour une utilisation avec des technologies existantes telles qu'un dépliant, des couches ouvertes, de la cire…

Jetez un œil par vous-même en visionnant cette incroyable démo : http://www.giscloud.com/map/284/africa

Assurez-vous de survoler l'un des polygones de la page et testez les commandes de zoom pour voir que ces polygones sont bien des vecteurs.

Ce que j'ai remarqué en examinant les demandes avec firebug, c'est que la carte demande des fichiers json spécifiques. Il semble qu'en fonction du niveau/de la zone de zoom, plusieurs fichiers json soient demandés.


Je dois également mentionner ici qu'une fois que giscloud a chargé les données sur la page en survolant un vecteur, la couleur change immédiatement sans créer de nouvelle demande.

EXEMPLES:

Je suppose que la structure de l'URL suit la logique du service de mosaïque standard (par exemple, le 3ème au dernier dossier étant le niveau de zoom…).

Dans tous les cas, j'ai analysé les données réelles de ces fichiers json et il semble que la logique qu'ils utilisent suit un certain type de logique par laquelle ils créent leurs vecteurs uniquement en fonction de ces valeurs de données :

  • largeur hauteur: ils définissent la largeur et la hauteur des données servies dans chaque requête json
  • pixels : ici, ils définissent des valeurs de pixels qui, je suppose, se rapportent d'une manière ou d'une autre à certaines coordonnées générales de pixels x/y pour les niveaux de points généralisés? Je suppose qu'ils ont en quelque sorte un moyen de simplifier automatiquement la région en fonction du niveau de zoom. Je suppose qu'en utilisant des coordonnées de pixels, je suppose qu'ils réduisent considérablement la taille des données à charger par rapport aux données lat/long.
  • modes: ici, ils définissent deux valeurs css RVB. « F » représentant la couleur du fichier de polygone et « S » représentant la couleur de la bordure du polygone.
  • géom : c'est ici que je suppose qu'ils définissent en quelque sorte spécifiquement chaque polygone dans la tuile en cours de chargement où ces données sont définies en fonction de la fenêtre du conteneur de carte. Ce qui est également intéressant, c'est que chaque entrée a une valeur "S" qui, je suppose, est utilisée comme attribut facultatif ou valeur de lien de fonctionnalité et à la fin de chaque entrée ici, il y a une zone qui semble définir un identifiant spécifique par vecteur avec l'ID de couche que je suppose est utilisé pour joindre en quelque sorte les données de chaque demande de tuile json appelée.

Je suppose également qu'ils ont en quelque sorte trouvé un moyen de déterminer et de diviser automatiquement les données qui doivent être chargées pour chaque tuile en fonction de la taille des données qui devraient être chargées pour la tuile demandée.

Voici une ventilation extraite de l'une de ces demandes :

{"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,0140,-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"}, {… }… ] }

Comment pouvons-nous reproduire le même type de vitesse (ou similaire) à l'aide de postgis (ce qu'ils semblent également utiliser) ?


J'ai vu cette technique utilisée dans le passé. Cela m'a été expliqué par Zain Memon (de Trulia) qui a contribué à donner son avis lorsque Michal Migurski créait TileStache. Zain l'a parcouru tout en expliquant sa démo Trulia qui utilise cette technique lors de l'une de nos anciennes réunions SF GeoMeetup il y a quelque temps. En fait, si vous êtes à SF la semaine prochaine (c'est ma tentative boiteuse de plug, il en parlera, alors n'hésitez pas à vous présenter :)

OK, maintenant à l'explication.

Tout d'abord, vous regardez légèrement au mauvais endroit lorsque vous regardez les fichiers json ci-dessus.

Laissez-moi vous expliquer (aussi brièvement que possible), pourquoi.

Les tuiles sont passées comme des tuiles rendues normales, ce n'est pas grave, nous savons comment faire cela et je n'ai donc pas besoin de l'expliquer.

Si vous l'inspectez dans Firebug, vous verrez que vous obtenez également tout un tas d'images qui semblent être vides, comme celle-ci.

Pourquoi est-il vide ? Ce n'est pas. Les pixels contiennent des données - mais pas des données d'images visibles traditionnelles. Ils utilisent une technique très intelligente pour transmettre des données encodées dans les pixels eux-mêmes.

Ce qui s'est passé au cours de la dernière décennie, c'est que les gens ont troqué les données de lisibilité et de portabilité des formats au détriment de l'efficacité du stockage.

Prenons cet exemple d'exemple de données XML :

    -32.1231   10.31243   vendu     -33.1231   11.31243   disponible 

OK, combien de piqûres pour transférer ça ? A condition que nous soyons en utf8 (1 octet par caractère lorsqu'on traite ce contenu). Eh bien, nous avons environ 176 caractères (sans compter les tabulations ou les espaces) ce qui fait que 176 octets (c'est être optimiste pour diverses raisons que j'omettrai par souci de simplicité). Attention, c'est pour 2 points !

Pourtant, un idiot intelligent qui ne comprend pas de quoi il parle, quelque part, prétendra que "json vous donne une compression plus élevée".

Très bien, mettons le même non-sens xml que json :

{ "data": [ "feature" : { "x" : -32.1231, "y" : 10.31243 , "type": "sold" }, "feature" : { "x" : -33.1231, "y" :11.31243 , "type": "disponibilité" }, ] }

Combien d'octets ici ? Dites ~ 115 caractères. J'ai même triché un peu et je l'ai fait plus petit.

Disons que ma zone couvre 256x256 pixels et que je suis à un niveau de zoom si élevé que chaque fonctionnalité est rendue comme un pixel et j'ai tellement de fonctionnalités qu'elle est pleine. De combien de données ai-je besoin pour montrer ces 65 536 fonctionnalités ?

54 caractères (ou octets utf - et j'ignore même d'autres choses) par entrée "fonctionnalité" multipliée x 65 536 = 3 538 944 ou environ 3,3 Mo

Je pense que tu as la photo.

Mais c'est ainsi que nous transportons les données dans une architecture orientée services. Merde gonflée lisible.

Et si je voulais tout transporter dans un schéma binaire que j'ai moi-même inventé ? Dites qu'à la place, j'ai codé cette information dans une image à bande unique (c'est-à-dire en noir et blanc). Et j'ai décidé que 0 signifie vendu, et 1 signifie disponible, et 2 signifie que je ne sais pas. Zut, dans 1 octet, j'ai 256 options que je peux utiliser - et je n'en utilise que 2 ou trois pour cet exemple.

Quel est le coût de stockage de cela? 256x256x 1 (une seule bande). 65 536 octets ou 0,06 Mo. Et cela ne prend même pas en considération les autres techniques de compression que j'obtiens gratuitement à partir de plusieurs décennies de recherche en compression d'images.

À ce stade, vous devriez vous demander pourquoi les gens n'envoient-ils pas simplement des données encodées au format binaire au lieu de les sérialiser en json ? Eh bien d'abord, il s'avère que javascript est nul pour le transport de données binaires, c'est pourquoi les gens ne l'ont pas fait historiquement.

Un formidable travail de contournement a été utilisé par certaines personnes lorsque les nouvelles fonctionnalités de HTML5 sont sorties, en particulier Canvas. Alors, quelle est cette formidable solution de contournement ? Il s'avère que vous pouvez envoyer des données sur le fil encodées sur ce qui semble être une image, puis vous pouvez insérer cette image dans un canevas HTML5, ce qui vous permet de manipuler les pixels directement ! Vous avez maintenant un moyen de récupérer ces données, de les décoder côté client et de générer les objets json dans le client.

Arrêtez-vous un instant et réfléchissez à cela.

Vous avez un moyen d'encoder une énorme quantité de données géoréférencées significatives dans un format hautement compressé, des ordres de grandeur inférieurs à tout ce qui est fait traditionnellement dans les applications Web, et de les manipuler en javascript.

Le canevas HTML n'a même pas besoin d'être utilisé pour dessiner, il n'est utilisé que comme mécanisme de décodage binaire !

C'est de cela que parlent toutes ces images que vous voyez dans Firebug. Une image, avec les données encodées pour chaque tuile téléchargée. Ils sont super petits, mais ils ont des données significatives.

Alors, comment les encodez-vous côté serveur ? Eh bien, vous devez généraliser les données côté serveur et créer une vignette significative pour chaque niveau de zoom contenant les données encodées. Actuellement, pour ce faire, vous devez lancer le vôtre - une solution open source prête à l'emploi n'existe pas, mais vous disposez de tous les outils dont vous avez besoin pour le faire. PostGIS fera la généralisation via GEOS, TileCache peut être utilisé pour mettre en cache et vous aider à déclencher la génération des tuiles. Côté client, vous devrez utiliser HTML5 Canvas pour transmettre les "fausses tuiles" spéciales, puis vous pouvez utiliser OpenLayers pour créer de vrais objets javascript côté client qui représentent les vecteurs avec des effets de survol de la souris.

Si vous avez besoin d'encoder plus de données, n'oubliez pas que vous pouvez toujours générer des images RGBA par pixel (ce qui vous donne 4 octets par pixel ou 4 294 967 296 nombres que vous pouvez représenter par pixel). Je peux penser à plusieurs façons d'utiliser ça :)

Mettre à jour: Répondre à la question QGIS ci-dessous.

QGIS comme la plupart des autres SIG de bureaues, n'ont pas un ensemble fixe de niveaux de zoom. Ils ont la possibilité de zoomer à n'importe quelle échelle et de simplement effectuer un rendu. Peuvent-ils afficher des données de sources WMS ou basées sur des tuiles ? Bien sûr qu'ils le peuvent, mais la plupart du temps, ils sont vraiment stupides à ce sujet : zoomez dans une mesure différente, calculez le cadre de délimitation, calculez les tuiles requises, saisissez-les, montrez-les. La plupart du temps, ils ignorent d'autres choses, comme les caches d'en-tête http qui leur éviteraient d'avoir à récupérer. Parfois, ils implémentent un mécanisme de cache simple (stockez la tuile, si vous la demandez, vérifiez la tuile, ne la demandez pas). Mais ce n'est pas assez.

Avec cette technique les tuiles et les vecteurs doivent être récupérés à chaque niveau de zoom. Pourquoi? Parce que les vecteurs ont été généralisés pour s'adapter aux niveaux de zoom.

En ce qui concerne toute l'astuce consistant à placer les tuiles sur un canevas HTML5 afin que vous puissiez accéder aux tampons, tout cela n'est pas nécessaire. QGIS vous permet d'écrire du code en Python et C++, les deux langages ont un excellent support pour gérer les tampons binaires, donc ce travail de contournement n'est vraiment pas pertinent pour cette plate-forme.

*MISE À JOUR 2** :

Il y avait une question sur la façon de créer les tuiles vectorielles généralisées en premier lieu (bébé étape 1 avant de pouvoir sérialiser les résultats en images). Peut-être que je n'ai pas assez précisé. Tilestache vous permettra de créer des « tuiles vectorielles » efficaces de vos données à chaque niveau de zoom (il a même une option qui vous permet de couper ou de ne pas couper les données lorsqu'elles passent la limite de la tuile). Cela prend soin de séparer les vecteurs en tuiles à différents niveaux de zoom. Je choisirais l'option "pas de clip" (mais elle choisira une tuile arbitraire où elle couvrira plus de surface). Ensuite, vous pouvez alimenter chaque vecteur via l'option de généralisation GEOS avec un grand nombre, en fait, vous le voulez assez grand pour que les polylignes et les polygones s'effondrent sur eux-mêmes, car s'ils le font, vous pouvez les supprimer du niveau de zoom car pour cette étape ils sont hors du sujet. Tilestache vous permet même d'écrire des fournisseurs de données pythoniques simples où vous pouvez mettre cette logique. À ce stade, vous pouvez choisir de les servir sous forme de fichiers json (comme ils le font avec certains échantillons de cartes africaines) ou de géométries sérialisées dans les png, comme ils le font dans d'autres échantillons (ou celui de Trulia) que j'ai donné ci-dessus.


Directement du développeur Dino Ravnic sur un récent message de la liste de diffusion :

Ce n'est pas un grand secret comment nous l'avons fait, donc je serais heureux de partager cela avec vous… la clé est dans deux choses :

  1. supprimer d'une tuile tous les vecteurs qui sont trop petits pour être visibles, c'est-à-dire que leur surface lorsqu'elle est calculée en pixels est inférieure à 1px. nous laissons donc tomber un tel vecteur et au lieu de cela, nous plaçons un pixel, il y a donc la propriété "pixels" dans notre tuile json

  2. les vecteurs qui seront réellement visibles sont généralisés puis écrits dans une tuile avec leurs coordonnées en pixels

Sur la partie client, nous rendons sur le canevas ces pixels statiques et vecteurs visibles. En plus des vecteurs, nous avons implémenté la gestion des événements de souris pour obtenir le survol, c'est-à-dire l'interactivité. et c'est tout.

Notre moteur de carte backend fait tout le gros du travail car nous n'utilisons aucune mise en cache préalable et toutes les tuiles sont générées à la volée. c'est très important pour nous d'avoir une carte qui peut être rafraîchie rapidement.

Il semble donc que le côté client soit la partie facile. Il est impressionnant que les données soient rendues sans aucune mise en cache.

Il mentionne également un service d'hébergement qui peut vous intéresser. Vous voudrez peut-être peser le coût d'essayer de recréer cela avec le coût d'utilisation d'un service prêt à l'emploi.


Comme je l'ai décrit sur la liste OSGeo, la clé consiste à fournir des données sous forme de tuiles JSON vectorielles qui ont des pixels pour la géométrie des sous-pixels et une géométrie généralisée pour les fonctionnalités qui seront réellement visibles à un certain niveau. Les performances sont excellentes car cette technique élimine toutes les informations vectorielles inutiles et ne laisse que les vecteurs qui auront réellement un impact visuel sur la carte. Les pixels sont là pour combler les lacunes et être placés à la place de ces vecteurs de sous-pixels. C'est tout en ce qui concerne le format de la tuile.

Du côté du backend se trouve le vrai poids lourd. Nous n'utilisons pas TileStache ou tout autre moteur de carte puisque nous avons écrit le nôtre qui peut, avec un certain nombre d'optimisations, produire de tels graphiques vectoriels en temps réel.

Tout d'abord, nous avons commencé par fournir des tuiles de carte sous forme de SWF et, dernièrement, nous avons simplement activé la sortie vers JSON afin que nous puissions utiliser HTML5 Canvas pour rendre les graphiques. Vous trouverez ci-dessous un benchmark comparant ce type de technologie vectorielle avec la technologie raster (mapnik). Pour une comparaison équitable, recherchez uniquement les résultats en mode CGI.

http://www.giscloud.com/blog/realtime-map-tile-rendering-benchmark-rasters-vs-vectors/

Nous prévoyons de fournir cette technologie en tant que service d'hébergement de tuiles de carte. L'idée est d'héberger vos données géographiques sur le cloud et, via HTML5, de les transmettre à n'importe quel client cartographique à grande vitesse, sans avoir besoin de pré-cacher les tuiles. Si vous souhaitez rejoindre cette bêta, n'hésitez pas à nous contacter ici : http://www.giscloud.com/contact/


On dirait qu'une question très similaire a été récemment posée sur le forum OSGeo Open Layers, avec les développeurs de GIS Cloud décrivant leur approche, qui est un mélange intéressant de géométries GeoJSON et de pixels statiques. Ils génèrent en fait toutes les tuiles vectorielles à la volée au lieu d'utiliser un cache pré-construit de fichiers GeoJSON.

Esri a mis en œuvre une approche similaire, à l'aide d'ArcGIS Server et de couches d'entités, qui peuvent généraliser les géométries à la volée et les envoyer sur le réseau en tant que JSON.

Pour une méthode simple que vous pouvez réellement implémenter maintenant, vous pouvez créer des tuiles vectorielles avec Tilestache (qui prend en charge PostGIS) et les utiliser dans Polymaps. Polymaps utilise SVG, mais les performances sont assez bonnes et les règles CSS pour styliser les éléments de la carte, de sorte que le rendu des fonctionnalités dépend entièrement de vous. Voici un article de blog travaillant sur quelque chose de similaire à ce que vous demandez.


J'ai joué avec OpenLayers en utilisant Canvas et j'ai obtenu des résultats raisonnables.

Comme mentionné dans les autres réponses : pour fournir et afficher des vecteurs à la volée - ils doivent être généralisés pour chaque niveau de zoom et chaque jeu de données. En outre, vous pouvez utiliser l'encodage polyligne de Google pour réduire considérablement la taille.

J'ai utilisé un mécanisme de livraison simple. Chaque géométrie était une fonction JavaScript dans une réponse HTTP JavaScript. pas aussi avancé que la livraison vectorielle basée sur des tuiles, mais simple et Open Source !

Je n'ai pas essayé Google Maps v3 avec Canvas, mais j'ai vu quelques démos du New York Times qui m'ont impressionné.


Je ne sais pas exactement quelle solution est utilisée par cette entreprise (vous pouvez peut-être leur demander directement) mais j'ai une idée.

La solution clé pour améliorer le transfert réseau et la vitesse de rendu des données vectorielles est de les généraliser en fonction du niveau de zoom : Le transfert et le rendu à un niveau de zoom élevé de milliers d'objets conçus pour un niveau de zoom beaucoup plus faible est souvent très chronophage (et aussi inutile car l'affichage final n'est généralement pas lisible - voir par exemple cette image). Pour implémenter cela, votre base de données de serveur postgis doit être multi-échelle: Pour chaque niveau de zoom, il doit y avoir une représentation de l'objet adaptée à ce niveau de zoom. Ces différentes représentations peuvent être calculées automatiquement à l'aide de techniques de généralisation. De plus, les données vectorielles envoyées par le serveur au client ne doivent pas seulement dépendre de l'étendue spatiale, mais aussi du niveau de zoom : Le serveur envoie des données adaptées en fonction du niveau de zoom. C'est l'approche défendue dans cet excellent article :-)


Il existe un article intéressant, une démo et le code source d'un logiciel développé par Stanford Visualization Group qui utilise un cube de données pour chaque tuile afin de visualiser et d'explorer un vaste ensemble de données géographiques. Il ne peut être utilisé que pour un jeu de données de points mais peut être un moyen intéressant.

http://vis.stanford.edu/papers/immens

Vizzuality avec leur plate-forme CartoDB et la bibliothèque appelée Torque expérimentent également d'une manière ou d'une autre comment dessiner un volume élevé de données.

http://cartodb.github.io/torque/
https://github.com/CartoDB/torque/tree/new_torque


Voir la vidéo: création polygone dans ArcGis (Octobre 2021).