Làm cách nào để thực hiện làm mịn dòng SIA hoặc Bezier trong PostGIS?


9

Bất cứ ai cũng có thể cung cấp một ví dụ SQL để làm mịn các dòng từ bảng postgis bằng cách sử dụng các đường cong Bezier hoặc thuật toán trung bình lặp ( SIA )?

Câu trả lời:


6

Tôi đã tạo một tập lệnh nhỏ, ngây thơ để chuyển đổi LineStrings đầu vào thành CompoundCurves dựa trên một số phương pháp phỏng đoán.

Những gì nó làm:

  • Cắt giảm các góc nhọn để tạo ra kết quả trực quan hấp dẫn hơn so với dữ liệu gốc.
  • Sử dụng plpgsql. Không có phần mở rộng bổ sung cần thiết.
  • Chấp nhận một "hệ số làm mịn" tùy chọn trong khoảng từ 0 đến 100 bên cạnh hình học.

Những gì nó không làm:

  • Quy trình MultiLineStrings. Đối với bất kỳ loại hình học khác, nó chỉ cần trả về đầu vào.
  • Sử dụng giá trị Z và M. Nó chỉ đơn giản là thả chúng. Chỉ sử dụng cho mục đích bản đồ 2D.
  • Tạo kết quả chính xác về mặt toán học. Các kết quả không chính xác, và thậm chí có thể không thẩm mỹ về mặt thị giác trong một số trường hợp (ví dụ: góc nhọn). Tôi đã không kiểm tra nó kỹ lưỡng. Luôn luôn xem lại kết quả!
  • Chạy nhanh. Tôi chắc chắn rằng nó có thể được viết lại thành một hình thức tối ưu hơn nhiều.
  • Có làm mịn thực sự. Có nhiều thuật toán tốt hơn (ví dụ Chaiken hoặc các thuật toán được đề cập trong câu hỏi) để sử dụng để làm mịn thực sự. Câu trả lời này nhắm đến những người như tôi đang tìm kiếm một cách tiếp cận PostGIS thuần túy tự động tạo ra một số loại đường cong từ dữ liệu thực.

Kịch bản:

CREATE OR REPLACE FUNCTION CreateCurve(geom geometry, percent int DEFAULT 40)
    RETURNS geometry AS
$$
DECLARE
    result text;
    p0 geometry;
    p1 geometry;
    p2 geometry;
    intp geometry;
    tempp geometry;
    geomtype text := ST_GeometryType(geom);
    factor double precision := percent::double precision / 200;
    i integer;
BEGIN
    IF percent < 0 OR percent > 100 THEN
        RAISE EXCEPTION 'Smoothing factor must be between 0 and 100';
    END IF;
    IF geomtype != 'ST_LineString' OR factor = 0 THEN
        RETURN geom;
    END IF;
    result := 'COMPOUNDCURVE((';
    p0 := ST_PointN(geom, 1);
    IF ST_NPoints(geom) = 2 THEN
        p1:= ST_PointN(geom, 2);
        result := result || ST_X(p0) || ' ' || ST_Y(p0) || ',' || ST_X(p1) || ' ' || ST_Y(p1) || '))';
    ELSE
        FOR i IN 2..(ST_NPoints(geom) - 1) LOOP
            p1 := ST_PointN(geom, i);
            p2 := ST_PointN(geom, i + 1);
            result := result || ST_X(p0) || ' ' || ST_Y(p0) || ',';
            tempp := ST_Line_Interpolate_Point(ST_MakeLine(p1, p0), factor);
            p0 := ST_Line_Interpolate_Point(ST_MakeLine(p1, p2), factor);
            intp := ST_Line_Interpolate_Point(
                ST_MakeLine(
                    ST_Line_Interpolate_Point(ST_MakeLine(p0, p1), 0.5),
                    ST_Line_Interpolate_Point(ST_MakeLine(tempp, p1), 0.5)
                ), 0.5);
            result := result || ST_X(tempp) || ' ' || ST_Y(tempp) || '),CIRCULARSTRING(' || ST_X(tempp) || ' ' || ST_Y(tempp) || ',' || ST_X(intp) || ' ' ||
            ST_Y(intp) || ',' || ST_X(p0) || ' ' || ST_Y(p0) || '),(';
        END LOOP;
        result := result || ST_X(p0) || ' ' || ST_Y(p0) || ',' || ST_X(p2) || ' ' || ST_Y(p2) || '))';
    END IF;
    RETURN ST_SetSRID(result::geometry, ST_SRID(geom));
END;
$$
LANGUAGE 'plpgsql' IMMUTABLE;

Vì nó trả về các đường cong theo kiểu hình học, nếu bạn muốn sử dụng nó trong một hệ thống GIS như QGIS, bạn phải bọc nó thành các hàm PostGIS chuyển đổi chúng xung quanh. Cú pháp sử dụng dự định là:

SELECT ST_AsText(ST_CurveToLine(CreateCurve(geom))) AS geom FROM linestringtable;

Đây là một cứu cánh! Cảm ơn bạn cho kịch bản. Có vẻ như làm mịn Chaikin sẽ trở nên khả dụng như một chức năng từ postgis 2.5 trở đi, điều mà tôi mong chờ.
she_weed

1

Đây vẫn là một vấn đề mở trong PostGIS (và các công cụ GIS khác) như đã nêu trong cuốn sách "PostGIS in Action" trong chương 2.2.6 "Hình học cong".

Dưới đây là một số tài liệu tham khảo về thuật toán và mã:


Tôi đã thêm các liên kết postgis.17.x6 ...
Martin F

0

Bạn có thể thử chuyển đổi các linestrings của mình thành các đường cong với ST_LineToCurve và sau đó quay lại các linestrings với ST_CurveToLine .

Bạn có thể đặt số lượng phân khúc trên mỗi vòng tròn quý bạn muốn trong ST_CurveToLine.


LineToCurve được xây dựng để bàn giao các đầu ra của CurveToLine, không trích xuất các đường cong từ đầu vào tùy ý.
Paul Ramsey

@PaulRamsey sẽ được làm mịn hơn trong phiên bản Postgis tiếp theo? Tôi đã suy nghĩ về một cái gì đó như thế này chẳng hạn: webhelp.esri.com/arcgisdesktop/9.2/iêu
Gery
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.