/Src/Dependencies/Boost/libs/polygon/doc/gtl_minkowski_tutorial.htm
http://hadesmem.googlecode.com/ · HTML · 229 lines · 222 code · 7 blank · 0 comment · 0 complexity · c1dbe82ef8dafffd0464fd796d15ae1a MD5 · raw file
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
- <title>Polygon Usage</title>
- </head>
- <body>
- <h1>Minkowski Sum Tutorial</h1>
- <p>In this tutorial we will implement an algorithm to compute the Minkowski sum
- of two polygon sets. The Minkowski sum of two polygon sets is the
- convolution of the two polygon sets and is defined as the set of points which is
- produced if you sum all pairs of points in the two polygon sets. The sum
- of two points is implemented in Boost.Polygon by the <font face="Courier New">
- convolve</font> function for <a href="gtl_point_concept.htm">point_concept</a>.
- Similarly there is a <font face="Courier New">
- convolve</font> function for <a href="gtl_rectangle_concept.htm">rectangle_concept</a>.
- The convolution of two polygon sets produces a polygon set as its output.
- An example of the convolution of two polygons is shown below. The center
- point of the green
- star can be imagined to slide around freely inside the blue picture frame shape
- painting the area the star touches to produce the red bloated picture frame.</p>
- <p> <img border="0" src="images/convolution1.PNG" width="438" height="404"></p>
- <p>The above image was produced using the code presented in this tutorial.
- We can see that the algorithm for Minkowski sum should support non-convex
- polygons that may potentially have holes. It should also support disjoint
- polygons in both input polygon sets. Shown below is what happens when
- multiple polygons are present in each input polygon set.</p>
- <p><img border="0" src="images/convolution2.PNG" width="547" height="432"></p>
- <p>In each of these examples the origin of the coordinate system is in the lower
- left corner of the image and the sum of the x and y locations of the input
- polygons places the result in the upper right hand corner of the images.
- In the example above the lower left red triangle is the convolution of the small
- blue triangle with the small green triangle. The upper right red triangle
- is the convolution of the large blue and large green triangle. The two
- medium sized red polygons are the result of the convolution of the small with
- large and large with small blue and green triangles. The test case was
- carefully contrived to prevent the result from merging together, though that
- could certainly happen.</p>
- <p>The algorithm implemented for Minkowski sum in this tutorial is very simple.
- It is based on the convolution of polygon edges. The convolution of two
- edges is very easy to compute and is in general a parallelogram. An
- example of two edges being convolved to produce a parallelogram is shown below.</p>
- <p><img border="0" src="images/convolve_edges.PNG" width="491" height="461"></p>
- <p>Now that we know what we need from a function to convolve two edges, let's
- implement one now. Below we show the code for convolving two edges along
- with some type definitions we will be using throughout the tutorial. The
- code for this tutorial is available in <a href="tutorial/minkowski.cpp">
- minkowski.cpp</a>.</p>
- <p><font face="Courier New" size="2">typedef boost::polygon::point_data<int>
- point;<br>
- typedef boost::polygon::polygon_set_data<int> polygon_set;<br>
- typedef boost::polygon::polygon_with_holes_data<int> polygon;<br>
- typedef std::pair<point, point> edge;<br>
- using namespace boost::polygon::operators;<br>
- <br>
- void convolve_two_segments(std::vector<point>& figure, const edge& a, const
- edge& b) {<br>
- using namespace boost::polygon;<br>
- figure.clear();<br>
- figure.push_back(point(a.first));<br>
- figure.push_back(point(a.first));<br>
- figure.push_back(point(a.second));<br>
- figure.push_back(point(a.second));<br>
- convolve(figure[0], b.second);<br>
- convolve(figure[1], b.first);<br>
- convolve(figure[2], b.first);<br>
- convolve(figure[3], b.second);<br>
- }</font></p>
- <p>This function for convolving two line segments just convolves the end points
- of the two line segments in all combinations to produce the four points of a
- parallelogram and populates a vector of points with them in the correct order.
- We are using the Boost.Polygon library function for convolving two points and
- the library point data structure.</p>
- <p>To compute the convolution of two polygon sets we start by taking the union
- of the convolution of all pairs of edges between the two polygon sets.
- Given an operation for convolving two edges it is pretty easy to convolve all
- pairs of edges of two polygon sets. The result is the convolution the
- perimeters of the polygon sets, but doesn't handle the convolution of their
- interiors. To illustrate this we show what happens when one of the above
- examples is computed using just the all pairs of edges convolution.</p>
- <p> <img border="0" src="images/perimeter_convolve.PNG" width="546" height="432"></p>
- <p>As we can see, the result is as if the small triangles were slid around the
- perimeter of the large triangles leaving a hole in the center that should be
- filled in if the small triangle were allowed to slide freely within the large
- triangle. Also available in Boost.Polygon is the <font face="Courier New">
- convolve</font> function for <a href="gtl_polygon_concept.htm">polygon_concept</a>
- that convolves a polygon over a point. All this does is translate the
- polygon by the x and y value of the point. To fill in the interior regions
- of the result of the convolution of two polygon sets we perform an all pairs of
- polygon convolution to the first vertex of the other polygon and merge that into
- the union of edge convolutions.</p>
- <p>Let's implement the rest of Minkowski sum of two polygon sets as the union of
- all pairs edges convolutions and the all pairs of polygons to point
- convolutions. First we implement a function that convolves all pairs of
- edges represented by iterator pairs over points. We assume that the first
- point is equal to the last point in each sequence because we know the polygons
- that gave rise to the iterators were produced by the Boost.Polygon algorithm for
- general polygon formation.</p>
- <p><font face="Courier New" size="2">template <typename itrT1, typename itrT2><br>
- void convolve_two_point_sequences(polygon_set& result, itrT1 ab, itrT1 ae, itrT2
- bb, itrT2 be) {<br>
- using namespace boost::polygon;<br>
- if(ab == ae || bb == be)<br>
- return;<br>
- point prev_a = *ab;<br>
- std::vector<point> vec;<br>
- polygon poly;<br>
- ++ab;<br>
- for( ; ab != ae; ++ab) {<br>
- point prev_b = *bb;<br>
- itrT2 tmpb = bb;<br>
- ++tmpb;<br>
- for( ; tmpb != be; ++tmpb) {<br>
- convolve_two_segments(vec, std::make_pair(prev_b,
- *tmpb), std::make_pair(prev_a, *ab));<br>
- set_points(poly, vec.begin(), vec.end());<br>
- result.insert(poly);<br>
- prev_b = *tmpb;<br>
- }<br>
- prev_a = *ab;<br>
- }<br>
- }</font></p>
- <p>Using the function defined above we can implement a function for computing
- the convolution of all pairs of edges represented by an iterator pair over
- points and edges in a collection of polygons. We just call the
- convolve_two_point_sequences for the input point sequence and all outer shell
- and hole point sequences from the container of polygons.</p>
- <p><font face="Courier New" size="2">template <typename itrT><br>
- void convolve_point_sequence_with_polygons(polygon_set& result, itrT b, itrT e,
- const std::vector<polygon>& polygons) {<br>
- using namespace boost::polygon;<br>
- for(std::size_t i = 0; i < polygons.size(); ++i) {<br>
- convolve_two_point_sequences(result, b, e,
- begin_points(polygons[i]), end_points(polygons[i]));<br>
- for(polygon_with_holes_traits<polygon>::iterator_holes_type
- itrh = begin_holes(polygons[i]);<br>
- itrh != end_holes(polygons[i]); ++itrh)
- {<br>
- convolve_two_point_sequences(result, b, e,
- begin_points(*itrh), end_points(*itrh));<br>
- }<br>
- }<br>
- }</font></p>
- <p>Using the function defined above we can implement a function for computing
- the convolution of all pairs of edges from polygons contained within two polygon
- sets. We also convolve each polygon with the first vertex of every polygon
- from the other set to fill in the interiors of the result.</p>
- <p><font face="Courier New" size="2">void convolve_two_polygon_sets(polygon_set&
- result, const polygon_set& a, const polygon_set& b) {<br>
- using namespace boost::polygon;<br>
- result.clear();<br>
- std::vector<polygon> a_polygons;<br>
- std::vector<polygon> b_polygons;<br>
- a.get(a_polygons);<br>
- b.get(b_polygons);<br>
- for(std::size_t ai = 0; ai < a_polygons.size(); ++ai) {<br>
- convolve_point_sequence_with_polygons(result,
- begin_points(a_polygons[ai]), <br>
-
- end_points(a_polygons[ai]), b_polygons);<br>
- for(polygon_with_holes_traits<polygon>::iterator_holes_type
- itrh = begin_holes(a_polygons[ai]);<br>
- itrh != end_holes(a_polygons[ai]); ++itrh)
- {<br>
- convolve_point_sequence_with_polygons(result,
- begin_points(*itrh), <br>
-
- end_points(*itrh), b_polygons);<br>
- }<br>
- for(std::size_t bi = 0; bi < b_polygons.size(); ++bi) {<br>
- polygon tmp_poly = a_polygons[ai];<br>
- result.insert(convolve(tmp_poly, *(begin_points(b_polygons[bi]))));<br>
- tmp_poly = b_polygons[bi];<br>
- result.insert(convolve(tmp_poly, *(begin_points(a_polygons[ai]))));<br>
- }<br>
- }<br>
- }</font></p>
- <p>We test the convolution of two polygon sets with the code shown below that
- produces the first example shown in this tutorial.<font face="Courier New" size="2">
- </font></p>
- <p><font face="Courier New" size="2">polygon_set a, b, c;<br>
- a += boost::polygon::rectangle_data<int>(0+300, 0, 200+300, 200);<br>
- a -= boost::polygon::rectangle_data<int>(50+300, 50, 150+300, 150);<br>
- std::vector<polygon> polys;<br>
- std::vector<point> pts;<br>
- pts.push_back(point(-40, 0+300));<br>
- pts.push_back(point(-10, 10+300));<br>
- pts.push_back(point(0, 40+300));<br>
- pts.push_back(point(10, 10+300));<br>
- pts.push_back(point(40, 0+300));<br>
- pts.push_back(point(10, -10+300));<br>
- pts.push_back(point(0, -40+300));<br>
- pts.push_back(point(-10, -10+300));<br>
- pts.push_back(point(-40, 0+300));<br>
- polygon poly;<br>
- boost::polygon::set_points(poly, pts.begin(), pts.end());<br>
- b+=poly;<br>
- convolve_two_polygon_sets(c, a, b);</font></p>
- <p>Output (a is blue, b is green and c is red):</p>
- <p><img border="0" src="images/convolution1.PNG" width="438" height="404"></p>
- <p>This concludes our tutorial on how to implement Minkowski sum of polygons as
- the convolution of polygon sets based on the Boolean OR operation of geometry
- produced by simpler convolution features provided by the Boost.Polygon library.</p>
- <table class="docinfo" rules="none" frame="void" id="table1">
- <colgroup>
- <col class="docinfo-name"><col class="docinfo-content">
- </colgroup>
- <tbody vAlign="top">
- <tr>
- <th class="docinfo-name">Copyright:</th>
- <td>Copyright Š Intel Corporation 2008-2010.</td>
- </tr>
- <tr class="field">
- <th class="docinfo-name">License:</th>
- <td class="field-body">Distributed under the Boost Software License,
- Version 1.0. (See accompanying file <tt class="literal">
- <span class="pre">LICENSE_1_0.txt</span></tt> or copy at
- <a class="reference" target="_top" href="http://www.boost.org/LICENSE_1_0.txt">
- http://www.boost.org/LICENSE_1_0.txt</a>)</td>
- </tr>
- </table>
- </body>
- </html>