QGIS'de dalgalı, kıvrımlı çizgiler çizmek?


21

Kaba çizgi çizmek için bir QGIS işlevi veya eklentisi var mı?

Spline Tool'u bazı dalgaları elle çizmek için kullandım, ancak zaman alıyor. Mümkünse, şöyle bir şey çizmek istiyorum:

görüntü tanımını buraya girin

Inkscape Function Plotter ( sin(x)eğri).


Gerçekten ilginç bir soru! Çizgileri anında çizmek için bir araç mı düşünüyorsunuz (örneğin, fareyi kullanarak basit bir çizgi özelliği çizdiğinizde olduğu gibi) veya belki de bu sonucu girdi olarak koordinatlardan (sonuç olarak noktalardan, çizgilerden veya çokgenlerden) başlayarak elde etmenin bir yolunu mu düşünüyorsunuz?
mgri

1
@mgri Yorumunuz için teşekkür ederiz. Bu çizgiyi bazı belirsizliklerin (dalgalı bir kıyı şeridi gibi) bir sınırı işaretlemek için kullanmasını bekliyorum, bu nedenle temel fikir bir polineri (önceden tanımlanmış koordinatlar aracılığıyla) kıpırdatmaya dönüştürmekti. Ancak bu tip çizgiyi anında çizme fikri de kulağa çekici geliyor.
Kazuhito

Lütfen, çözümümün yardımcı olup olmadığına bakın. Yaygın olarak test etmedim, bu yüzden lütfen bir şeyler ters giderse bana bildirin (şu anda yapamam, ancak cevabımı daha fazla bilgi ile düzenleyeceğim).
mgri

Yanıtlar:


18

PyQGIS kullanarak bir çözüm öneriyorum. Hem Linestring hem de MultiLineString katmanları için çalışmalıdır.

Bu çözüm yarım daire halkaların oluşturulmasına dayanmaktadır, bu nedenle çap için bir değer belirlemeniz gerekir (örn step. Aşağıdaki koddaki değişken). Seçtiğiniz adım, kullanılan gerçek adım olmayacaktır, çünkü satır uzunluğuna göre ayarlanır (ancak başlangıçta ayarlanan değere gerçekten benzerdir). stepDeğişken için en iyi değeri bulmadan önce bazı denemeler yapmanız gerekir .

Kod ayrıca crv_angle, halkaların eğriliğini azaltmaya veya arttırmaya yardımcı olan ikinci bir (isteğe bağlı) parametre gerektirir ( bunun için birkaç test yaptım, bu nedenle gerçek dairesel oluşacağından 45 dereceyi varsayılan açı olarak bırakmanızı öneririm) halkalar).

Bu kodu yalnızca Python Konsolundan çalıştırmanız gerekir:

from math import sin, cos, radians

step = 3 # choose the proper value (e.g. meters or degrees) with reference to the CRS used
crv_angle = 45 # degrees

def segment(polyline):
    for x in range(0, len(polyline) - 1):
        first_point = polyline[x]
        second_point = polyline[x +1]
        seg = QgsGeometry.fromPolyline([first_point, second_point])
        tmp_azim = first_point.azimuth(second_point)
        len_feat = seg.length()
        parts = int(len_feat/step)
        real_step = len_feat/parts # this is the real step applied

        points = []
        current = 0
        up = True

        while current < len_feat:
            if up:
                round_angle = radians(90 - (tmp_azim - crv_angle))
                up = False
            else:
                round_angle = radians(90 - (tmp_azim + crv_angle))
                up = True
            first = seg.interpolate(current)
            coord_x, coord_y = (first.asPoint().x(), first.asPoint().y())
            p1=QgsPointV2(coord_x, coord_y)
            dist_x, dist_y = ((real_step*sin(rad_crv_angle))* cos(round_angle), (real_step*sin(rad_crv_angle)) * sin(round_angle))
            p2 = QgsPointV2(coord_x + dist_x, coord_y + dist_y)
            points.extend([p1, p2])
            current += real_step

        second = seg.interpolate(current + real_step)
        p3=QgsPointV2(second.asPoint().x(), second.asPoint().y())
        points.append(p3)

        circularRing = QgsCircularStringV2()
        circularRing.setPoints(points) # set points for circular rings
        fet = QgsFeature()
        fet.setGeometry(QgsGeometry(circularRing))
        prov.addFeatures([fet])

layer = iface.activeLayer() # load the input layer as you want
crs = layer.crs().toWkt()
rad_crv_angle = radians(crv_angle)

# Create the output layer
outLayer = QgsVectorLayer('Linestring?crs='+ crs, 'wiggly_line' , 'memory')
prov = outLayer.dataProvider()
fields = layer.pendingFields()
prov.addAttributes(fields)
outLayer.updateFields()

for feat in layer.getFeatures():
    geom = feat.geometry()
    polyline = geom.asPolyline()
    segment(polyline)

# Add the layer to the Layers panel
QgsMapLayerRegistry.instance().addMapLayer(outLayer)

ve beklenen sonuç ile yeni bir satır bellek katmanı yaratacaktır:

görüntü tanımını buraya girin


Vaov! Bununla oynamayı bırakamıyorum, çok güzel. Bunun üzerine çıkışın kendisi tampon gibi başka işlemler için de kullanılabilir. Teşekkürler @mgri. Son bir şey, bazen köşelerin başında veya yakınında küçük daireler olduğunu görüyorum. Bu önlenebilir mi? Onları, bu dairenin merkez düğümünü Düğüm Aracı ile silerek kaldırabilirim (bu yüzden büyük bir sorun değil).
Kazuhito

