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ả y và x đề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
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 đồ
z
là một danh sách các điểm đến và y
là 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 y
bắ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.
x
là 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
]