Quelle est la façon la plus efficace de trouver l'épaisseur de paroi minimale (valeur et emplacement) d'une zone de polygone complexe et non convexe, y compris des trous? Voir l'exemple d'un polygone en bleu, avec l'épaisseur de paroi minimale en rouge, bien que dans ce cas l'emplacement soit ambigu, si les deux lignes adjacentes sont parallèles.
Jusqu'à présent, nous avons essayé:
- Subdiviser des lignes de polygone et trouver des lignes point-point minimales à l'intérieur du polygone (force brute, pas efficace pour les polygones complexes avec> 10'000 points)
- Triangulation de Delaunay et recherche d'arêtes minimales à l'intérieur du polygone. Pas assez précis, réalisable uniquement s'il est combiné avec la subdivision des lignes polygonales en premier. Voici un exemple (Nr 3), où la triangulation de Delaunay ne trouverait pas d'arêtes simplex en rouge mais manquerait l'épaisseur de paroi minimale dans la boîte verte:
- Augmentation itérative du tampon d'érosion pour trouver l'encart minimal, où le polygone d'érosion se divise en plusieurs parties = la moitié de l'épaisseur minimale de la paroi. Le problème est de trouver l'emplacement de l'épaisseur de paroi minimale avec cette approche par la suite. De plus, l'érosion ne se divise pas toujours en plusieurs parties et manque des "impasses". Voici un exemple (Nr 2) qui s'érode en une ligne et donne la mauvaise épaisseur de paroi minimale:
- Trouver d'abord l'axe médian, puis rechercher le cercle minimum sur l'axe médian qui recouvre mais ne chevauche pas la zone du polygone. Edit: Problématique sont les nombreux «mauvais candidats» sur l'axe médian: par exemple. (Nr 1) le cercle A serait faux, le cercle B indiquerait l'épaisseur de paroi minimale correcte:
Réponses:
L'une des méthodes les plus efficaces pour trouver l'épaisseur de paroi minimale (valeur et emplacement) d'une zone de polygone complexe et non convexe, y compris des trous, pourrait être en utilisant une couche régulièrement espacée (ou aléatoire) de points pour déterminer, d'abord, le segment le plus proche avec le contexte pour chaque point et, ensuite, le point d'intersection entre le segment incrémentiel et le polygone latéral opposé; basé dans les directeurs cosinus.
Des distances incrémentielles peuvent être utilisées jusqu'à ce que le premier segment atteigne et recoupe un polygone latéral (l'épaisseur de paroi minimale).
Pour essayer mon approche, j'ai cloné votre polygone avec des trous et créé une couche de points aléatoires à l'intérieur du polygone avec 100 points; comme on peut le voir sur l'image suivante:
Le code utilisé par PyQGIS se présente comme suit:
et il produit une couche mémoire de distances incrémentielles (uniquement à des fins de visualisation) et imprime une épaisseur de paroi minimale au format WKT.
Après avoir exécuté le code sur la console Python de QGIS, j'ai obtenu le résultat de l'image suivante:
On peut observer qu'une seule distance incrémentielle a atteint le côté opposé en premier dans la zone attendue.
Le format WKT imprimé (pour une épaisseur de paroi minimale) est utilisé avec le plugin QuickWKT de QGIS pour visualiser ce segment à l'image suivante:
La légère inclinaison a été produite parce que "le segment le plus proche avec le contexte" était joint à un sommet; au lieu du polygone latéral. Cependant, il peut être évité avec une exception de code ou plusieurs points.
la source
Deux autres idées à jeter dans le pot:
Pixellisez votre polygone et utilisez une transformation de distance (renvoie l'image de la distance la plus courte entre chaque pixel différent de zéro et un pixel nul). Squelettez votre image tramée, puis prenez les valeurs de l'image transformée à distance le long du squelette. De cet ensemble, vous aurez quelques minimums qui devraient correspondre à votre largeur la plus étroite. Cet ensemble peut être utilisé comme points de recherche initiaux pour ensuite implémenter votre approche par force brute. Je dois noter que le squelette coupera les coins des objets, et à ces endroits, la transformation de distance approchera de zéro (à mesure que vous vous rapprocherez de la limite de l'objet). Cela peut être problématique, mais représente un problème avec votre problème - pourquoi t la plus petite largeur doit-elle être dans un coin (et être essentiellement nulle)? Vous pouvez résoudre ce problème en définissant un seuil sur la distance la plus courte autour du périmètre entre les deux points (s'ils se trouvent sur le même objet). Vous pouvez utiliser une transformation de distance géodésique sur l'ensemble des pixels de périmètre pour trouver rapidement cette valeur.
Cette méthode vous oblige à prendre une décision sur la résolution du polygone tramé, ce qui introduit une certaine dépendance à l'échelle. Et si vous choisissez une résolution trop élevée, la transformation de distance peut prendre beaucoup de temps. Mais en général, ils sont assez rapides. Cette méthode peut ne pas vous donner la précision souhaitée, mais elle peut au moins vous donner un ensemble beaucoup plus restreint d'emplacements à vérifier.
Votre méthode de force brute n'est pas un mauvais point de départ. J'ai eu un problème similaire où je devais trouver toutes les intersections d'une (longue) ligne avec lui-même, et j'ai été en mesure d'accélérer considérablement le temps de recherche en utilisant un algorithme de recherche d'arbre kd (j'ai utilisé la recherche de plage dans Matlab à l'époque) pour trouver pointe d'abord dans un quartier. De cette façon, vous ne forcez que brutalement un petit sous-ensemble du nombre total de points.
la source
L'approche de l'axe médian est correcte, il vous suffit d'un critère pour ignorer les mauvais cercles: chaque cercle de l'axe médian touche la surface en deux points (ou plus). Imaginez des vecteurs du centre du cercle à ces points de la surface et observez que l'angle entre est de 180 ° pour le bon cercle B et de seulement 90 ° pour le mauvais cercle A.
la source
Un algorithme de dessin polygonal générique fonctionne en triant les segments de ligne de haut en bas et en les parcourant pour tracer des lignes orthogonales de pixels. Cette méthode de décomposition des polygones (sans courbures) étant très rapide, elle peut être utilisée comme base. Au lieu d'aller uniquement de haut en bas, vous pouvez aller à 0, 30, 60 et 90 degrés, et trouver votre section orthogonale la plus courte (= épaisseur de paroi minimale!), Il vous suffit de la calculer une fois par point et non pour tout type de «résolution en pixels».
Voir algorithme de remplissage de polygone-ligne-infographie-infographie
la source