Làm thế nào để tìm một nửa điểm giữa hai điểm khác?


8

Tôi đang làm việc để triển khai định dạng nhị phân OSM Mobile cho dữ liệu bản đồ và vì nó sử dụng delta 16 bit cho mỗi điểm trên đường đi, nên nó không thể biểu thị một cách nếu có khoảng cách lớn giữa hai điểm.

Giải pháp được ghi nhận là đưa các điểm mới vào đường đi, để giữ cho khoảng cách nhỏ hơn.

Đây là phần có liên quan trong mã của tôi:

// calculate the distance between this point and the previous point,
// multiplied by 1,000,000 so it can be represented as an integer.
int32_t realNodeLatDelta = ((point.latitude - lastPoint.latitude) * 1000000);
int32_t realNodeLonDelta = ((point.longitude - lastPoint.longitude) * 1000000);

// cast as a 16 bit int (reduces filesize by about half)
int16_t nodeLatDelta = realNodeLatDiff;
int16_t nodeLonDelta = realNodeLonDiff;

// check if the cast caused corruption
if (realNodeLatDelta != nodeLatDelta || realNodeLatDelta != nodeLatDelta) {
  // if this point is reached, we need to add new points in the way,
  // which can be represented in a 16 bit delta
}

Tôi không chắc làm thế nào để tính toán vị trí của các điểm mới trên đường đi? Tôi cho rằng nó cần phải là một vòng tròn lớn?

Các điểm cách nhau đủ xa để gây ra vấn đề này là rất hiếm, nhưng khi chúng xảy ra, nó thường là một ranh giới chính trị hoặc tương tự, có xu hướng khá dài và cần được trình bày chính xác.


Tôi đề nghị đặt câu hỏi này trong danh sách gửi thư OSM-dev ( list.openstreetmap.org/listinfo/dev ), nó hơi quá cụ thể đối với một diễn đàn GIS nói chung.
Igor Brejc

1
Chắc chắn toán học để tìm một nửa điểm giữa hai điểm khác không phải là rất cụ thể?
Abhi Beckert

Không, nhưng có thể có nhiều cách khác để xử lý vấn đề này, đó là định dạng cụ thể.
Igor Brejc

Không có bất kỳ phương pháp thay thế nào để đối phó với nó. Số nguyên 16 bit là định dạng duy nhất được phép cho các điểm theo cách và (ở 6 vị trí chính xác thập phân), số nguyên 16 bit chỉ có khả năng biểu thị sự khác biệt khoảng 3,5km giữa hai điểm. Thay thế duy nhất là không sử dụng định dạng đó (đó là giải pháp tạm thời của tôi). Nhưng tôi muốn sử dụng một cái gì đó tiêu chuẩn nếu có thể.
Abhi Beckert

1
Tôi nghĩ rằng bạn có thể đi theo một trật tự lớn: khoảng cách dài nhất bạn có thể tìm thấy trên trái đất là khoảng 20.000 km. Với 16 bit, có nghĩa là chính xác đến 300m.
whuber

Câu trả lời:


13

Độ chính xác tốt nhất thu được với các mô hình ellipsoidal. Vì lợi ích của sự đơn giản, bạn muốn tránh những điều đó khi bạn phải tự viết mã khoảng cách. Chúng tôi phải trả giá: cho rằng độ phẳng của trái đất là khoảng 1/300, sử dụng mô hình hình cầu hoàn toàn có khả năng gây ra lỗi khoảng cách tương đối lên tới 1/300 cho các tuyến đường rất dài: khoảng 3000 phần triệu. Đây là giá trị khám phá.

Đầu tiên, công thức hình cầu : chỉ cần chuyển đổi (lat, lon) sang tọa độ cartesian, lấy trung bình hai điểm cartesian, sau đó chuyển đổi trung bình trở lại tọa độ hình cầu. Đây là mã giả:

