Saya membuat skrip kecil dan naif yang mengubah input LineStrings ke CompoundCurves berdasarkan beberapa heuristik.
Apa fungsinya:
- Memotong sudut tajam untuk membuat hasil yang secara visual lebih menarik daripada data asli.
- Gunakan plpgsql. Tidak diperlukan ekstensi tambahan.
- Menerima "faktor pemulusan" opsional antara 0 dan 100 selain geometri.
Apa yang tidak dilakukan:
- Memproses MultiLineStrings. Untuk jenis geometri lainnya, ia hanya mengembalikan input.
- Menggunakan nilai Z dan M. Itu hanya menjatuhkan mereka. Gunakan ini hanya untuk keperluan kartografi 2D.
- Menciptakan hasil yang benar secara matematis. Hasilnya jauh dari benar, dan bahkan mungkin secara visual tidak estetis dalam beberapa kasus (misalnya sudut tajam). Saya tidak mengujinya secara menyeluruh. Selalu tinjau hasilnya!
- Berlari cepat. Saya yakin itu dapat ditulis ulang ke bentuk yang jauh lebih optimal.
- Apakah smoothing nyata. Ada banyak algoritma yang lebih baik (misalnya Chaiken atau yang disebutkan dalam pertanyaan) untuk digunakan untuk smoothing nyata. Jawaban ini menargetkan orang-orang seperti saya yang mencari pendekatan PostGIS murni secara otomatis membuat semacam garis lengkung dari data nyata.
Naskah:
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;
Ketika mengembalikan kurva dalam tipe geometri, jika Anda ingin menggunakannya dalam GIS seperti QGIS, Anda harus membungkusnya ke dalam fungsi PostGIS untuk mengubahnya. Sintaks penggunaan yang dimaksudkan adalah:
SELECT ST_AsText(ST_CurveToLine(CreateCurve(geom))) AS geom FROM linestringtable;
Ini masih merupakan masalah terbuka di PostGIS (dan perangkat GIS lainnya) sebagaimana dinyatakan dalam buku "PostGIS dalam Tindakan" di bab 2.2.6 "Geometri lengkung".
Berikut ini beberapa referensi untuk algoritma dan kode:
sumber
Anda dapat mencoba mengubah linestrings Anda menjadi kurva dengan ST_LineToCurve dan kemudian kembali ke linestrings dengan ST_CurveToLine .
Anda dapat mengatur jumlah segmen per kuartal lingkaran yang Anda inginkan di ST_CurveToLine.
sumber