QGISで波状の波線を描画しますか?


21

波線を描くQGIS関数またはプラグインはありますか?

Spline Toolを使用していくつかの波を手動で描画しましたが、時間がかかります。可能であれば、次のようなものを描きたいと思います。

ここに画像の説明を入力してください

Inkscape Function Plottersin(x)曲線)。


本当に興味深い質問です!マウスを使用して簡単なラインフィーチャを描画する場合など、すぐにラインを描画するためのツールを考えていますか、それとも入力としての座標から(最終的にはポイント、ラインまたはポリゴンから)この結果を取得する方法を考えていますか?
mgri

1
@mgriコメントありがとうございます。このラインを使用して、いくつかの不確実性(変動する海岸線など)で境界をマークすることを想定しているため、主なアイデアはポリラインを(事前定義された座標を介して)ウィグルに変換することでした。しかし、このタイプの線を即座に描くというアイデアも魅力的です。
和人

私の解決策が役立つかどうかを確認してください。私はそれを広くテストしていませんでしたので、何かがうまくいかない場合は私に知らせてください(私は今それをすることはできませんが、おそらく私はより多くの情報で私の答えを編集します)。
mgri

回答:


18

PyQGISを使用したソリューションを提案します。LinestringレイヤーとMultiLineStringレイヤーの両方で機能するはずです。

このソリューションは半円形のリングの作成に基づいているため、直径の値(つまり、step以下のコードの変数)を設定する必要があります。選択したステップは、実際のステップではありません。これは、ラインの長さに基づいて調整されるためです(ただし、最初に設定した値と実際に似ています)。step変数の最適な値を見つける前に、いくつかの試行を行う必要があります。

コードには、2番目の(オプションの)パラメーター(と呼ばれるcrv_angle)も必要です。これは、リングの曲率を増減させるのに役立ちます(いくつかのテストを実行したため、実際の円形につながるため、デフォルトの角度として45度のままにすることをお勧めしますリング)。

Python Consoleからこのコードを実行するだけです:

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)

そして、期待される結果で新しいラインメモリレイヤーを作成します:

ここに画像の説明を入力してください


うわー!これで遊ぶのをやめられないので、とてもゴージャスです。さらに、出力自体は、バッファなどの追加の操作に使用できます。@mgriありがとう。最後に、頂点またはその近くに小さな円が表示されることがあります。これは避けられますか?Node Toolでそのような円の中心ノードを消去することでそれらを削除できます(それで大したことではありません)。
和人

1
@Kazuhito、私の編集したコードをご覧ください。離散化に何か問題があったようです。これが修正されることを望みます。いくつかのテストを実行しましたが、うまく機能しているようです(コードも読みやすくなっています)。
mgri

1
@mgriどうもありがとう。非常に小さな円がありますが、残念ながら、これらの円がどのように表示されるかを明確に説明することはできません。ほとんどの頂点は「サークルフリー」になりました。私が気づいたのは、ノードツールの頂点エディタテーブルで、そのようなノード(丸付き)がより小さい「r値」を示していたことだけでした。これは簡単に管理でき、予想していたよりもはるかに優れています。ありがとうございました。あなたの答えを解決策として受け入れさせてください。
和人

1
ありがとう、一和。完璧なソリューションを作成できなかったことを申し訳ありません。ただし、楽しんでいただければ幸いです(そうでない場合は、サンプルシェープファイルを送信して問題を修正してみてください)。もっと効率的な方法を見つけたら、投稿します!
mgri

1
@mgriに感謝します。円の外観に特徴的なパターンが見つかった場合は、再現可能な例を使用して更新します。これはとても楽しいです(そしてその出力は美しいです)!
和人

20

簡単な答え:カスタムSVGを使用して取得できます。この投稿の下部をご覧ください。

長い答え:

ラインジオメトリを変更するよりも表現する方が良いと思います。エッジを移動したり、ジオメトリ上で他のアクションを実行したりする場合、直線の表現ではなく、ウィグルがジオメトリの一部であるかどうかを管理するのは悪夢です。

スタイルマーカーラインで遊ぶことができます。必要なものに簡単に近づける方法がありますが、もう少し手間をかけると、正確にそれを取得できる可能性があります。 ここに画像の説明を入力してください

これを取得するには、2つのマーカーラインでラインをスタイルします。各マーカーラインは、半円形のシンプルマーカーで構成されています。1つ目は180度回転します。両方とも透明に設定されます。

マーカーラインでは、2つのシンボルが互いの前に描かれるのではなく、並んで描かれるように、それらの1つをオフセットするよう指示します。offest = 1/2 * interval sizeを使用すると、出力は正弦曲線になります。間隔サイズ、オフセット、シンボルサイズを試してみることをお勧めします。

このアプローチの主な制限は、半円の直径線であり、合計すると元の線になります。背景が白(または任意の無地の色)の場合、背景色を使用して3番目の単純な線を追加できます。

ここに画像の説明を入力してください

ここに画像の説明を入力してください

ここに画像の説明を入力してください

ここに画像の説明を入力してください

** 編集 **

中心線を取り除く別のオプションは、新しいSVGシンボルを作成することです。半曲線を修正し、丸みを帯びた部分のみを使用しました。動作しますが、1/2の楕円がより魅力的かもしれません。スクリーンショットは、シンボルサイズ10、間隔4、オフセット2を使用して行われました。

ここに画像の説明を入力してください

以下のコードをファイルhalf_circle_line.svgに保存し、svgへのパスが設定されていることを確認します 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>

良いアイデア。現在、持続的な「中心線」に苦しんでいます...:\
Kazuhito

私からも+1。その間、私はPyQGISソリューションを考えようとしています。@一仁、これで十分かどうか、または物理的な解決策を好むかどうかを教えてください。
mgri

@mgriこの回答で、私は今「波」ではなく「チェーン」を持っています(修正しようとしています)。物理的な解決策があれば本当にありがたいです。
和人

JGH「中心線」を削除する考えを、白い線(下の図)でマスクする以外に考えていますか?断片化されているように見えます。
和人

@Kazuhito -あなたは変更することができますPen styleはありませんペン :)
ジョセフ・
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.