function cartesian(f,l) { // f = latitude, l = longitude
    return (cos(f)*cos(l), cos(f)*sin(l), sin(f))
}
function spherical(x,y,z) {
    r = sqrt(x^2 + y^2)
    if (r == 0) {
        if (z > 0) return (90, 0) 
        elseif (z < 0) return (-90, 0)
        else return Undefined // (x,y,z) == (0,0,0)
    } else {
        return (atan2(r, z), atan2(x, y)) // atan2 must return *degrees*
    }
}
function midpoint(f0,l0, f1,l1) { 
    return spherical((cartesian(f0,l0) + cartesian(f1,l1))/2)
}

(Số học cho midpointliên quan đến tổng vectơphép chia vô hướng của tổng đó, vì vậy nó thực sự ẩn ba tổng và ba phép chia.)

Đó là trung điểm trong hình học hình cầu. Việc tính toán đòi hỏi hai cosin, hai sin, một căn bậc hai, hai arctang và một số phép nhân và phép cộng: khá nhanh và dễ dàng. Sẽ không có vấn đề nào ở gần các cực hoặc vượt qua kinh tuyến + -180. Kết quả sẽ không được xác định khi hai điểm đối diện nhau.

Một cách để đo lỗi là tính khoảng cách tăng đi qua điểm giữa so với khoảng cách giữa các điểm ban đầu. Nếu mức tăng nhỏ so với khoảng cách ban đầu, chúng ta không có gì phải phàn nàn. Tôi đã tính toán các lỗi này bằng cách sử dụng khoảng cách ellipsoidal chính xác cho ellipsoid WGS84. Như một ví dụ điển hình về kết quả, đây là một chuỗi các lỗi tương đối khi một trong các điểm cuối được sửa tại (lat, lon) = (45, 0):

Lỗi tương đối

Các đường viền nằm trên thang đo logarit (cơ sở 10): các đường viền -6 hiển thị các điểm trong đó sai số tương đối là 10 ^ (- 6); đó là, một phần triệu (ppm). Các đường viền -5 (hầu như không nhìn thấy gần (-45, 180), điểm đối diện đường kính) là 10 ppm. -7, -8, v.v. là các phân số của ppm: độ chính xác cao.

Rõ ràng, miễn là chúng ta không cố gắng tính trung điểm của hai điểm gần như đối lập nhau, chúng ta sẽ làm tốt. (Hãy nhớ rằng, phép tính là hoàn toàn chính xác cho hình cầu; những lỗi này là do sự làm phẳng của hình cầu.)

Cho rằng độ chính xác 16 bit là khoảng 16 ppm (một bản ghi cơ sở 10 bằng -4,8), có thể sử dụng công thức hình cầu để tìm điểm giữa với điều kiện hai điểm cách xa nhau hơn một độ so với đối xứng.

Điều gì về công thức tuyến tính đơn giản hơn? Để nghiên cứu điều này, hãy so sánh khoảng cách giữa điểm giữa tuyến tính (thu được bằng cách lấy trung bình hai vĩ độ và hai kinh độ) với trung điểm hình cầu, so với khoảng cách giữa hai điểm cuối. Hình tiếp theo sửa một điểm cuối tại (45, 180) và khám phá một vùng tương đối nhỏ xung quanh nó.

Lỗi tương đối 2

Hầu hết các đường viền này (logarit cơ sở 10 một lần nữa) gần -2: đó là một phần trăm (1%) lỗi. Đối với các hướng bắc-nam không có lỗi, nhưng đối với tất cả các hướng khác , lỗi không thể chấp nhận được đối với nhiều ứng dụng .

Để xem liệu xấp xỉ tuyến tính bao giờ trở nên OK, chúng ta hãy phóng to lên rằng bản đồ trước đó bởi một nhân tố của 10. Bây giờ nó là rộng một mức độ (50 dặm ở vĩ độ này) và một nửa độ qua (35 dặm): chúng tôi đang tìm kiếm ở quy mô của một thành phố lớn hoặc một thành phố nhỏ và vùng ngoại ô của nó.

Bây giờ các đường viền là khoảng -3 đến -4: đó là 100 đến 1000 phần triệu (0,01% đến 0,1%). Khá thô và hầu như không đáng chú ý trên màn hình máy tính độ phân giải cao nếu bạn nhìn kỹ.

Lỗi tương đối 3

