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:
import math
def azimuth(point1, point2):
return point1.azimuth(point2) #in degrees
def cosdir_azim(azim):
azim = math.radians(azim)
cosa = math.sin(azim)
cosb = math.cos(azim)
return cosa,cosb
registry = QgsMapLayerRegistry.instance()
polygon = registry.mapLayersByName('polygon_with_holes')
point_layer = registry.mapLayersByName('Random_points')
points = [ feat.geometry().asPoint() for feat in point_layer[0].getFeatures() ]
feat_polygon = polygon[0].getFeatures().next()
#producing rings polygons
rings_polygon = feat_polygon.geometry().asPolygon()
segments = []
epsg = point_layer[0].crs().authid()
uri = "LineString?crs=" + epsg + "&field=id:integer""&index=yes"
mem_layer = QgsVectorLayer(uri,
'increasing_segments',
'memory')
prov = mem_layer.dataProvider()
length = 10
pt2 = 0
k = 0
while pt2 == 0:
for i, point in enumerate(points):
#determining closest distance to vertex or side polygon
dist1 = feat_polygon.geometry().closestSegmentWithContext(point)[0]
#determining point with closest distance to vertex or side polygon
pt = feat_polygon.geometry().closestSegmentWithContext(point)[1]
cosa, cosb = cosdir_azim(azimuth(pt, point))
#extending segment in opposite direction based in director cosine and length
op_pt = QgsPoint(point.x() + (length*cosa), point.y() + (length*cosb))
segments.append([pt,op_pt])
geom = QgsGeometry.fromPolyline([point,op_pt])
for ring in rings_polygon:
geom_ring = QgsGeometry.fromPolyline(ring)
if geom.intersects(geom_ring):
pt3 = geom.intersection(geom_ring)
pt2 = pt3.distance(QgsGeometry.fromPoint(point))
ms = [pt3.asPoint(), pt]
length += 100
k += 1
new_segments = segments[len(segments) -1 - len(segments)/k: len(segments) - 1]
feats = [ QgsFeature() for i in range(len(new_segments)) ]
for i,feat in enumerate(feats):
feat.setAttributes([i])
geom = QgsGeometry.fromPolyline(new_segments[i])
feat.setGeometry(geom)
prov.addFeatures(feats)
QgsMapLayerRegistry.instance().addMapLayer(mem_layer)
minimum_segment = QgsGeometry().fromPolyline(ms).exportToWkt()
print minimum_segment, k
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.