Saya menulis fungsi untuk ini:
CREATE OR REPLACE FUNCTION st_extend (
geom geometry,
head_rate double precision,
head_constant double precision,
tail_rate double precision,
tail_constant double precision)
RETURNS geometry AS
$BODY$
-- Extends a linestring.
-- First segment get extended by length * head_rate + head_constant.
-- Last segment get extended by length * tail_rate + tail_constant.
--
-- References:
-- http://blog.cleverelephant.ca/2015/02/breaking-linestring-into-segments.html
-- /gis//a/104451/44921
-- /gis//a/16701/44921
WITH segment_parts AS (
SELECT
(pt).path[1]-1 as segment_num
,
CASE
WHEN
(nth_value((pt).path, 2) OVER ()) = (pt).path
AND
(last_value((pt).path) OVER ()) = (pt).path
THEN
3
WHEN
(nth_value((pt).path, 2) OVER ()) = (pt).path
THEN
1
WHEN
(last_value((pt).path) OVER ()) = (pt).path
THEN
2
ELSE
0
END AS segment_flag
,
(pt).geom AS a
,
lag((pt).geom, 1, NULL) OVER () AS b
FROM ST_DumpPoints($1) pt
)
,
extended_segment_parts
AS
(
SELECT
*
,
ST_Azimuth(a,b) AS az1
,
ST_Azimuth(b,a) AS az2
,
ST_Distance(a,b) AS len
FROM
segment_parts
where b IS NOT NULL
)
,
expanded_segment_parts
AS
(
SELECT
segment_num
,
CASE
WHEN
bool(segment_flag & 2)
THEN
ST_Translate(b, sin(az2) * (len*tail_rate+tail_constant), cos(az2) * (len*tail_rate+tail_constant))
ELSE
a
END
AS a
,
CASE
WHEN
bool(segment_flag & 1)
THEN
ST_Translate(a, sin(az1) * (len*head_rate+head_constant), cos(az1) * (len*head_rate+head_constant))
ELSE
b
END
AS b
FROM extended_segment_parts
)
,
expanded_segment_lines
AS
(
SELECT
segment_num
,
ST_MakeLine(a, b) as geom
FROM
expanded_segment_parts
)
SELECT
ST_LineMerge(ST_Collect(geom ORDER BY segment_num)) AS geom
FROM expanded_segment_lines
;
$BODY$
LANGUAGE sql;
Pemakaian:
SELECT st_extend(
st_makeline(
'0101000020E6100000300DC347C49418C03EE8D9ACFAA44A40',
'0101000020E6100000FB743C66A03218C0CDCCCCCCCC7C4A40'
),
1.333::double precision,
0::double precision,
1::double precision,
0::double precision
);
Perhatikan bahwa ini menghasilkan linestring yang lebih panjang tetapi bukan titik akhir.
Kode pada GitHub Gist (jika Anda upvote di sini saya akan menghargai bintang di sana juga)
Deskripsi parameter (jika Anda melewatkannya di komentar fungsi sql):
- Panjang segmen pertama adalah original_length * head_rate + head_constant.
- Jika Anda ingin menjadi dua kali lipat maka laju head adalah 2, konstanta adalah 0.
- Kami di hungary biasanya menggunakan proyeksi EOV yang berbasis meter. Jadi jika saya ingin menambahkan 2 meter ke akhir baris, saya mengatur tail: rate ke 1 dan tail_constant ke 2.