Nhìn lại, rõ ràng là công thức hình cầu hơi phức tạp hơn một chút - nhưng vẫn dễ thực hiện - đạt được độ chính xác cao hơn trên toàn cầu so với công thức tuyến tính đơn giản ngay cả ở các địa điểm gần đó. (Tôi hơi khó hiểu một chút, vì tôi đã sử dụng hai cách khác nhau để đo lỗi, vì vậy chúng không thể so sánh trực tiếp được.)

Điểm mấu chốt:

- Công thức tuyến tính sẽ sử dụng sai điểm giữa bởi sai số tương đối từ 0,01% đến 0,1% ở quy mô thành phố; trên các khu vực rộng lớn hơn, việc sử dụng sai mục đích có thể rất sai (1% trên tới hàng trăm%).

- Công thức hình cầu hoàn toàn chính xác cho mô hình trái đất hình cầu. So với công thức ellipsoidal chính xác hơn, nó vẫn nên làm tốt ngoại trừ các điểm gần như ngược chiều.


1
Ồ cảm ơn nhé! Đó là một số thông tin thực sự tốt. Tôi không cần độ chính xác hoàn hảo, đó chỉ là một ứng dụng iPhone để sử dụng GPS cá nhân, chủ yếu chỉ tập trung trên đường phố. Vì đường cao tốc không hoàn toàn thẳng cho hàng trăm km, ngay cả độ chính xác tuyến tính là "đủ tốt". Nhưng ranh giới chính trị thường thẳng và dài (phía bên phải của Tây Úc là 1.800km). Công thức hình cầu nên hoàn hảo cho điều đó. Tôi ước tôi có thể cho bạn một tiền thưởng cho câu trả lời của bạn, bạn xứng đáng với điều đó.
Abhi Beckert

8

Giải pháp của bạn hoạt động trong khoảng cách nhỏ, nhưng nó sẽ không hiệu quả với những giải pháp lớn hơn. Cách dễ nhất để xem tại sao là nhìn vào bản đồ sau (lấy từ đây ):

nhập mô tả hình ảnh ở đây

Đây là một bản đồ thế giới trong phép chiếu tương đương - kinh độ và vĩ độ được chiếu tuyến tính đơn giản vào các trục X và Y. Toán học của bạn có thể được đại diện bởi hình chữ nhật màu xanh . Tuy nhiên, đường chéo màu xanh không biểu thị "đường thẳng" ngắn nhất giữa hai điểm trên bề mặt Trái đất. Những gì bạn cần là một vòng tròn lớn (đại diện bởi đường cong màu đen ).

Mặc dù bạn đang sử dụng C ++, tôi khuyên bạn nên xem Thư viện C # Geodesy của Mike Gavaghan , đây là nguồn mở và mã có chất lượng cao, bạn sẽ có thể tìm ra cách thực hiện phép tính dọc theo vòng tròn lớn. Bạn cũng có thể xem công thức của Vincenty nếu bạn quan tâm đến toán học đằng sau phép tính.


Cảm ơn! Đó chính xác là những gì tôi đang tìm kiếm. Mã của Mike Gavaghan có vẻ dễ dàng chuyển sang C (tôi thực sự đang sử dụng Objective-C btw). Tôi khá chắc chắn rằng toán học tuyến tính của tôi sẽ thoát ra, nhưng cần phải có một cái gì đó.
Abhi Beckert

-1

Toán tuyến tính đơn giản dường như hoạt động tốt:

double newLat = lastCoord.latitude + ((coord.latitude - lastCoord.latitude) / 2);
double newLon = lastCoord.longitude + ((coord.longitude - lastCoord.longitude) / 2);

Tôi đang đệ quy chèn một nửa điểm mới vào mỗi phần của con đường quá lớn, cho đến khi tất cả chúng đều đủ nhỏ.

Tôi không chắc liệu toán học phức tạp hơn có cần thiết cho khoảng cách lớn hơn không (có ai có thể xác nhận điều này cho tôi không?), Nhưng nó hoạt động tốt trên cái này (khoảng 5km):

ví dụ về đường thẳng dài giữa các điểm

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.