Tôi có 2 bộ dữ liệu bao gồm dữ liệu bưu kiện địa chính - khoảng 125.000 hàng mỗi bộ. Cột hình học là đa giác WKB đại diện cho ranh giới bưu kiện; tất cả dữ liệu có giá trị hình học (đa giác được đóng, v.v.).
Một số dữ liệu gần đây xuất hiện trong một phép chiếu khác với dữ liệu cơ sở đang được sử dụng cho một công việc so sánh - vì vậy tôi đã loại bỏ dữ liệu mới hơn (cơ sở là 4326; cái còn lại là WGA94 được đưa vào PostGIS là 900914 ... Tôi đã đăng lại thành 4326) .
Giai đoạn đầu tiên của phân tích là tìm và lưu trữ các bưu kiện không phù hợp; một phần trong đó là xác định và lưu trữ các bưu kiện có hình dạng giống hệt nhau.
Vì vậy, tôi đã chạy một truy vấn rất chuẩn (khối mã bên dưới tóm tắt chi tiết lược đồ, v.v.):
create table matchdata as
select a.*
from gg2014 a, gg2013 b
where ST_Equals(a.g1,b.g1)
Kết quả KHÔNG.
"Lạ ..." Tôi nghĩ. "Có lẽ đã có những thay đổi đỉnh nhỏ gây ra bởi sự từ chối: điều đó sẽ gây phiền nhiễu, và thực sự không nên xảy ra."
May mắn thay, có dữ liệu khao khát dồi dào (5 cột định danh) cho phép tôi thiết lập các bưu kiện giống hệt nhau về mặt không gian: những cột có cùng số nhận dạng, có ngày thay đổi trong bảng 2014 trước ngày thay đổi tối đa trong dữ liệu 2013. Con số đó lên tới 120.086 hàng khác nhau.
Tôi đã lưu trữ các định danh và hình học trong một bảng riêng biệt ( match_id
) và chạy truy vấn sau:
select apid,
bpid,
ST_Area(ag::geometry) as aa,
ST_Area(bg::geometry) as ab,
ST_Area(ST_Intersection(ag,bg)::geometry)/ST_Area(ag::geometry) as inta,
ST_Area(ST_Intersection(ag,bg)::geometry)/ST_Area(ag::geometry) as intb
from match_id
order by inta
16 giá trị đầu tiên cho inta
và intb
có giá trị bằng 0, 456 tiếp theo là 0,99999999-ish (tối thiểu 0,999999999999994, tối đa 0,99999999999999) và các hàng 473 trở đi là 1 - cho đến hàng 120050, khi diện tích của giao lộ lớn hơn cả hình học (lớn nhất) giá trị cho inta
và intb
là 1.00000000000029, nhưng vẫn).
Vì vậy, đây là câu hỏi hóc búa của tôi: nếu hai hình học giao nhau về mặt không gian giữa 99.999999999994% và 100.000000000029% các khu vực tương ứng của chúng, tôi muốn "ST_Equals" nói "Yep .... Tôi sẽ cung cấp cho bạn cái đó. Đóng đủ".
Rốt cuộc, nó tương đương với việc thoát ra khoảng 1 phần trong 16 nghìn tỷ ... tức là, như thể nợ quốc gia của Hoa Kỳ đã giảm dưới 93 cent.
Trong bối cảnh chu vi của Trái đất (ở mức ~ 40.000km), nó giống như bị tắt bởi 0,0000000025km, ngọn (do dẫn đến sự khác biệt về diện tích nhỏ, bất kỳ sự dịch chuyển đỉnh nào cũng phải nhỏ hơn).
Theo TFD (mà tôi có R'd), dung sai cho không phải ST_Intersects()
là 0,00001m (1mm), do đó, những thay đổi ngụ ý ở các đỉnh (mà tôi thú nhận là tôi đã không kiểm tra: tôi sẽ làm ST_Dump()
chúng và làm như vậy) dường như nhỏ hơn Hơn cả sự bao dung. (Tôi nhận ra điều đó ST_Intersects !== ST_Intersection()
, nhưng đó là sự khoan dung duy nhất được đề cập).
Tôi chưa thể tìm ra dung sai tương ứng cho so sánh đỉnh được thực hiện bởi ST_Equals()
... nhưng có vẻ thực sự kỳ lạ khi ít nhất 120.000 hàng của tôi phải vượt qua bất kỳ đánh giá hợp lý nào về nhận dạng không gian, nhưng không.
(Lưu ý: Tôi cũng đã thực hiện bài tập tương tự bằng cách sử dụng ::geography
- với kết quả có nhiều thay đổi hơn, nhưng vẫn còn hơn 110.000 mục với độ sạch đẹp '1').
Có cách nào để nới lỏng dung sai của ST_Equals, mà không cần phải đào sâu vào các kẽ của mã không? Tôi không quan tâm đến việc đó.
Nếu không, có một loại bùn mà bất cứ ai cũng biết?
Lưu ý: sẽ tốt hơn nếu 'bùn' không thực hiện so sánh song phương như
where ST_within(g1, ST_Buffer(g2, 0.0000001))
and ST_within(g2, ST_Buffer(g1, 0.0000001))
- I've done that: sure, it works... but it's a gigantic documentation PITA).
Tôi có thể giải quyết vấn đề này, nhưng viết 20 trang để ghi lại cách giải quyết - sẽ chỉ xuất hiện trở lại nếu chúng tôi nhận được dữ liệu tinh ranh - là một PITA mà tôi không muốn phải làm vì nó có khả năng là một lần .
(Phiên bản: Postgresql 9.3.5; PostGIS 2.1.3)
ST_Equals
chỉ trả về true
khi hình học bằng nhau - loại hình học, số đỉnh, SRID và giá trị đỉnh (trong tất cả các kích thước, theo cùng một thứ tự). Nếu có bất kỳ phương sai nào, so sánh dừng lại và false
được trả về.
ST_Equals()
bỏ qua tính định hướng. Tôi lấy điều đó có nghĩa là đối với đa giác 2 chiều đóng, sẽ không có gì khác biệt nếu các điểm được liệt kê theo chiều kim đồng hồ so với ngược chiều kim đồng hồ. ST_OrderingEquals()
là bài kiểm tra chặt chẽ hơn. Điều đó nói rằng, đã kiểm tra các đỉnh (sử dụng ST_Dump()
và tính toán đồng bằng cho mọi đỉnh) thì rõ ràng câu trả lời tuyệt vời của @John Barça là về tiền. ST_equals()
được chống chỉ định, ngay cả đối với ex ante dữ liệu được biết đến như giống hệt, nếu một hình học được chiếu lại - trừ khi so sánh được thực hiện với ST_SnapToGrid ().
(100*(ST_Area(ST_Intersection(a.g1, b.g1))/ST_Area(a.g1)))::int as int_pca
và (100*(ST_Area(ST_Intersection(a.g1, b.g1))/ST_Area(b.g1)))::int as int_pcb
(đảm bảo JOIN
bao gồm của bạn ST_Intersects(a.g1,b.g1)
). Kiểm tra nếu (int_pca, int_pcb)=(100,100)
(hoặc một số bộ cắt khác). Kydgy, nhưng nó sẽ thực hiện 2,6 triệu bưu kiện trong ~ 30 phút (miễn là g1 được lập chỉ mục GIST).