Bản đồ đường cong điểm-điểm-điểm


39

Gần đây tôi đã xem xét các trang web của các hãng hàng không hiển thị các tuyến đường của họ khởi hành từ một thành phố nhất định đến tất cả các thành phố khác mà họ phục vụ. Tôi muốn có thể tạo các tuyến đường cong tương tự giữa các điểm. Có ai đã tạo các tập lệnh hoặc hàm sẽ tạo ra các cung cong như những gì được hiển thị trong ví dụ này chưa?

Đường bay

Trong PostGIS, có triển khai ST_MakeLine cho phép bạn chỉ định lượng đường cong sẽ sử dụng khi kết nối 2 điểm không?

Mặc dù hiện tại tôi đang sử dụng PostGIS và QGIS, tôi rất vui khi nghe về các tùy chọn phần mềm khác có thể tạo giao diện tương tự.


Bất cứ ai cũng biết về bất kỳ triển khai tốt đẹp này? Ví dụ hay gì?
Đánh dấu Boulder

Câu trả lời:


26

Tạo các vòng tròn lớn có thể mang lại cho bạn hiệu quả mong muốn.

Có lẽ một cái gì đó giống như được thảo luận trên http://lists.osgeo.org/pipermail/postgis-users/2008-F/2/018620.html

Cập nhật:

Tôi đã tiếp tục ý tưởng này trong "Trực quan hóa các kết nối toàn cầu" . Đó là một giải pháp hoàn toàn dựa trên PostGIS bằng cách sử dụng từ chối để tạo vòng cung.

SELECT ST_Transform(
  ST_Segmentize(
    ST_MakeLine(
      ST_Transform(a.the_geom, 953027),
      ST_Transform(b.the_geom, 953027)
    ), 
  100000), 
4326)

