ST_Intersect dengan degenerate LINESTRING

9

Saya memiliki, di PostGIS, sekelompok objek Z LINESTRING (yang mewakili kutub), dan saya ingin menemukan mana yang ada di dalam area (diwakili oleh POLYGON). Untuk keperluan latihan ini, kita dapat dengan aman berasumsi bahwa sebuah tiang cukup vertikal, sehingga tidak akan memotong batas area.

Masalahnya adalah bahwa terkadang kutubnya persis vertikal.

Kueri ini, yang ingin saya lakukan, tidak berhasil:

SELECT ST_Intersects(ST_GeomFromText('LINESTRING Z (544483.525 6849134.28 104.1098,544483.525 6849134.28 114.6)',28356),
ST_GeomFromText('POLYGON((543907.636214323 6848710.84802846,543909.787417164 6849286.92923919,544869.040437688 6849283.30837091,544866.842236582 6848707.22673193,543907.636214323 6848710.84802846))',28356));

Menjelajahi beberapa varian, ini berhasil:

SELECT ST_Intersects(ST_GeomFromText('POINT (544483.525 6849134.28)',28356),
ST_GeomFromText('POLYGON((543907.636214323 6848710.84802846,543909.787417164 6849286.92923919,544869.040437688 6849283.30837091,544866.842236582 6848707.22673193,543907.636214323 6848710.84802846))',28356));

Ini tidak berhasil:

SELECT ST_Intersects(ST_GeomFromText('LINESTRING (544483.525 6849134.28,544483.525 6849134.28)',28356),
ST_GeomFromText('POLYGON((543907.636214323 6848710.84802846,543909.787417164 6849286.92923919,544869.040437688 6849283.30837091,544866.842236582 6848707.22673193,543907.636214323 6848710.84802846))',28356));

Jika Anda melakukan kueri 3DIntersects, berhasil:

SELECT ST_3DIntersects(ST_GeomFromText('LINESTRING Z (544483.525 6849134.28 104.1098,544483.525 6849134.28 114.6)',28356),
ST_GeomFromText('POLYGON((543907.636214323 6848710.84802846,543909.787417164 6849286.92923919,544869.040437688 6849283.30837091,544866.842236582 6848707.22673193,543907.636214323 6848710.84802846))',28356));

namun hal itu menimbulkan PEMBERITAHUAN bahwa:

One or both of the geometries is missing z-value. The unknown z-value will be regarded as "any value"

Jadi itu bekerja, semacam, tetapi mengisi log saya dengan kebisingan dan saya lebih suka untuk tidak mematikan peringatan.

Bacaan saya tentang standar akses fitur OpenGIS Simple (lihat bagian 1, bagian 4.14) adalah bahwa meskipun LINESTRING adalah yang merosot, itu masih harus ditafsirkan sebagai ditutup secara topologis, sehingga mereka harus berpotongan.

Apakah ini benar?

EDIT

Setelah beberapa percobaan, saya dapat menjawab sebagian dari pertanyaan saya sendiri. Alasan mengapa kueri di atas menghasilkan false adalah ini karena LINESTRING Z diyakini tidak valid:

SELECT ST_IsValidReason(ST_GeomFromText('LINESTRING Z (544483.525 6849134.28 104.1098,544483.525 6849134.28 114.6)',28356));
                           st_isvalidreason                           
----------------------------------------------------------------------
 Too few points in geometry component[544483.525 6849134.28 104.1098]
(1 row)

Ini adalah cara yang sopan untuk mengatakan bahwa OGC tidak mendukung 3D, dan karena itu, GDAL / PostGIS hanya mendukungnya saja.

Saya dapat menerimanya, meskipun saya masih belum menemukan apa pun dalam spesifikasi OGC yang menunjukkan bahwa LINESTRING yang sesuai tidak valid.

Jadi saya kira pertanyaan saya benar-benar adalah: Apakah ada cara yang diberkati secara resmi untuk menemukan jejak kaki sepotong geometri 3D yang selalu mengembalikan geometri 2D yang valid?

Nama samaran
sumber

Jawaban:

6

Perbaikan yang sangat sederhana pada kueri pertama adalah menggunakan ST_MakeValid untuk membuat geometri "valid" untuk mengembalikan true:

SELECT ST_Intersects(ST_MakeValid(A), B), ST_AsText(ST_MakeValid(A)) AS ST_MakeValid
FROM (
  SELECT ST_GeomFromText('LINESTRING Z (544483.525 6849134.28 104.1098,544483.525 6849134.28 114.6)',28356) AS A,
         ST_GeomFromText('POLYGON((543907.636214323 6848710.84802846,543909.787417164 6849286.92923919,544869.040437688 6849283.30837091,544866.842236582 6848707.22673193,543907.636214323 6848710.84802846))',28356) AS B
) AS d;

-[ RECORD 1 ]-+-----------------------------------------
st_intersects | t
st_makevalid  | POINT Z (544483.525 6849134.28 104.1098)

Kueri asli gagal karena objek LineString tidak valid, seperti yang ditemukan oleh ST_IsValid atau ST_IsValidReason . Ini karena ST_Intersects adalah operator 2D, sehingga geometri terpaksa dua dimensi LINESTRING(544483.525 6849134.28,544483.525 6849134.28), yang tidak valid.

ST_MakeValid menghapus koordinat berulang (dalam ruang 2D), dan mengubahnya ke jenis titik karena geometri yang dihasilkan hanya memiliki satu koordinat.

Anda mungkin melihat bahwa koordinat Z sebagian masih ada, tetapi diabaikan. Jika ini mengganggu Anda, Anda juga dapat menggunakan ST_Force2D untuk hanya menggunakan geometri 2D untuk hal-hal seperti ST_Intersects:

SELECT ST_Intersects(ST_MakeValid(ST_Force2D(A)), B),
  ST_AsText(ST_Force2D(A)) AS ST_Force2D,
  ST_AsText(ST_MakeValid(ST_Force2D(A))) AS ST_MakeValid
FROM (
  SELECT ST_GeomFromText('LINESTRING Z (544483.525 6849134.28 104.1098,544483.525 6849134.28 114.6)',28356) AS A,
         ST_GeomFromText('POLYGON((543907.636214323 6848710.84802846,543909.787417164 6849286.92923919,544869.040437688 6849283.30837091,544866.842236582 6848707.22673193,543907.636214323 6848710.84802846))',28356) AS B
) AS d;

-[ RECORD 1 ]-+--------------------------------------------------------
st_intersects | t
st_force2d    | LINESTRING(544483.525 6849134.28,544483.525 6849134.28)
st_makevalid  | POINT(544483.525 6849134.28)
Mike T
sumber
Terima kasih! Ini adalah penjelasan yang bagus tentang apa yang terjadi, dan solusinya juga bagus.
Nama samaran