Vẽ các đường lượn sóng, uốn lượn trong QGIS?


21

Có một chức năng hoặc plugin QGIS để vẽ đường uốn lượn?

Tôi đã sử dụng Spline Tool để tự vẽ một số sóng, nhưng nó tốn thời gian. Nếu có thể, tôi muốn vẽ một cái gì đó như:

nhập mô tả hình ảnh ở đây

Inkscape Function Plotter ( sin(x)đường cong).


Câu hỏi thực sự thú vị! Bạn đang suy nghĩ về một công cụ để vẽ các đường ngay lập tức (ví dụ như khi bạn vẽ một tính năng đường đơn giản bằng chuột) hoặc có thể là cách để có kết quả này bắt đầu từ tọa độ làm đầu vào (cuối cùng là từ các điểm, đường hoặc đa giác)?
mgri

1
@mgri Cảm ơn bình luận của bạn. Tôi hy vọng sẽ sử dụng dòng này để đánh dấu một ranh giới với một số điểm không chắc chắn (như đường bờ dao động), vì vậy ý ​​tưởng chính là chuyển đổi một đa tuyến (thông qua tọa độ được xác định trước) thành các vặn. Nhưng ý tưởng vẽ ngay đường này cũng có vẻ hấp dẫn.
Kazuhito

Xin vui lòng, xem nếu giải pháp của tôi giúp. Tôi đã không kiểm tra rộng rãi, vì vậy vui lòng cho tôi biết nếu có sự cố xảy ra (tôi không thể thực hiện ngay bây giờ, nhưng tôi có thể sẽ chỉnh sửa câu trả lời của mình với nhiều thông tin hơn).
mgri

Câu trả lời:


18

Tôi đề xuất một giải pháp sử dụng PyQGIS. Nó nên hoạt động cho cả hai lớp Linestring và MultiLineString.

Giải pháp này dựa trên việc tạo ra các vòng bán nguyệt, vì vậy bạn cần đặt giá trị cho đường kính (tức là stepbiến trong mã bên dưới). Bước bạn chọn sẽ không phải là bước thực sự được sử dụng vì nó được điều chỉnh trên cơ sở độ dài của dòng (nhưng nó sẽ thực sự giống với giá trị được đặt ban đầu). Bạn cần thực hiện một số lần thử trước khi tìm giá trị tốt nhất cho stepbiến.

Mã này cũng yêu cầu tham số thứ hai (tùy chọn) (được gọi crv_angle), giúp giảm hoặc tăng độ cong cho các vòng (Tôi đã thực hiện một vài thử nghiệm cho nó, vì vậy tôi khuyên bạn nên để góc 45 độ làm góc mặc định vì nó sẽ dẫn đến vòng tròn thực Nhẫn).

Bạn chỉ cần chạy mã này từ Bảng điều khiển Python:

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)

và nó sẽ tạo ra một lớp bộ nhớ dòng mới với kết quả mong đợi:

nhập mô tả hình ảnh ở đây


Ồ Tôi không thể ngừng chơi với điều này, rất tuyệt vời. Trên hết, đầu ra có thể được sử dụng cho các hoạt động tiếp theo như bộ đệm. Cảm ơn bạn @mgri. Một điều cuối cùng, đôi khi tôi thấy các vòng tròn nhỏ xuất hiện ở hoặc gần các đỉnh. Điều này có thể tránh được không? Tôi có thể loại bỏ chúng bằng cách xóa nút trung tâm của vòng tròn như vậy bằng Công cụ Node (vì vậy nó không phải là vấn đề lớn).
Kazuhito

1
@Kazuhito xin vui lòng, xem mã chỉnh sửa của tôi. Có vẻ như có điều gì đó không ổn với sự rời rạc và tôi hy vọng nó đã được sửa chữa. Tôi đã thực hiện một số thử nghiệm và nó có vẻ hoạt động tốt (mã cũng dễ đọc hơn).
mgri

1
Cảm ơn rất nhiều @mgri. Có những vòng tròn rất nhỏ, mà tôi xin lỗi tôi không thể giải thích rõ ràng chúng xuất hiện như thế nào. Hầu hết các đỉnh hiện nay là "không có vòng tròn". Chỉ có sự khác biệt mà tôi nhận thấy là nút như vậy (có vòng tròn) đã hiển thị "giá trị r" nhỏ hơn trên Bảng công cụ nút của Vertex Editor. Điều này dễ dàng quản lý và tốt hơn nhiều so với tôi đã dự đoán. Cám ơn bạn một lần nữa. Hãy để tôi chấp nhận câu trả lời của bạn là giải pháp.
Kazuhito

