Làm cách nào để nhóm các điểm gần với vị trí GPS?


10

Tôi là một nhân viên CNTT nên tôi không biết quá nhiều về các dự đoán và cứ thế, tôi hy vọng bạn có thể giúp tôi.

Tôi đã tạo một ứng dụng cho Android thu thập vị trí GPS, vì vậy tôi có vĩ độ và kinh độ tại một thời điểm nhất định. Tôi muốn lưu lại các yếu tố gần nhau, trong các nhóm khu vực địa hình có cùng kích thước; vấn đề là tôi không biết điểm trước và chúng có thể đến từ bất kỳ vị trí nào trên thế giới .

Ý tưởng đầu tiên của tôi (để giải thích thêm một chút vấn đề) là sử dụng số thập phân của vĩ độ và kinh độ để nhóm; chẳng hạn, một nhóm sẽ là các vị trí có vĩ độ trong khoảng từ 35.123 đến 35.124 và kinh độ từ 60.101 đến 60.102. Vì vậy, nếu tôi có được một vị trí như lat = 35.1235647 và lon = 60.1012254598, điểm này sẽ thuộc về nhóm đó.

Giải pháp này sẽ ổn đối với đại diện 2D của cartesian, vì tôi sẽ có diện tích 0,001 đơn vị rộng và cao; tuy nhiên, vì kích thước của 1 độ kinh độ khác nhau ở các vĩ độ khác nhau, tôi không thể sử dụng phương pháp này.

Bất kỳ ý tưởng?


Tại sao bạn không thể lưu trữ vị trí như trong, và sau đó thực hiện xử lý sau? Ngoài ra tại xích đạo, 1 độ kinh độ xấp xỉ 111 km, do đó 0,001 độ sẽ hơn 1 km một chút. Bạn có thực sự muốn thùng của bạn rất lớn?
Devdatta Tengshe

Độ 0,001 chỉ là một ví dụ về ý tưởng của tôi. Tất nhiên tôi sẽ phải thích ứng với yêu cầu. Tôi không thể thực hiện xử lý bài đăng vì đây là một ứng dụng thời gian thực và tôi không thể nói với người dùng của mình "giữ cho đến ngày mai, vì tôi phải nhóm các điểm" Dù sao cũng cảm ơn vì ý tưởng;)
Kuu

Câu trả lời:


6

Một cách nhanh chóng và bẩn thỉu sử dụng một phân khu hình cầu đệ quy . Bắt đầu với một tam giác bề mặt trái đất, đệ quy chia từng tam giác từ một đỉnh ngang đến giữa cạnh dài nhất của nó. (Lý tưởng nhất là bạn sẽ chia hình tam giác thành hai phần có đường kính bằng nhau hoặc phần có diện tích bằng nhau, nhưng vì chúng liên quan đến một số tính toán khó hiểu, tôi chỉ chia hai bên chính xác một nửa: điều này khiến cho các hình tam giác khác nhau cuối cùng có kích thước khác nhau, nhưng điều đó dường như không quan trọng đối với ứng dụng này.)

Tất nhiên, bạn sẽ duy trì phân ngành này trong cấu trúc dữ liệu cho phép nhanh chóng xác định tam giác trong đó có bất kỳ điểm tùy ý nào. Cây nhị phân (dựa trên các lệnh gọi đệ quy) hoạt động độc đáo: mỗi lần chia tam giác, cây được chia tại nút của tam giác đó. Dữ liệu liên quan đến mặt phẳng phân tách được giữ lại, để bạn có thể nhanh chóng xác định phía nào của mặt phẳng bất kỳ điểm tùy ý nào: điều đó sẽ xác định việc di chuyển sang trái hay phải xuống cây.

(Tôi có nói là chia "mặt phẳng" không? Có - nếu mô hình bề mặt trái đất thành một hình cầu và sử dụng tọa độ địa tâm (x, y, z), thì hầu hết các tính toán của chúng tôi diễn ra theo ba chiều, trong đó các cạnh của hình tam giác là các mảnh của giao điểm của hình cầu với các mặt phẳng qua gốc của nó. Điều này làm cho việc tính toán nhanh chóng và dễ dàng.)


Tôi sẽ minh họa bằng cách hiển thị thủ tục trên một quãng tám của hình cầu; bảy quãng tám khác được xử lý theo cách tương tự. Một octant như vậy là một tam giác 90-90-90. Trong đồ họa của tôi, tôi sẽ vẽ các hình tam giác Euclide trải dài trên các góc giống nhau: chúng trông không đẹp cho đến khi chúng nhỏ lại, nhưng chúng có thể dễ dàng và nhanh chóng được vẽ. Đây là tam giác Euclide tương ứng với octant: đó là bắt đầu của thủ tục.