1
@Kazuhito lütfen, düzenlenmiş koduma bakın. Ayrıklaştırma konusunda yanlış bir şey olduğu anlaşılıyor ve umarım şimdiye kadar gider. Birkaç test yaptım ve iyi çalışıyor gibi görünüyor (kod da daha okunaklı).
mgri

1
Çok teşekkürler mgri. Çok küçük çemberler var, bunun için üzgünüm, bunların nasıl göründüğünü net bir şekilde açıklayamıyorum. Çoğu köşe artık “dairesiz” durumda. Fark ettiğim tek fark, böyle bir düğümün (daireli) Düğüm Aracının Vertex Editör Tablosunda daha küçük bir "r-değeri" gösterdiği idi. Bu kolayca yönetilebilir ve beklediğimden çok daha iyi. Tekrar teşekkürler. Cevabınızı çözüm olarak kabul edeyim.
Kazuhito,

1
Teşekkürler, @ Kazuhito. Mükemmel bir çözüm üretmediğim için üzgünüm. Ancak, bundan hoşlanacağınızı umuyorum (aksi takdirde bana örnek bir şekil dosyası da gönderebilirsiniz ve sorunu gidermeye çalışacağım). Daha etkili bir yol bulursam, gönderirim!
mgri

1
Çok teşekkürler Çevrelerin görünümünde belirgin bir desen bulursam sizi tekrarlanabilir örnek ile güncelleyeceğim. Bu çok zevkli (ve çıktısı güzel)!
Kazuhito

20

Kısa cevap: Özel bir SVG kullanarak elde edebilirsiniz. Biri için bu yazının altına bakın.

Uzun cevap:

Bunu temsil etmenin çizgi geometrisini değiştirmekten daha iyi olduğuna inanıyorum. Bir kenarı hareket ettirmek veya geometri üzerinde başka bir işlem yapmak istiyorsanız, kıpırdatmanın sadece düz bir çizginin temsili yerine geometrinin bir parçası olup olmadığını idare etmek kabus olurdu.

Stil işaretleyici çizgisiyle oynayabilirsiniz. İhtiyacınız olan şeylere kolayca yaklaşmanın bir yolu var ve biraz daha fazla çaba ile tam olarak onu elde etmeniz mümkün. görüntü tanımını buraya girin

Bunu elde etmek için çizgiyi iki Marker çizgisi ile stillendirirsiniz. Her Marker çizgisi, yarım daireli bir Basit Marker'den yapılmıştır. Birincisi 180 derece döndürülür. Her ikisi de saydam olarak ayarlanır.

İşaretçi satırında, bir tanesine ofset yapılmasını söylersiniz, böylece iki sembol birbirinin önüne değil, yan yana çizilir. En kapalı = 1/2 * aralık boyutu kullanırsanız, çıktı sinüzoidal bir eğri olur. Aralık, ofset ve sembol boyutlarıyla oynamanızı öneririm.

Bu yaklaşımla ilgili ana sınırlama, yarım dairenin çap çizgisidir ve orijinal çizgiyi oluşturur. Arka planınız beyazsa (veya herhangi bir düz renkte), arka plan rengini kullanarak 3. basit bir çizgi ekleyebilirsiniz.

görüntü tanımını buraya girin

görüntü tanımını buraya girin

görüntü tanımını buraya girin

görüntü tanımını buraya girin

** EDIT **

Orta çizgiden kurtulmak için başka bir seçenek yeni bir SVG sembolü oluşturmaktır. Yarım eğriyi değiştirdim, sadece yuvarlak kısmı yaşadım. 1/2 elips daha çekici olsa da işe yarıyor. Ekran görüntüsü, sembol boyutu 10, aralık 4, ofset 2 kullanılarak yapıldı.

görüntü tanımını buraya girin

aşağıdaki kodu half_circle_line.svg dosyasına kaydedin ve svg yolunun içinde ayarlandığından emin olun. QGIS // Settings / Options / System / SVG Paths

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="11.2889mm" height="11.2889mm"
 viewBox="0 0 32 32"
 xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"  version="1.2" baseProfile="tiny">
<title>Qt Svg Document</title>
<desc>Generated with Qt</desc>
<defs>
</defs>
<g fill="none" stroke="black" stroke-width="1" fill-rule="evenodd" stroke-linecap="square" stroke-linejoin="bevel" >

<g fill="#ffffff" fill-opacity="0" stroke="#000000" stroke-opacity="1" stroke-width="1" stroke-linecap="square" stroke-linejoin="bevel" transform="matrix(1,0,0,1,0,0)"
font-family="MS Shell Dlg 2" font-size="8.25" font-weight="400" font-style="normal" 
>
<path vector-effect="non-scaling-stroke" fill-rule="evenodd" d="M19.1181,16 C19.1181,16 19.1181,14.2779 17.7221,12.8819 16,12.8819 C14.2779,12.8819 12.8819,14.2779 12.8819,16"/>
</g>
</g>
</svg>

İyi fikir. Şu anda ısrarcı "merkez hattı" ile mücadele ediyor ...: \
Kazuhito

Benden de +1. Bu arada, bir PyQGIS çözümünü düşünmeye çalışıyorum. @ Kazuhito, lütfen bunun sizin için yeterli olup olmadığını veya fiziksel bir çözümü tercih ediyorsanız bana bildirin .
mgri

@mgri Bu cevabı ile şimdi "dalga" değil "değiştirmeye" bir "zincir" var. Fiziksel bir çözüme sahip olduğunuzu gerçekten takdir ediyorum.
Kazuhito

JGH “Orta çizgiyi”, beyaz bir çizgiyle maskelemekten başka, kaldırma şekliniz var mı? Parçalanmış gibi görünüyor.
Kazuhito

@Kazuhito - No Pen :) ' Pen stylee değiştirebilirsiniz :)
Joseph
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.