(Định nghĩa CRS cho 953027 có thể được tìm thấy ở đây: http://spatialreference.org/ref/esri/53027/ )

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


4
Tôi thích ý tưởng này, mặc dù với những vòng tròn lớn, vấn đề bạn gặp phải là ở khoảng cách ngắn hơn, bạn vẫn sẽ kết thúc bằng một đường thẳng nói chung. Tôi muốn có thể kiểm soát số lượng cung mà tôi đặt trong dòng (ví dụ: arclength = distance * 2).
RyanDalton

1
Dưới đây là một ví dụ điển hình cho vấn đề chỉ đơn giản bằng cách sử dụng các vòng kết nối tuyệt vời: gc.kls2.com/cgi-bin/ mẹo
RyanDalton

1
Sau một số nghiên cứu bổ sung, tôi thấy bài đăng này có thể hữu ích trong việc hỗ trợ phương pháp này. mail-archive.com/postgis-users@postgis.refraction.net/,
RyanDalton

Để sử dụng cho người đọc trong tương lai, tôi nghĩ rằng tôi sẽ tiếp tục và liên kết đến bài đăng blog gần đây của @ underdark bao gồm chủ đề này. underdark.wordpress.com/2011/08/20/...
RyanDalton

Thật tuyệt!! Được sử dụng trong dự án của tôi để vẽ các đường giữa đăng ký người dùng và địa điểm địa điểm, được chọn từ Forsapes
Lorenzo Barbagli

24

Vấn đề là tìm ra mức độ uốn cong các cung để tăng cường độ phân giải hình ảnh của chúng.

Đây là một giải pháp (trong số rất nhiều có thể). Chúng ta hãy xem xét tất cả các cung phát ra từ một nguồn gốc chung. Các cung được đông đúc nhất ở đây. Để phân tách chúng tốt nhất, chúng ta hãy sắp xếp nó sao cho chúng trải đều theo các góc cách đều nhau . Đó là một vấn đề nếu chúng ta vẽ các đoạn thẳng từ điểm gốc đến điểm đến, bởi vì thông thường sẽ có các cụm điểm đến theo nhiều hướng khác nhau. Chúng ta hãy sử dụng sự tự do của chúng ta để uốn cong các cung để không gian các góc khởi hành càng đều càng tốt.

Để đơn giản, hãy sử dụng các cung tròn trên bản đồ. Một thước đo tự nhiên của "uốn cong" trong một cung từ điểm y đến điểm x là sự khác biệt giữa ổ đỡ của nó tại y và ổ trục trực tiếp từ y đến x . Một cung như vậy là một khu vực của một vòng tròn mà cả yx đều nằm; hình học cơ bản cho thấy góc uốn bằng một nửa góc bao gồm trong cung.

Để mô tả một thuật toán, chúng ta cần thêm một chút ký hiệu. Đặt y là điểm gốc (như được chiếu trên bản đồ) và đặt x_1 , x_2 , ..., x_n là các điểm đích. Xác định a_i là ổ đỡ từ y đến x_i , i = 1, 2, ..., n .

Bước đầu tiên, giả sử vòng bi (tất cả trong khoảng từ 0 đến 360 độ) theo thứ tự tăng dần: điều này đòi hỏi chúng ta phải tính toán vòng bi và sau đó sắp xếp chúng; cả hai đều là nhiệm vụ đơn giản.

Lý tưởng nhất, chúng tôi muốn các vòng bi của vòng cung bằng 360 / n , 2 * 360 / n , v.v., liên quan đến một số vòng bi bắt đầu. Do đó, sự khác biệt giữa vòng bi mong muốn và vòng bi thực tế do đó bằng i * 360 / n - a_i cộng với vòng bi bắt đầu, a0 . Sự khác biệt lớn nhất là tối đa của n sự khác biệt này và sự khác biệt nhỏ nhất là mức tối thiểu của chúng. Hãy đặt a0 là nửa chừng giữa cực đại và cực tiểu; đây là một ứng cử viên tốt cho ổ trục khởi động vì nó giảm thiểu tối đa lượng uốn sẽ xảy ra . Do đó, xác định

b_i = i * 360 / n - a0 - a_i:

Đây là uốn để sử dụng .

Vấn đề về hình học cơ bản là vẽ một cung tròn từ y đến x có phụ một góc 2 b_i, vì vậy tôi sẽ bỏ qua các chi tiết và đi thẳng vào một ví dụ. Dưới đây là minh họa về các giải pháp cho 64, 16 và 4 điểm ngẫu nhiên được đặt trong bản đồ hình chữ nhật

văn bản thay thế

văn bản thay thế

văn bản thay thế

Như bạn có thể thấy, các giải pháp dường như trở nên đẹp hơn khi số lượng điểm đến tăng lên. Giải pháp cho n = 4 cho thấy rõ ràng cách các vòng bi cách đều nhau, vì trong trường hợp này, khoảng cách bằng 360/4 = 90 độ và rõ ràng khoảng cách đó đã đạt được chính xác.

Giải pháp này không hoàn hảo: bạn có thể xác định một số cung có thể được điều chỉnh thủ công để cải thiện đồ họa. Nhưng nó sẽ không làm một công việc tồi tệ và dường như là một khởi đầu thực sự tốt.

Thuật toán cũng có ưu điểm là đơn giản: phần phức tạp nhất bao gồm sắp xếp các điểm đến theo vòng bi của chúng.


Mã hóa

Tôi không biết PostGIS, nhưng có lẽ mã tôi đã sử dụng để vẽ các ví dụ có thể đóng vai trò là một hướng dẫn để thực hiện thuật toán này trong PostGIS (hoặc bất kỳ GIS nào khác).

Hãy coi những điều sau đây là mã giả (nhưng Mathicala sẽ thực thi nó :-). (Nếu trang web này hỗ trợ TeX, như toán học, thống kê, và những người TCS làm, tôi có thể làm điều này một nhiều dễ đọc hơn.) Các ký hiệu bao gồm:

  • Tên biến và hàm là trường hợp nhạy cảm.
  • [Alpha] là một nhân vật Hy Lạp viết thường. ([Pi] có giá trị mà bạn nghĩ nó nên có.)
  • x [[i]] là phần tử i của một mảng x (được lập chỉ mục bắt đầu từ 1).
  • f [a, b] áp dụng hàm f cho các đối số a và b. Các hàm trong trường hợp thích hợp, như 'Min' và 'Bảng', được xác định theo hệ thống; các hàm có chữ in thường ban đầu, như 'góc' và 'offset', do người dùng xác định. Nhận xét giải thích mọi chức năng hệ thống tối nghĩa (như 'Arg').
  • Bảng [f [i], {i, 1, n}] tạo mảng {f [1], f [2], ..., f [n]}.
  • Vòng tròn [o, r, {a, b}] tạo ra một vòng cung của đường tròn có tâm tại o bán kính r từ góc a đến góc b (cả hai đều theo radian ngược chiều kim đồng hồ từ hướng đông).
  • Sắp xếp [x] trả về một mảng các chỉ mục của các phần tử được sắp xếp của x. x [[Đặt hàng [x]]] là phiên bản được sắp xếp của x. Khi y có cùng độ dài với x, y [[Sắp xếp [x]]] sắp xếp y song song với x.

Phần thực thi của mã rất ngắn gọn - dưới 20 dòng - bởi vì hơn một nửa trong số đó là chi phí khai báo hoặc bình luận.

Vẽ bản đồ

zlà một danh sách các điểm đến và ylà nguồn gốc.

circleMap[z_List, y_] := 
Module[{\[Alpha] = angles[y,z], \[Beta], \[Delta], n},
    (* Sort the destinations by bearing *)
    \[Beta] = Ordering[\[Alpha]];
    x = z[[\[Beta] ]]; (* Destinations, sorted by bearing from y *)
    \[Alpha] = \[Alpha][[\[Beta]]]; (* Bearings, in sorted order *)
    \[Delta] = offset[\[Alpha]];
    n = Length[\[Alpha]];
    Graphics[{(* Draw the lines *)
        Gray, Table[circle[y, x[[i]],2 \[Pi] i / n + \[Delta] - \[Alpha][[i]]], 
             {i, 1, Length[\[Alpha]]}],
        (* Draw the destination points *)
        Red, PointSize[0.02], Table[Point[u], {u, x}]
    }]
]

Tạo một cung tròn từ điểm này xđến điểm khác ybắt đầu từ góc \[Beta]so với góc mang x -> y.

circle[x_, y_, \[Beta]_] /; -\[Pi] < \[Beta] < \[Pi] := 
Module[{v,  \[Rho], r, o, \[Theta], sign},
    If[\[Beta]==0, Return[Line[{x,y}]]];

    (* Obtain the vector from x to y in polar coordinates. *)
    v = y - x; (* Vector from x to y *)
    \[Rho] = Norm[v]; (* Length of v *)
    \[Theta] = Arg[Complex @@ v]; (* Bearing from x to y *)

    (* Compute the radius and center of the circle.*)
    r = \[Rho] / (2 Sin[\[Beta]]); (* Circle radius, up to sign *)
    If[r < 0, sign = \[Pi], sign = 0];
    o = (x+y)/2 + (r/\[Rho]) Cos[\[Beta]]{v[[2]], -v[[1]]}; (* Circle center *)

    (* Create a sector of the circle. *)
    Circle[o, Abs[r], {\[Pi]/2 - \[Beta] + \[Theta] + sign, \[Pi] /2 + \[Beta] + \[Theta] + sign}]
]

Tính toán các vòng bi từ một điểm gốc đến một danh sách các điểm.

angles[origin_, x_] := Arg[Complex@@(#-origin)] & /@ x;

Tính toán giữa của phần dư của một bộ vòng bi.

xlà một danh sách các vòng bi theo thứ tự sắp xếp. Lý tưởng nhất là x [[i]] ~ 2 [Pi] i / n.

offset[x_List] :=
Module[
    {n = Length[x], y},
    (* Compute the residuals. *)
    y = Table[x[[i]] - 2 \[Pi] i / n, {i, 1, n}];
    (* Return their midrange. *)
    (Max[y] + Min[y])/2
]

Tôi nên đề cập rằng giải pháp này giả định các điểm đến ít nhiều bao quanh nguồn gốc. Khi đây không phải là trường hợp, toàn bộ ý tưởng (của vòng bi cách đều nhau) không phải là một ý tưởng tốt. Nhưng nó có thể dễ dàng được sửa chữa bằng cách giới thiệu một số điểm đến giả trong các khoảng trống góc và sau đó loại bỏ các điểm đến đó (và cung của chúng). Quá trình này có thể được tự động bằng cách tính khoảng cách trung bình giữa vòng bi và sử dụng rằng để xác định các lỗ hổng lớn, vv .
whuber

Đồ họa đẹp. Tôi tự hỏi nếu các hãng hàng không sử dụng một công cụ tự động khi họ vẽ các bản đồ đường bay được hiển thị ở mặt sau của tạp chí trên chuyến bay của họ.
Kirk Kuykendall

1
@Kirk Họ có thể trả tiền cho ai đó để làm bản đồ theo cách thủ công :-). Tôi đã được truyền cảm hứng bởi câu hỏi này để xem liệu một cách tiếp cận đơn giản có thể tạo ra đồ họa hợp lý tốt hay không. Câu trả lời có vẻ hứa hẹn. Nhân tiện, những đồ họa này được Mathicala 8 tạo ra bằng cách sử dụng các nguyên hàm CirclePoint và một số học vectơ nhỏ để tìm các tâm vòng tròn.
whuber

Tôi thích kết quả mà bạn đã thể hiện và tôi đây là con đường để đi. Mặc dù vậy, tôi sẽ thành thật, tôi tự coi mình là kỹ thuật nhưng tôi đã bị mất một chút trong công thức bạn đưa ra và làm thế nào để biến nó thành mã PostGIS do đó trở nên gần như không thể. Bất cứ ai ở ngoài đó có bất kỳ ý tưởng nào về cách dịch khái niệm whuber thành mã khả thi? Tôi sẽ cố gắng xem xét và cho nó đi, nhưng sự giúp đỡ sẽ được đánh giá rất cao.
RyanDalton

@ whuber- Cảm ơn vì mã giả đã cập nhật. Chúng ta sẽ phải xem liệu chúng ta có thực sự triển khai nó trong PostGIS hay không.
RyanDalton

5

Hãy thử ST_CurveToLine

Một cái gì đó như ví dụ:

SELECT ST_CurveToLine('CIRCULARSTRING(1 1,5 3,10 1)'::geometry) as the_geom;

Bạn có thể hình dung điều này bằng cách đối phó truy vấn vào hộp văn bản và nhấn Map1 tại http://www.postgisonline.org/map.php


Cuối cùng tôi đã thử điều này để tạo ra một chuỗi các linestrings "hai điểm".
Brent Edwards


3

Cuối cùng tôi đã thử điều này để tạo ra một chuỗi các linestrings "hai điểm" bằng cách sử dụng hàm ST_CurveToLine theo đề xuất của @Nicklas Avén.

Tôi đã chuyển 3 bộ tọa độ sau cho hàm ST_ OffersetCurve:

  1. Bắt đầu của dòng ban đầu
  2. Điểm giữa của đường thẳng song song với đường ban đầu
  3. Kết thúc dòng gốc

Tôi đã sử dụng hàm ST_ OffersetCurve để tính toán phần bù - 1/10 chiều dài của dòng ban đầu trong ví dụ của tôi.

Đây là SQL tôi đã sử dụng để tạo các đường cong từ các đường thẳng ban đầu:

    ST_CurveToLine('CIRCULARSTRING(' || st_x(st_startpoint(the_geom)) || ' ' || st_y(st_startpoint(the_geom)) || ', ' || st_x(st_centroid(ST_OffsetCurve(the_geom, st_length(the_geom)/10, 'quad_segs=4 join=bevel'))) || ' ' || st_y(st_centroid(ST_OffsetCurve(the_geom, st_length(the_geom)/10, 'quad_segs=4 join=bevel'))) || ', ' || st_x(st_endpoint(the_geom)) || ' ' ||  st_y(st_endpoint(the_geom)) || ')') AS the_curved_geom

Thực sự hữu ích, nhưng vì một số lý do, kết quả không tôn trọng srid của tôi. Bất cứ ý tưởng tại sao?
DMS02

Bạn có thể cung cấp thêm một số chi tiết - srid của hình học đầu vào, srid đầu ra bị thiếu, là khác nhau, lỗi được tạo ra (ứng dụng nào - QGIS, PostgreQuery).
Brent Edwards

Bảng mà tôi muốn chèn các đường cong kết quả có ràng buộc cưỡng chế. Khi tôi thực hiện truy vấn, tôi gặp lỗi khi truy vấn này vi phạm ràng buộc đó. Với một bảng không có ràng buộc đó, nó hoạt động nhưng sau đó khi thêm nó vào QGIS, nó được liệt kê bằng srid 0. Truy vấn của tôi: Kiểm tra INSERT INTO (the_curved_geom) CHỌN [ở đây SQL của bạn] TỪ các dòng
DMS02

Hãy thử chạy các hàm postgis.net/docs/ST_GeometryType.htmlpostgis.net/docs/ST_SRID.html trên cột hình học (the_curved_geom) và kiểm tra xem có xung đột với bảng thử nghiệm của bạn không và có thực thi hay không. Nếu vậy, bạn có thể chuyển đổi hình học / srid khi cần hoặc sửa đổi bảng kiểm tra / ràng buộc của bạn.
Brent Edwards
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.