Voici une carte de contour pour laquelle tous les polygones de niveaux sont disponibles.
Laissez-vous demander comment lisser les polygones en conservant tous les sommets à leur emplacement exact?
En effet, le contour étant créé au-dessus d’une donnée de grille, vous pouvez alors suggérer de lisser les données de la grille afin que le contour résultant soit plus lisse. Notez que cela ne fonctionne pas comme je le souhaite car la fonction de lissage, telle que le filtre gaussien, supprimera les petits paquets de données et modifiera la plage de la troisième variable, par exemple la hauteur non autorisée dans mon application.
En fait, je cherche un morceau de code (de préférence en Python ) capable de lisser des polygones 2D (tout type: convexe, concave, s'entrecroisant, etc.) raisonnablement indolore (oublier les pages de codes) et précis.
Pour votre information, il existe une fonction dans ArcGIS qui le fait parfaitement, mais l’utilisation d’applications commerciales tierces n’est pas mon choix pour cette question.
1)
Scipy.interpolate:
Comme vous le voyez, les splines obtenues (en rouge) ne sont pas satisfaisantes!
2)
Voici le résultat en utilisant le code donné ici . Cela ne fonctionne pas bien!
3)
Pour moi, la meilleure solution devrait être quelque chose comme la figure suivante dans laquelle un carré est lissé progressivement en ne modifiant qu'une seule valeur. J'espère un concept similaire pour lisser toute forme de polygone.
Satisfaire à la condition que spline passe les points:
4)
Voici mon implémentation de "l'idée de whuber" ligne par ligne en Python sur ses données. Il y a peut-être des bugs car les résultats ne sont pas bons.
K = 2 est un désastre et donc pour k> = 4.
5)
J'ai supprimé un point de l'emplacement problématique et la spline résultante est maintenant identique à celle de whuber. Mais il reste une question que pourquoi la méthode ne fonctionne pas pour tous les cas?
6)
Un bon lissage des données de whuber peut être le suivant (dessiné par un logiciel de graphisme vectoriel) dans lequel un point supplémentaire a été ajouté sans à-coups (comparer avec update
4):
sept)
Voir le résultat de la version Python du code de whuber pour certaines formes emblématiques:
Notez que la méthode semble ne pas fonctionner pour les polylignes. Pour la polyligne d’angle (contour), le vert est ce que je veux, mais j’ai eu le rouge. Ceci doit être traité car les cartes de contour sont toujours des polylignes, bien que les polylignes fermées puissent être traitées comme des polygones, comme dans mes exemples. En outre, le problème apparu dans la mise à jour 4 n’a pas encore été résolu.
8) [mon dernier]
Voici la solution finale (pas parfaite!):
N'oubliez pas que vous devrez faire quelque chose à propos de la zone indiquée par les étoiles. Il y a peut-être un bogue dans mon code ou la méthode proposée nécessite un développement supplémentaire pour prendre en compte toutes les situations et fournir les résultats souhaités.
Réponses:
La plupart des méthodes pour spline des suites de nombres spline des polygones. L'astuce consiste à faire en sorte que les splines se "referment" en douceur aux extrémités. Pour ce faire, "envelopper" les sommets autour des extrémités. Ensuite, séparez les coordonnées x et y séparément.
Voici un exemple de travail dans
R
. Il utilise laspline
procédure cubique par défaut disponible dans le package de statistiques de base. Pour plus de contrôle, remplacer presque toute procédure que vous préférez: assurez - vous qu'il splines par les chiffres (qui est, interpole eux) plutôt que de simplement les utiliser comme des « points de contrôle ».Pour illustrer son utilisation, créons un petit polygone (mais compliqué).
Spline le en utilisant le code précédent. Pour rendre la spline plus lisse, augmentez le nombre de sommets de 100; pour le rendre moins lisse, diminuez le nombre de sommets.
Pour voir les résultats, on trace (a) le polygone d'origine en pointillé rouge, montrant l'écart entre le premier et le dernier sommet (c'est-à-dire ne ferme pas sa polyligne limite); et (b) la spline en gris, montrant une fois de plus son écart. (L'écart étant si petit, ses extrémités sont mises en évidence par des points bleus.)
la source
Je sais que ceci est un ancien message, mais il est apparu sur Google pour quelque chose que je cherchais et j'ai donc pensé poster ma solution.
Je ne vois pas cela comme un exercice d’ajustement de courbe en 2D, mais plutôt en 3D. En considérant les données en 3D, nous pouvons nous assurer que les courbes ne se croisent jamais et que nous pouvons utiliser les informations provenant d'autres contours pour améliorer notre estimation pour le graphique actuel.
L'extrait iPython suivant utilise une interpolation cubique fournie par SciPy. Notez que les valeurs z que j'ai tracées ne sont pas importantes, tant que tous les contours sont équidistants en hauteur.
Les résultats obtenus ne sont pas optimaux, mais avec si peu de points de contrôle, ils restent parfaitement valables. Notez comment la ligne ajustée verte est tirée pour suivre le contour bleu plus large.
la source
J'ai écrit presque exactement le package que vous recherchez ... mais c'était en Perl et l'était il y a plus de dix ans: GD :: Polyline . Il utilisait des courbes de Bézier cubiques 2D et "lisserait" un polygone ou une "polyligne" arbitraire (mon nom s’appelait alors à ce que l’on appelle communément un "LineString").
L'algorithme comportait deux étapes: compte tenu des points du polygone, ajoutez deux points de contrôle de Bézier entre chaque point; appelez ensuite un algorithme simple pour faire une approximation par morceaux de la spline.
La deuxième partie est facile. la première partie était un peu d'art. Voici l'aperçu était: envisager un « segment de contrôle » un Vertex N:
vN
. Le segment de contrôle était de trois points de co-linéaire:[cNa, vN, cNb]
. Le point central était le sommet. La pente de ce segment de contrôle était égale à la pente du sommet N-1 au sommet N + 1. La longueur de la partie gauche de ce segment était égale à 1/3 de la longueur allant du sommet N-1 au sommet N, et la longueur de la partie droite de ce segment était égale à 1/3 de la longueur du sommet N au sommet N + 1.Si la courbe d' origine était de quatre sommets:
[v1, v2, v3, v4]
alors chaque sommet maintenant obtenir un segment de contrôle de la forme:[c2a, v2, c2b]
. Enchaînez-les comme ceci:[v1, c1b, c2a, v2, c2b, c3a, v3, c3b, c4a, v4]
et broyez-les quatre à la fois comme les quatre points de Bézier:,[v1, c1b, c2a, v2]
puis[v2, c2b, c3a, v3]
, et ainsi de suite. Parce que[c2a, v2, c2b]
co-linéaires, la courbe résultante sera lisse à chaque sommet.Donc, cela répond également à votre exigence de paramétrer le "serrage" de la courbe: utilisez une valeur inférieure à 1/3 pour une courbe "plus étroite", une valeur plus grande pour un ajustement "plus bouclé". Dans les deux cas, la courbe résultante passe toujours par les points donnés d'origine.
Cela a abouti à une courbe lisse qui "circonscrit" le polygone d'origine. J'avais aussi un moyen "d'inscrire" une courbe lisse ... mais je ne le vois pas dans le code CPAN.
Quoi qu'il en soit, je n'ai pas encore de version disponible en Python ni de chiffres. MAIS ... si / quand je porte ceci en Python, je serai sûr de poster ici.
la source