ST_Intects với LINESTRING thoái hóa


9

Tôi có, trong PostGIS, một loạt các đối tượng LINESTRING Z (đại diện cho các cực) và tôi muốn tìm những đối tượng nào ở trong một khu vực (được đại diện bởi POLYGON). Với mục đích của bài tập này, chúng ta có thể giả định một cách an toàn rằng một cây cột có chiều dọc khá nhiều, vì vậy nó sẽ không giao nhau với ranh giới của khu vực.

Vấn đề là đôi khi cực chính xác.

Truy vấn này, một truy vấn tôi muốn làm, không thành công:

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));

Khám phá một vài biến thể, điều này thành công:

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));

Điều này không thành công:

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));

Nếu bạn thực hiện truy vấn 3DIntersects, nó sẽ thành công:

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));

tuy nhiên, nó đưa ra một thông báo rằng:

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

Vì vậy, nó hoạt động, loại, nhưng nó lấp đầy nhật ký của tôi với tiếng ồn và tôi không muốn tắt cảnh báo.

Tôi đọc tiêu chuẩn truy cập tính năng OpenGIS Simple (xem phần 1, mục 4.14) là mặc dù LINESTRING là một suy biến, nhưng nó vẫn nên được hiểu là đóng theo cấu trúc liên kết, vì vậy chúng nên giao nhau.

Điều này có đúng không?

BIÊN TẬP

Sau một số thử nghiệm, tôi có thể trả lời một phần câu hỏi của riêng tôi. Lý do tại sao các truy vấn trên trả về sai là vì LINESTRING Z được cho là không hợp lệ:

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)

Đây là một cách lịch sự để nói rằng OGC không hỗ trợ 3D và do đó, GDAL / PostGIS chỉ hỗ trợ loại này.

Tôi có thể chấp nhận điều đó, mặc dù tôi vẫn chưa tìm thấy bất cứ điều gì trong đặc tả OGC chỉ ra rằng LINESTRING tương ứng không hợp lệ.

Vì vậy, tôi đoán câu hỏi của tôi thực sự là: Có một cách chính thức may mắn để tìm dấu chân của một mảnh hình học 3D luôn trả về hình học 2D hợp lệ?

Câu trả lời:


6

Một sửa chữa thực sự đơn giản cho truy vấn đầu tiên là sử dụng ST_MakeValid để tạo hình học "hợp lệ" để trả về 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)

Truy vấn ban đầu không thành công vì đối tượng LineString không hợp lệ, như được phát hiện bởi ST_IsValid hoặc ST_IsValidR Lý do . Điều này là do ST_Intersects là một toán tử 2D, do đó hình học bị buộc thành hai chiều, LINESTRING(544483.525 6849134.28,544483.525 6849134.28)không hợp lệ.

ST_MakeValid loại bỏ tọa độ lặp lại (trong không gian 2D) và thay đổi nó thành loại điểm do hình dạng kết quả chỉ có một tọa độ.

Bạn có thể thấy tọa độ Z vẫn còn một phần, nhưng nó bị bỏ qua. Nếu điều này làm phiền bạn, bạn cũng có thể sử dụng ST_Force2D để chỉ sử dụng hình học 2D cho những thứ như 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)

Cảm ơn! Đây là một lời giải thích tốt về những gì đang xảy ra, và cách giải quyết cũng tốt.
Bút danh
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.