Một trong những phương pháp hiệu quả nhất để tìm độ dày thành tối thiểu (giá trị và vị trí) của một khu vực đa giác không lồi phức tạp bao gồm các lỗ, có thể bằng cách sử dụng một lớp cách đều đặn (hoặc ngẫu nhiên) các điểm để xác định, đầu tiên, phân đoạn gần nhất với bối cảnh cho từng điểm và, tiếp theo, điểm giao nhau giữa phân đoạn tăng dần và đa giác phía đối diện; có trụ sở tại cosines giám đốc.
Khoảng cách tăng dần có thể được sử dụng cho đến khi đoạn đầu tiên chạm tới và giao với một số đa giác bên (độ dày thành tối thiểu).
Để thử cách tiếp cận của tôi, tôi đã nhân bản đa giác của bạn bằng các lỗ và tạo một lớp điểm ngẫu nhiên bên trong đa giác với 100 điểm; như nó có thể được quan sát ở hình ảnh sau:
Mã được sử dụng PyQGIS trông như sau:
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
và nó tạo ra một lớp bộ nhớ khoảng cách gia tăng (chỉ dành cho mục đích trực quan hóa) và in độ dày thành tối thiểu ở định dạng WKT.
Sau khi chạy mã tại Bảng điều khiển Python của QGIS, tôi nhận được kết quả như sau:
Có thể thấy rằng chỉ có một khoảng cách gia tăng đạt được phía đối diện trước tiên trong khu vực dự kiến.
Định dạng WKT được in (cho độ dày thành tối thiểu) được sử dụng với plugin QuickWKT của QGIS để hiển thị phân đoạn đó ở hình ảnh sau:
Độ nghiêng nhẹ được tạo ra do "phân đoạn gần nhất với bối cảnh" được nối với một đỉnh; thay vào đó là đa giác. Tuy nhiên, nó có thể tránh được với một ngoại lệ mã hoặc nhiều điểm hơn.