Um dos métodos mais eficientes para encontrar a espessura mínima da parede (valor e localização) de uma área complexa de polígonos não convexos, incluindo orifícios, poderia ser usando uma camada regularmente espaçada (ou aleatória) de pontos para determinar o primeiro segmento mais próximo com contexto para cada ponto e, a seguir, o ponto de interseção entre o segmento incremental e o polígono do lado oposto; baseado em diretores cossenos.
Distâncias incrementais podem ser usadas até o primeiro segmento atingir e cruzar algum polígono lateral (a espessura mínima da parede).
Para experimentar minha abordagem, clonei seu polígono com furos e criei uma camada de pontos aleatórios dentro do polígono com 100 pontos; como pode ser observado na seguinte imagem:
O código usado do PyQGIS é o seguinte:
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
e produz uma camada de memória de distâncias incrementais (apenas para fins de visualização) e imprime uma espessura mínima da parede no formato WKT.
Depois de executar o código no Python Console do QGIS, obtive resultado da seguinte imagem:
Pode-se observar que apenas uma distância incremental alcançou o lado oposto primeiro na área esperada.
O formato WKT impresso (para espessura mínima da parede) é usado com o plug-in QuickWKT do QGIS para visualizar esse segmento na seguinte imagem:
A leve inclinação foi produzida porque "o segmento mais próximo ao contexto" foi associado a um vértice; polígono lateral. No entanto, isso pode ser evitado com uma exceção de código ou mais pontos.