ปัญหาคือการหาว่าโค้งงอมากแค่ไหนเพื่อเพิ่มความคมชัดของภาพ
นี่คือทางออกหนึ่ง (ในหลาย ๆ ที่เป็นไปได้) ลองพิจารณาส่วนโค้งทั้งหมดที่เปล่งออกมาจากจุดกำเนิดร่วม ส่วนโค้งแออัดมากที่สุดที่นี่ หากต้องการแยกพวกมันออกจากกันให้ดีที่สุดให้จัดเรียงมันเพื่อให้พวกมันกระจายออกไปในมุมที่เว้นระยะเท่ากัน มันเป็นปัญหาถ้าเราวาดส่วนของเส้นตรงจากจุดเริ่มต้นไปยังปลายทางเพราะโดยทั่วไปจะมีกลุ่มของจุดหมายปลายทางในทิศทางต่าง ๆ ลองใช้อิสรภาพของเราในการงอโค้งเพื่อให้พื้นที่ในมุมที่ออกไปเท่ากันให้มากที่สุด
เพื่อความเรียบง่ายลองใช้ส่วนโค้งเป็นวงกลมบนแผนที่ วัดตามธรรมชาติของ "โค้ง" ใน arc จากจุดYไปยังจุดxคือความแตกต่างระหว่างแบริ่งที่Yและแบริ่งโดยตรงจากYไปx ส่วนโค้งนี้เป็นส่วนของวงกลมที่yและxอยู่ทั้งคู่ เรขาคณิตเบื้องต้นแสดงให้เห็นว่ามุมดัดเท่ากับครึ่งหนึ่งของมุมรวมในส่วนโค้ง
เพื่ออธิบายอัลกอริทึมเราจำเป็นต้องมีสัญกรณ์เพิ่มเติมอีกเล็กน้อย ให้yเป็นจุดกำเนิด (ตามที่คาดไว้บนแผนที่) และให้x_1 , x_2 , ... , x_nเป็นจุดปลายทาง กำหนดÄ_iจะเป็นแบริ่งจากYไปx_i , ฉัน = 1, 2, ... , n
ขั้นตอนเบื้องต้นให้ถือว่าแบริ่ง (ทั้งหมดระหว่าง 0 ถึง 360 องศา) อยู่ในลำดับที่สูงขึ้น: สิ่งนี้ต้องการให้เราคำนวณแบริ่งแล้วเรียงลำดับ ทั้งสองเป็นงานที่ไม่ซับซ้อน
โดยหลักการแล้วเราต้องการให้ตลับลูกปืนของส่วนโค้งเท่ากับ 360 / n , 2 * 360 / nเป็นต้นเมื่อเทียบกับตลับลูกปืนเริ่มต้น ความแตกต่างระหว่างแบริ่งที่ต้องการและแบริ่งที่เกิดขึ้นจริงจึงเท่ากับฉัน * 360 / n - Ä_iบวกแบริ่งเริ่มต้นA0 ความแตกต่างที่ใหญ่ที่สุดคือค่าสูงสุดของความแตกต่างnเหล่านี้และความแตกต่างที่เล็กที่สุดคือค่าต่ำสุด ลองตั้งa0ให้อยู่กึ่งกลางระหว่างค่าสูงสุดและค่าต่ำสุด นี้เป็นผู้สมัครที่ดีสำหรับแบริ่งเริ่มต้นเพราะมันจะช่วยลดจำนวนเงินสูงสุดของการดัดที่จะเกิดขึ้น ดังนั้นกำหนด
b_i = i * 360 / n - a0 - a_i:
นี้เป็นดัดที่จะใช้
มันเป็นเรื่องของเรขาคณิตเบื้องต้นในการวาดส่วนโค้งวงกลมจากyถึงxที่รองรับมุม 2 b_i ดังนั้นฉันจะข้ามรายละเอียดและตรงไปที่ตัวอย่าง นี่คือภาพประกอบของวิธีแก้ปัญหาสำหรับ 64, 16 และ 4 จุดสุ่มที่อยู่ในแผนที่รูปสี่เหลี่ยมผืนผ้า
อย่างที่คุณเห็นโซลูชั่นดูเหมือนจะดีขึ้นเมื่อจำนวนจุดปลายทางเพิ่มขึ้น คำตอบสำหรับn = 4 แสดงให้เห็นอย่างชัดเจนว่าตลับลูกปืนมีระยะห่างเท่ากันอย่างไรในกรณีนี้ระยะห่างเท่ากับ 360/4 = 90 องศาและเห็นได้ชัดว่าระยะห่างนั้นทำได้อย่างแท้จริง
วิธีแก้ปัญหานี้ไม่สมบูรณ์แบบ: คุณอาจระบุอาร์คหลายอันที่สามารถปรับแต่งด้วยตนเองเพื่อปรับปรุงกราฟิก แต่มันจะไม่ทำงานที่แย่มากและดูเหมือนว่าเป็นการเริ่มต้นที่ดีจริงๆ
อัลกอริทึมยังมีข้อดีของความเรียบง่ายส่วนที่ซับซ้อนที่สุดประกอบด้วยการเรียงลำดับจุดหมายปลายทางตามแบริ่ง
การเข้ารหัส
ฉันไม่รู้ PostGIS แต่บางทีรหัสที่ฉันใช้ในการวาดตัวอย่างสามารถใช้เป็นแนวทางสำหรับการใช้อัลกอริทึมนี้ใน PostGIS (หรือ GIS อื่น ๆ )
พิจารณาสิ่งต่อไปนี้เป็น pseudocode (แต่Mathematicaจะใช้งานมัน :-) (หากเว็บไซต์นี้ได้รับการสนับสนุนเท็กซ์เป็นคณิตศาสตร์สถิติและคน TCS ทำผมสามารถทำให้เรื่องนี้เป็นจำนวนมากอ่านเพิ่มเติม.) สัญกรณ์รวมถึง:
- ชื่อตัวแปรและฟังก์ชั่นเป็นกรณี ๆ ไป
- [Alpha] เป็นตัวอักษรกรีกตัวพิมพ์เล็ก ([Pi] มีค่าที่คุณคิดว่าควรจะมี)
- x [[i]] เป็นองค์ประกอบ i ของอาร์เรย์ x (ดัชนีเริ่มต้นที่ 1)
- f [a, b] ใช้ฟังก์ชัน f กับอาร์กิวเมนต์ a และ b ฟังก์ชันในกรณีที่เหมาะสมเช่น 'Min' และ 'Table' ถูกกำหนดโดยระบบ ฟังก์ชั่นที่มีตัวอักษรตัวพิมพ์เล็กเริ่มต้นเช่น 'มุม' และ 'ออฟเซ็ต' เป็นแบบที่ผู้ใช้กำหนด ความคิดเห็นอธิบายถึงฟังก์ชั่นของระบบที่คลุมเครือ (เช่น 'Arg')
- ตาราง [f [i], {i, 1, n}] สร้างอาร์เรย์ {f [1], f [2], ... , f [n]}
- Circle [o, r, {a, b}] สร้างส่วนโค้งของวงกลมที่ศูนย์กลางที่ o ของรัศมี r จากมุม a ถึงมุม b (ทั้งในเรเดียนทวนเข็มนาฬิกาจากตะวันออก)
- การสั่งซื้อ [x] จะส่งคืนอาร์เรย์ของดัชนีขององค์ประกอบที่เรียงลำดับของ x x [[การสั่งซื้อ [x]]] เป็นรุ่นที่เรียงลำดับของ x เมื่อ y มีความยาวเท่ากับ x, y [[การสั่งซื้อ [x]]] เรียงลำดับ y พร้อมกับ x
ส่วนที่ปฏิบัติการได้ของโค้ดสั้นอย่างมีเมตตา - น้อยกว่า 20 บรรทัด - เพราะครึ่งหนึ่งของรหัสนั้นเป็นค่าใช้จ่ายที่เปิดเผยหรือความคิดเห็น
วาดแผนที่
z
เป็นรายการของปลายทางและy
เป็นจุดเริ่มต้น
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}]
}]
]
สร้างส่วนโค้งแบบวงกลมจากจุดหนึ่งx
ไปอีกจุดหนึ่งโดยy
เริ่มจากมุมที่\[Beta]
สัมพันธ์กับ 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}]
]
คำนวณตลับลูกปืนจากจุดเริ่มต้นไปยังรายการคะแนน
angles[origin_, x_] := Arg[Complex@@(#-origin)] & /@ x;
คำนวณระดับกลางของส่วนที่เหลือของชุดตลับลูกปืน
x
เป็นรายการของแบริ่งในการเรียงลำดับ อุดมคติแล้ว 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
]