Hình 1

Vì tất cả các mặt có độ dài bằng nhau, một mặt được chọn ngẫu nhiên là "dài nhất" và được chia nhỏ:

Hình 2

Lặp lại điều này cho mỗi hình tam giác mới:

Hình 3

Sau n bước ta sẽ có 2 ^ n tam giác. Đây là tình huống sau 10 bước, hiển thị 1024 hình tam giác trong quãng tám (và 8192 trên tổng thể hình cầu):

hinh 4

Để minh họa thêm, tôi đã tạo một điểm ngẫu nhiên trong quãng tám này và đi trên cây phân khu cho đến khi cạnh dài nhất của tam giác đạt dưới 0,05 radian. Các tam giác (cartesian) được hiển thị với điểm thăm dò màu đỏ.

Hình 5

Ngẫu nhiên, để thu hẹp vị trí của một điểm đến một độ vĩ độ (xấp xỉ), bạn sẽ lưu ý rằng đây là khoảng 1/60 radian và do đó bao phủ khoảng (1/60) ^ 2 / (Pi / 2) = 1/6000 tổng bề mặt. Vì mỗi phân khu xấp xỉ một nửa kích thước tam giác, khoảng 13 đến 14 phân khu của octant sẽ thực hiện thủ thuật. Đó không phải là nhiều tính toán - như chúng ta sẽ thấy dưới đây - làm cho nó hiệu quả không phải là lưu trữ cây, mà là thực hiện phân chia một cách nhanh chóng. Lúc đầu, bạn sẽ lưu ý điểm nào nằm trong khoảng tám điểm - được xác định bởi các dấu của ba tọa độ của nó, có thể được ghi lại dưới dạng số nhị phân ba chữ số - và tại mỗi bước bạn muốn nhớ liệu điểm đó có nằm không ở bên trái (0) hoặc phải (1) của tam giác. Điều đó cho một số nhị phân 14 chữ số khác. Bạn có thể sử dụng các mã này để nhóm các điểm tùy ý.

(Nói chung, khi hai mã gần nhau là số nhị phân thực tế, các điểm tương ứng gần nhau; tuy nhiên, các điểm vẫn có thể gần nhau và có các mã khác nhau đáng kể. Ví dụ, hãy xem xét hai điểm cách nhau Xích đạo: mã của chúng phải khác nhau trước điểm nhị phân, bởi vì chúng ở các quãng tám khác nhau. Loại điều này là không thể tránh khỏi với bất kỳ phân vùng không gian cố định nào.)


Tôi đã sử dụng Mathicala 8 để thực hiện điều này: bạn có thể sử dụng nó như nguyên trạng hoặc mã giả để thực hiện trong môi trường lập trình yêu thích của bạn.

Xác định phía nào của mặt phẳng 0-ab điểm p nằm trên:

side[p_, {a_, b_}] := If[Det[{p, a, b}] >=  0, left, right];

Tinh chỉnh tam giác abc dựa trên điểm p.

refine[p_, {a_, b_, c_}] := Block[{sides, x, y, z, m},
  sides = Norm /@ {b - c, c - a, a - b} // N;
  {x, y, z} = RotateLeft[{a, b, c}, First[Position[sides, Max[sides]]] - 1];
  m = Normalize[Mean[{y, z}]];
  If[side[p, {x, m}] === right, {y, m, x}, {x, m, z}] 
  ]

Hình cuối cùng được vẽ bằng cách hiển thị octant và trên hết, bằng cách hiển thị danh sách sau đây dưới dạng một tập hợp đa giác:

p = Normalize@RandomReal[NormalDistribution[0, 1], 3]        (* Random point *)
{a, b, c} = IdentityMatrix[3] . DiagonalMatrix[Sign[p]] // N (* First octant *)
NestWhileList[refine[p, #] &, {a, b, c}, Norm[#[[1]] - #[[2]]] >= 0.05 &, 1, 16]

NestWhileListliên tục áp dụng một thao tác ( refine) trong khi một điều kiện liên quan (tam giác lớn) hoặc cho đến khi đạt được số lượng hoạt động tối đa (16).

Để hiển thị tam giác đầy đủ của octant, tôi bắt đầu với octant đầu tiên và lặp lại sàng lọc mười lần. Điều này bắt đầu với một sửa đổi nhỏ về refine:

split[{a_, b_, c_}] := Module[{sides, x, y, z, m},
  sides = Norm /@ {b - c, c - a, a - b} // N;
  {x, y, z} = RotateLeft[{a, b, c}, First[Position[sides, Max[sides]]] - 1];
  m = Normalize[Mean[{y, z}]];
  {{y, m, x}, {x, m, z}}
  ]

Sự khác biệt là splittrả về cả hai nửa của tam giác đầu vào của nó chứ không phải là một điểm trong đó một điểm đã cho nằm. Phép tính tam giác đầy đủ thu được bằng cách lặp lại điều này:

triangles = NestList[Flatten[split /@ #, 1] &, {IdentityMatrix[3] // N}, 10];

Để kiểm tra, tôi đã tính toán kích thước của mọi tam giác và xem xét phạm vi. .

Through[{Min, Max}[Map[Round[Det[#], 0.00001] &, triangles[[10]] // N, {1}]]]

{0,00523, 0,00739}

Do đó, kích thước thay đổi tăng hoặc giảm khoảng 25% so với mức trung bình của họ: điều đó có vẻ hợp lý để đạt được một cách thống nhất cho các điểm nhóm.

Khi quét mã này, bạn sẽ không nhận thấy lượng giác : nơi duy nhất cần thiết, nếu có, sẽ là chuyển đổi qua lại giữa tọa độ hình cầu và cartesian. Mã này cũng không chiếu bề mặt trái đất lên bất kỳ bản đồ nào, do đó tránh được các biến dạng của người phục vụ. Mặt khác, nó chỉ sử dụng trung bình ( Mean), Định lý Pythagore ( Norm) và định thức 3 by 3 ( Det) để thực hiện tất cả công việc. (Có một số lệnh thao tác danh sách đơn giản như RotateLeftFlatten, cùng với việc tìm kiếm cạnh dài nhất của mỗi tam giác.)


1

Đây là một điều khó khăn, vì các phép chiếu giới thiệu sự biến dạng khi đi từ hệ thống tọa độ địa lý 3D WGS84 sang hình chiếu 2D phẳng. Ở quy mô toàn cầu, bạn chắc chắn sẽ có những biến dạng ở đâu đó trong hệ thống.

Tôi nghĩ rằng đặt cược tốt nhất của bạn là chiếu vào phép chiếu Universal Transverse Mercator . Theo như tôi biết thì đây là lần gần nhất bạn có thể có được một phép chiếu toàn cầu với ít biến dạng nhất.

Nếu bạn có thể nới lỏng các yêu cầu mà các nhóm phải được xác định trong các khu vực có cùng kích thước cũng như yêu cầu xử lý thời gian thực, có các thuật toán phân cụm như DBSCAN và một nhóm các công cụ phái sinh, có thể giúp tạo ra các nhóm.


1
UTM không phải là "phép chiếu toàn cầu": minh chứng là hầu như bất kỳ cặp tọa độ hợp lệ nào, chẳng hạn như (500000, 5000000), tương ứng với ít nhất 120 điểm được phân tách rộng rãi trong hệ thống UTM. Và thật không may, các thuật toán phân cụm không đáp ứng nhu cầu của OP là có thể nhóm các điểm theo thời gian thực chỉ dựa trên vị trí của chúng (chứ không phải ở gần các điểm khác).
whuber

@whuber re: "chiếu toàn cầu" - đúng. Đó là lý do tại sao tôi nói "gần nhất bạn có thể đến dự phóng toàn cầu". Nếu bạn biết hệ thống trình chiếu tốt hơn phù hợp hơn, vui lòng để lại trong phần bình luận và tôi sẽ chỉnh sửa câu trả lời của tôi. Ngoài ra, OP không có yêu cầu thời gian thực trong bài viết ban đầu. Tôi sẽ chỉnh sửa câu trả lời của mình để tính đến điều này.
Sean Barbeau

Sean, (1) Giải pháp của tôi cho vấn đề trình chiếu toàn cầu là không sử dụng một. Có tồn tại không phép chiếu toàn cầu mà không dị. (2) Đúng, sự làm rõ thời gian thực xuất hiện trong một bình luận. Tuy nhiên, văn bản theo "ý tưởng đầu tiên của tôi" thực hiện tốt công việc, khi nhấn mạnh rằng vấn đề này là một trong việc phân vùng bề mặt trái đất thay vì phân cụm một tập hợp các vị trí. Đó là điểm mà tôi (không thực sự hiệu quả) đang cố gắng vượt qua trong nhận xét trước đây của tôi với bạn.
whuber
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.