1
Cảm ơn, @Kazuhito. Tôi xin lỗi vì đã không tạo ra một giải pháp hoàn hảo. Tuy nhiên, tôi hy vọng bạn sẽ thích nó (nếu không, bạn cũng có thể gửi cho tôi một shapefile mẫu và tôi sẽ cố gắng khắc phục vấn đề). Nếu tôi tìm thấy một cách hiệu quả hơn, tôi sẽ đăng nó!
mgri

1
Rất cám ơn @mgri. Nếu tôi tìm thấy bất kỳ mẫu đặc biệt nào xuất hiện các vòng tròn, tôi sẽ cập nhật cho bạn với ví dụ có thể lặp lại. Điều này là rất nhiều thú vị (và đầu ra của nó là đẹp)!
Kazuhito

20

Câu trả lời ngắn: bạn có thể lấy nó bằng cách sử dụng một SVG tùy chỉnh. Xem dưới cùng của bài viết này cho một.

Câu trả lời dài:

Tôi tin rằng tốt hơn là đại diện cho nó hơn là sửa đổi hình dạng đường. Nếu bạn muốn di chuyển một cạnh hoặc thực hiện các hành động khác trên hình học, sẽ là một cơn ác mộng khi quản lý nếu các wiggles là một phần của hình học thay vì chỉ là một đại diện của một đường thẳng.

Bạn có thể chơi với dòng đánh dấu phong cách. Có một cách để dễ dàng đến gần với những gì bạn cần, và với một chút nỗ lực hơn, có khả năng có thể có được nó một cách chính xác. nhập mô tả hình ảnh ở đây

Để có được điều này, bạn sẽ tạo kiểu cho dòng bằng hai dòng Marker. Mỗi dòng Marker được tạo từ một Marker đơn giản, nửa vòng tròn. Cái đầu tiên được xoay 180. Cả hai đều được đặt trong suốt.

Trên dòng Marker, bạn hướng dẫn một trong số chúng được bù để hai biểu tượng không được vẽ trước mặt nhau mà nằm cạnh nhau. Nếu bạn sử dụng kích thước khoảng cách = 1/2 *, đầu ra sẽ là một đường cong hình sin. Tôi đề nghị bạn chơi với kích thước khoảng, kích thước bù và kích thước biểu tượng.

Giới hạn chính của phương pháp này là đường kính của nửa vòng tròn, tính tổng với đường ban đầu. Nếu nền của bạn là màu trắng (hoặc bất kỳ màu trơn nào), bạn có thể thêm một dòng đơn giản thứ 3 bằng cách sử dụng màu nền.

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

** CHỈNH SỬA **

Một tùy chọn khác để thoát khỏi đường trung tâm là tạo biểu tượng SVG mới. Tôi sửa đổi nửa đường cong, chỉ sống phần tròn. Nó hoạt động, mặc dù hình elip 1/2 có thể hấp dẫn hơn. Ảnh chụp màn hình được thực hiện bằng cách sử dụng ký hiệu kích thước 10, khoảng 4, bù 2.

nhập mô tả hình ảnh ở đây

lưu mã bên dưới trong tệp Half_circle_line.svg và đảm bảo đường dẫn đến svg được đặt trong 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>

Ý kiến ​​hay. Hiện đang vật lộn với "đường trung tâm" dai dẳng ...: \
Kazuhito

+1 từ tôi cũng vậy. Trong khi đó, tôi đang cố gắng nghĩ đến giải pháp PyQGIS. @Kazuhito, xin vui lòng cho tôi biết nếu điều này là đủ cho bạn hoặc nếu bạn thích một giải pháp vật lý .
mgri

@mgri Với câu trả lời này tôi có một "chuỗi" chứ không phải "sóng" bây giờ (cố gắng sửa đổi nó). Sẽ thực sự đánh giá cao để có một giải pháp vật lý.
Kazuhito

JGH Bạn có khả năng có ý tưởng loại bỏ "đường trung tâm", ngoài việc che dấu nó bằng một đường trắng (hình dưới của ieyour) không? Có vẻ như nó bị phân mảnh.
Kazuhito

@Kazuhito - Bạn có thể đổi Pen stylethành Không bút :)
Joseph
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.