Comment dégrader ou lisser intelligemment les données SIG (simplifier les polygones)?
J'ai des cartes détaillées du comté des États-Unis, à partir des ensembles de données TIGER LINE. Comment puis-je échantillonner, lisser ou dégrader les données pour obtenir des formes plus droites, plus carrées, moins "bruyantes" pour représenter les caractéristiques géographiques-dans ce cas, juste les limites du comté et les lignes d'état, mais peut-être aussi dans le cas général?
L'échantillonnage pourrait se produire au moment du rendu si cela peut être fait efficacement, ou un ensemble de données parallèle pourrait être généré et stocké. J'utilise PostGIS , et les lignes sont multi-polylignes générées par shp2pgsql
- mais toute solution où vous prenez une ligne ondulée et la réduisez à une ligne plus lisse de la même signification pour un interprète humain serait très utile.
6 réponses
Le problème avec le simple fait de jeter des points est que vous pouvez rapidement déformer la forme du polygone d'origine. Une meilleure approche consiste à venir de l'autre côté; commencez par une approximation de base du polygone, puis affinez-le vers le haut vers votre forme complexe.
Un excellent exemple de cette approche est l'algorithme Douglas-Puecker . Vous commencez avec deux sommets tirés du polygone complet. Ajoutez un troisième sommet en sélectionnant celui qui se trouve le plus loin un bord dessiné entre les deux premiers sommets. Continuez à ajouter des points jusqu'à ce que vous ayez quelque chose qui ressemble suffisamment à votre polygone d'origine.
Douglas-Peucker est certainement la bonne approche. Il existe des moyens simples d'accéder aux implémentations de celui-ci dans PostGIS et QGIS que je pensais ajouter ici pour ceux qui rencontrent ce post avec une question similaire. Le but est de commencer par quelque chose comme ceci:
Et se retrouver avec quelque chose comme ceci:
Dans PostGIS Douglas-Peucker est implémenté comme simplify
, la syntaxe, détaillée ici à bostongis.org , est une variante de:
SELECT transform(simplify(transform(the_geom, 2249), 500),4326) from the_geo_table
Cela a très bien fonctionné même sur l'ensemble complet des données nationales, avec quelques erreurs qui semblent dues à de mauvaises données sous-jacentes. Il s'avère également que dans QGIS, l'élément de menu Tools > Geometry Tools > Simplify Geometries
exportera un fichier de formes simplifié de n'importe quelle géométrie et l'ajoutera en tant que calque à votre projet actuel.
C'est un joli outil fondamental et j'ai posé la question à un niveau trop bas, mais c'était agréable d'apprendre les mathématiques sous-jacentes, il y a une bonne explication ici: http://www.mappinghacks.com/code/PolyLineReduction/, avec un exemple de code qui s'avère pas trop nécessaire!
Au lieu de QGIS, je suggère d'utiliser ogr2ogr car il ne supprime pas les polygones!
ogr2ogr output.shp input.shp -simplify 0.0001
Voici un algorithme de lissage itératif simple:
Pour chaque trois points séquentiels sur n'importe quel chemin, si le point central n'a pas d'intersections et se trouve dans un petit angle de seuil du chemin direct entre les deux points extérieurs, retirez-le.
Répéter jusqu'à satisfaction.
Vous pouvez également essayer l'algorithme de Visvalingam, qui supprime itérativement la partie la moins perceptible d'une ligne. Voici une excellente explication de cet algorithme:
Vous pouvez également utiliser Simplifier.js {[2] } qui utilise une combinaison deDouglas-Peucker et des algorithmes de Distance radiale. Il existe également des liens vers de nombreux ports vers d'autres langues listés sur le projet github