Introduction
In this page, I describe a brief explanation on the algorithm of the 2-dimensional convex hull upon which I touched in the previous page. I also show you my implementation of it in C++.Algorithm
The algorithm discussed here is called the Incremental Method which has the complexity of $O(n\log{n})$ 1.Input: A sequence of points, $A=\{P_1,P_2,\cdots,P_n\}$ (We call the suffixes the original numbers)
Output: Convex Hull, $C(A)$
- Arrange points in ascending order of $x$-coordinate values. We write the resultant sequence as $A^{\prime}=\{P_{(1)},P_{(2)},\cdots,P_{(n)}\}$ and call the suffixes the sorted numbers. When two points have the same $x$-coordinate value, we arrange them in descending order of the original numbers. We store the table $T_{{\rm sorted}\rightarrow{\rm original}}$ that maps the sorted number to the original one.
- Make a triangle consisting of the first three points of $A^{\prime}$ and write it as $C(\{P_{(1)},P_{(2)},P_{(3)}\})$. Store two arrays $V_{\rm clockwise}$ and $V_{\rm counterclockwise}$ that allow us to follow points in clockwise order and counterclockwise order, respectively. For instance, if the sorted number $a$ is followed by $b$ when we trace the points in clockwise order, $V_{\rm clockwise}(a)=b$ holds.
- Add points sequentially from $(3)$ to $(n)$. Every time a point is inserted, the algorithm $X$ that is discussed later is executed.
- Finally we obtain the output $C(\{P_{(1)},P_{(2)},\cdots,P_{(n)}\})$. The sequence of points obtained by $V_{\rm clockwise}$ or $V_{\rm counterclockwise}$ provides the convex hull to us.
Let us turn to the algorithm $X$.
Input:$C(\{P_{(1)},P_{(2)}, \cdots,P_{(k)}\})$, $P_{(k+1)}$, $V_{\rm clockwise}$, $V_{\rm counterclockwise}$, $T_{{\rm sorted}\rightarrow{\rm original}}$
Output:$C(\{P_{(1)},P_{(2)},\cdots,P_{(k+1)}\})$, $V_{\rm clockwise}$, $V_{\rm counterclockwise}$
- $P_{(s)}\leftarrow P_{(k)}$
- Consider three points, $P_{(k+1)}$, $P_{(s)}$, and $P_{(t)}$, where $t=V_{\rm counterclockwise}(s)$.
- Trace these points in this order. If the path turns right at $P_{(s)}$, return to step 2 after setting $s\leftarrow t$. Otherwise return to step 4. See the figure below.
- Store the sorted number $(u)$ of the point at which the path turns left.
- $P_{(s)}\leftarrow P_{(k)}$
- Consider three points, $P_{(k+1)}$, $P_{(s)}$, and $P_{(t)}$, where $t=V_{\rm clockwise}(s)$.
- Trace these points in this order. If the path turns left at $P_{(s)}$, return to step 6 after setting $s\leftarrow t$. Otherwise return to step 8.
- Store the sorted number $(l)$ of the point at which the path turns right.
- Set $V_{\rm counterclockwise}(l)=k+1$ and $V_{\rm counterclockwise}(k+1)=u$.
- Set $V_{\rm clockwise}(u)=k+1$ and $V_{\rm clockwise}(k+1)=l$.
In order to determine if the path turns left or right, the determinant $F$ as shown in the previous page is used.
- Consider $F(P_{(i)},P_{(j)},P_{(k)})$.
- Convert the sorted numbers to the original ones using $T_{{\rm sorted}\rightarrow{\rm original}}$. \begin{eqnarray} a&=&T_{{\rm sorted}\rightarrow{\rm original}}(i) \nonumber \\ b&=&T_{{\rm sorted}\rightarrow{\rm original}}(j) \nonumber \\ c&=&T_{{\rm sorted}\rightarrow{\rm original}}(k) \nonumber \end{eqnarray}
- Arrange the elements of the list $L=(a,b,c)$ in descending order to generate a new list $L^{\prime}=(a^{\prime},b^{\prime},c^{\prime})$. If the conversion is done with an odd permutation, $p=-1$. Otherwise $p=1$.
- Calculate the value of $F(P_{a^{\prime}},P_{b^{\prime}},P_{c^{\prime}})$. Multiply its sign by $p$ to obtain the sign of $F(P_{a},P_{b},P_{c})$. If it is positive, the path turns left, otherwise turns right.
Implementation in C++
Here is my source code.The functionmain
is as follows:
- the 16th-39th lines: The input points are randomly generated.
- the 43th line: An object of the template class
ConvexHull2d
is created. In this sample, the type ofint
is passed to the template argument. It is also possible to pass the type ofboost::multiprecision::cpp_int
to the template argument. - the 44th line: The algorithm is executed.
- after the 46th line: The input points and the convex hull are drawn.
- the 57th line: The sequence of points which constitutes the convex hull is extracted.
Demos
Development Environment
- Mac OS X 10.8.4
- Processor:3.06 GHz Intel Core 2 Duo
- Memory:4GB
- Xcode4.6.2 with Apple LLVM 4.2(C++ Language Dialect → C++11, C++ Standard Library → libc++)
- boost-1.53.0 built by Apple LLVM 4.2 (See here)
- opencv-2.4.5 built by Apple LLVM 4.2 (See here)
Reference
- 計算幾何プログラミング, 杉原厚吉, 岩波書店 (in Japanese)
0 件のコメント:
コメントを投稿