Sadece bir geometri üreticisine ve özel bir işleve benzeyen bir yaklaşım öneriyorum.
Başlamadan önce, istenen sonucu yeniden üretmek için yapılacak minimum şeylerin açıklamasına dikkat çekeceğimin altını çizmek istiyorum: bu, bazı diğer küçük parametrelerin (boyutlar, genişlikler vb.) Sizin tarafınızdan kolayca ayarlanması gerektiği anlamına gelir. ihtiyaçlarınızı daha iyi karşılamak için.
Bu nedenle, bu çözüm hem Coğrafi hem de Öngörülen Referans Sistemleri için çalışır: aşağıda, yansıtılan bir CRS (yani ölçüm birimleri metredir) kullandığımı varsaydım, ancak bunları CRS'nize göre değiştirebilirsiniz.
bağlam
Kabloları temsil eden bu linestring vektör katmanından başlayalım (etiketler çakışan (çakışan) tellerin sayısını temsil eder):
Çözüm
İlk olarak, oluşturucuyu Layer Properties | Style
seçin ve ardından seçin Single symbol
.
Gönderen Symbol selector
diyalog, bir seçim Geometry generator
sembol katman türü olarak ve Linestring / MultiLinestring
geometri türü olarak. Ardından, Function Editor
sekmeyi tıklayın:
Ardından tıklayın New file
ve draw_wires
yeni işlevin adı olarak yazın:
Yeni bir işlevin oluşturulduğunu ve iletişim kutusunun sol tarafında listelendiğini göreceksiniz. Şimdi, işlevin adını tıklayın ve varsayılanı @qgsfunction
aşağıdaki kodla değiştirin (buraya eklenen tüm kitaplıkları eklemeyi unutmayın):
from qgis.core import *
from qgis.gui import *
from math import sin, cos, radians
@qgsfunction(args='auto', group='Custom')
def draw_wires(angle, percentage, curr_feat, layer_name, feature, parent):
def wires(polyline, new_angle, percentage):
for x in range(0, len(polyline)-1):
vertices = []
first_point = polyline[x]
second_point = polyline[x +1]
seg = QgsGeometry.fromPolyline([first_point, second_point])
len_feat = seg.length()
frac_len = percentage * len_feat
limb = frac_len/cos(radians(new_angle))
tmp_azim = first_point.azimuth(second_point)
angle_1 = radians(90 - (tmp_azim+new_angle))
dist_x, dist_y = (limb * cos(angle_1), limb * sin(angle_1))
point_1 = QgsPoint(first_point[0] + dist_x, first_point[1] + dist_y)
angle_2 = radians(90 - (tmp_azim-new_angle))
dist_x, dist_y = (limb * cos(angle_2), limb * sin(angle_2))
point_2 = QgsPoint(second_point[0] - dist_x, second_point[1] - dist_y)
tmp_azim = second_point.azimuth(first_point)
angle_3 = radians(90 - (tmp_azim+new_angle))
dist_x, dist_y = (limb * cos(angle_3), limb * sin(angle_3))
point_3 = QgsPoint(second_point[0] + dist_x, second_point[1] + dist_y)
angle_4 = radians(90 - (tmp_azim-new_angle))
dist_x, dist_y = (limb * cos(angle_4), limb * sin(angle_4))
point_4 = QgsPoint(first_point[0] - dist_x, first_point[1] - dist_y)
vertices.extend([first_point, point_1, point_2, second_point, point_3, point_4, first_point])
tempGeom = QgsGeometry.fromPolyline(vertices)
num.append(tempGeom)
return num
layer = QgsMapLayerRegistry.instance().mapLayersByName(layer_name)[0]
all_feats = {}
index = QgsSpatialIndex()
for ft in layer.getFeatures():
index.insertFeature(ft)
all_feats[ft.id()] = ft
first = True
tmp_geom = curr_feat.geometry()
polyline = tmp_geom.asPolyline()
idsList = index.intersects(tmp_geom.boundingBox())
occurrences = 0
for id in idsList:
test_feat = all_feats[id]
test_geom = test_feat.geometry()
if tmp_geom.equals(test_geom):
occurrences += 1
if occurrences & 0x1:
num = [tmp_geom]
else:
num = []
rapp = occurrences/2
i=2
new_angle = angle
while i <= occurrences:
draw=wires(polyline, new_angle, percentage)
i += 2
new_angle -= new_angle/rapp
first = True
for h in num:
if first:
geom = QgsGeometry(h)
first = False
else:
geom = geom.combine(h)
return geom
Bunu yaptıktan sonra, Load
düğmeye tıklayın , işlevi iletişim kutusunun Custom
Menüsünden görebileceksiniz Expression
.
Şimdi bu ifadeyi yazın (aşağıdaki resme referans olarak bakın):
draw_wires(40, 0.3, $currentfeature, @layer_name)
Sadece hayali bir şekilde söyleyen bir işlevi çalıştırdınız:
"Geçerli katman ( @layer_name ) ve geçerli özellik ( $ currentfeature ) için, 40 derecelik bir başlangıç maksimum açıklığı kullanarak ve geçerli segmentin uzunluğunun 0,3 katı mesafede bir yön değişikliği ile kabloları birlikte görüntüleyin."
Değiştirmeniz gereken tek şey, ilk iki parametrenin değerini istediğiniz gibi, ancak açıkça makul bir şekilde (diğer işlev parametrelerini sağlandığı gibi bırakın).
Son olarak, Apply
değişiklikleri uygulamak için düğmeye tıklayın.
Bunun gibi bir şey göreceksiniz:
beklenildiği gibi.
DÜZENLE
OP tarafından bir yorumda dile getirilen belirli bir talebe göre:
"Bu kalıbı, her köşe noktası yerine her bir çoklu çizginin başlangıcı ve bitişi arasında oluşturmak mümkün müdür?"
Kodu biraz düzenledim. Aşağıdaki işlev beklenen sonucu döndürmelidir:
from qgis.core import *
from qgis.gui import *
from math import sin, cos, radians
@qgsfunction(args='auto', group='Custom')
def draw_wires(angle, percentage, curr_feat, layer_name, feature, parent):
def wires(polyline, new_angle, percentage):
vertices = []
len_feat = polyline.length()
frac_len = percentage * len_feat
limb = frac_len/cos(radians(new_angle))
tmp_azim = first_point.azimuth(second_point)
angle_1 = radians(90 - (tmp_azim+new_angle))
dist_x, dist_y = (limb * cos(angle_1), limb * sin(angle_1))
point_1 = QgsPoint(first_point[0] + dist_x, first_point[1] + dist_y)
angle_2 = radians(90 - (tmp_azim-new_angle))
dist_x, dist_y = (limb * cos(angle_2), limb * sin(angle_2))
point_2 = QgsPoint(second_point[0] - dist_x, second_point[1] - dist_y)
tmp_azim = second_point.azimuth(first_point)
angle_3 = radians(90 - (tmp_azim+new_angle))
dist_x, dist_y = (limb * cos(angle_3), limb * sin(angle_3))
point_3 = QgsPoint(second_point[0] + dist_x, second_point[1] + dist_y)
angle_4 = radians(90 - (tmp_azim-new_angle))
dist_x, dist_y = (limb * cos(angle_4), limb * sin(angle_4))
point_4 = QgsPoint(first_point[0] - dist_x, first_point[1] - dist_y)
vertices.extend([first_point, point_1, point_2, second_point, point_3, point_4, first_point])
tempGeom = QgsGeometry.fromPolyline(vertices)
num.append(tempGeom)
layer = QgsMapLayerRegistry.instance().mapLayersByName(layer_name)[0]
all_feats = {}
index = QgsSpatialIndex()
for ft in layer.getFeatures():
index.insertFeature(ft)
all_feats[ft.id()] = ft
first = True
tmp_geom = curr_feat.geometry()
coords = tmp_geom.asMultiPolyline()
if coords:
new_coords = [QgsPoint(x, y) for x, y in z for z in coords]
else:
coords = tmp_geom.asPolyline()
new_coords = [QgsPoint(x, y) for x, y in coords]
first_point = new_coords[0]
second_point = new_coords[-1]
polyline=QgsGeometry.fromPolyline([first_point, second_point])
idsList = index.intersects(tmp_geom.boundingBox())
occurrences = 0
for id in idsList:
test_feat = all_feats[id]
test_geom = test_feat.geometry()
if tmp_geom.equals(test_geom):
occurrences += 1
if occurrences & 0x1:
num = [polyline]
else:
num = []
rapp = occurrences/2
i=2
new_angle = angle
while i <= occurrences:
draw=wires(polyline, new_angle, percentage)
i += 2
new_angle -= new_angle/rapp
first = True
for h in num:
if first:
geom = QgsGeometry(h)
first = False
else:
geom = geom.combine(h)
return geom