PostGISでラインを外挿する


19

私はラインセグメントから外挿しようとしていますが、ライン上のポイントを見つけようとしていますが、3番目の方法は「戻る」、つまりnewポイントAB以下のポイントを見つけようとしています:

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

線を指定すると、それに沿って特定の割合で位置を取得するためにそれを補間できます。

=# select st_line_interpolate_point(
   st_makeline('0101000020E6100000300DC347C49418C03EE8D9ACFAA44A40', 
               '0101000020E6100000FB743C66A03218C0CDCCCCCCCC7C4A40'), 
   0.333);
0101000020E6100000ED45B41D537718C069C6A2E9EC984A40

負の数を入力して、線に沿って反対方向のポイントを見つけようとしましたが、補間引数が[0、1]の範囲内にある必要があるため失敗します

最初にラインをスケーリングすることを考えましたが、ラインの中心を原点として使用しないので、私の目的には役に立ちません。

回答:


21

以前に同様の問題を解決した別の方法は、それを次の手順に分解することです。

-- get the points A and B given a line L
A := ST_STARTPOINT(L);
B := ST_ENDPOINT(L);

-- get the bearing from point B --> A
azimuth := ST_AZIMUTH(B,A);

-- get the length of the line A --> B
length := ST_DISTANCE(A,B);
newlength := length + (length * (1/3));   -- increase the line length by 1/3

-- create a new point 1/3 as far away from A as B is from A
newpoint := ST_TRANSLATE(A, sin(azimuth) * newlength, cos(azimuth) * newlength);

編集:newlengthの割り当てを修正し、1/3ではなく1 1/3の長さになるようにし、図に合わせてA&Bを切り替えました。


勝者がいます!はるかにわかりやすい。
EoghanM

これはかなりクールです
ネイサンW

ありがとう。私はもともと輪郭線間を手動で補間していたいくつかの作業からこのスニペットを持っていました-輪郭でやろうとしていたことは時間の無駄でしたが、このスニペットが他の人を助けてくれてうれしいです!:)
ジェイデン

6

でそれを解決しました:

F = 1.3333
st_affine(A, F, 0, 
             0, F, 
            (F-1)*-st_x(st_line_interpolate_point(st_makeline(A, B), 0.5)), 
            (F-1)*-st_y(st_line_interpolate_point(st_makeline(A, B), 0.5))
          )

説明:

(2-d)開始点を1.3333の係数でスケーリングします。ラインセグメントの中点をスケーリングの原点として使用します。

グラフ用紙を入手してください!

http://en.wikipedia.org/wiki/Affine_transformation


2

このための関数を書きました:

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;

使用法:

SELECT st_extend(
st_makeline(
  '0101000020E6100000300DC347C49418C03EE8D9ACFAA44A40', 
  '0101000020E6100000FB743C66A03218C0CDCCCCCCCC7C4A40'
),
1.333::double precision,
0::double precision,
1::double precision,
0::double precision
);

これにより、長いラインストリングが得られますが、エンドポイントは得られないことに注意してください。

GitHubの要旨上のコード(あなたがここupvote私もそこに星をいただければ幸いです場合)

パラメータの説明(sql関数のコメントで見逃した場合):

  • 最初のセグメントの長さは、original_length * head_rate + head_constantになります。
  • 2倍にするには、ヘッドレートは2、定数は​​0です。
  • ハンガリーでは通常、メートルベースのEOV投影法を使用しています。したがって、行の最後に2メートルを追加する場合は、tail:rateを1に、tail_constantを2に設定します。

これは非常にうまく機能します。head_rate、head_constant、tail_rate、tail_constantに関する情報を追加できますか?ここやGitHubでは説明されていません。ヘッドレート=エンドポイント後のライン延長のスケールファクター、テールレート=スタートポイント前のライン延長のスケールファクターと仮定しています。定数はどのように機能しますか?彼らはどのような効果がありますか?
jbalk

そのコメントに。最初のセグメントの長さはですoriginal_length * head_rate + head_constant。2倍にしたい場合、ヘッドレートは2、定数は​​0です。ハンガリーでは通常、メーターベースのEOV投影を使用します。私は、行の末尾に2メートルを追加したいのであれば、私は尾を設定する:1にレートと2にtail_constant
SzieberthAdam

ありがとうございました!そして、この機能を共有してくれてありがとう。完全に機能し、迅速に実行されます。
jbalk
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.