]> git.proxmox.com Git - ceph.git/blame - ceph/src/boost/libs/polygon/doc/gtl_minkowski_tutorial.htm
bump version to 12.2.2-pve1
[ceph.git] / ceph / src / boost / libs / polygon / doc / gtl_minkowski_tutorial.htm
CommitLineData
7c673cae
FG
1<html>
2
3<head>
4<meta http-equiv="Content-Type" content="text/html; charset=windows-1252">
5<title>Polygon Usage</title>
6</head>
7
8<body>
9
10<h1>Minkowski Sum Tutorial</h1>
11<p>In this tutorial we will implement an algorithm to compute the Minkowski sum
12of two polygon sets.&nbsp; The Minkowski sum of two polygon sets is the
13convolution of the two polygon sets and is defined as the set of points which is
14produced if you sum all pairs of points in the two polygon sets.&nbsp; The sum
15of two points is implemented in Boost.Polygon by the <font face="Courier New">
16convolve</font> function for <a href="gtl_point_concept.htm">point_concept</a>.&nbsp;
17Similarly there is a <font face="Courier New">
18convolve</font> function for <a href="gtl_rectangle_concept.htm">rectangle_concept</a>.&nbsp;
19The convolution of two polygon sets produces a polygon set as its output.&nbsp;
20An example of the convolution of two polygons is shown below.&nbsp; The center
21point of the green
22star can be imagined to slide around freely inside the blue picture frame shape
23painting the area the star touches to produce the red bloated picture frame.</p>
24<p>&nbsp;<img border="0" src="images/convolution1.PNG" width="438" height="404"></p>
25<p>The above image was produced using the code presented in this tutorial.&nbsp;
26We can see that the algorithm for Minkowski sum should support non-convex
27polygons that may potentially have holes.&nbsp; It should also support disjoint
28polygons in both input polygon sets.&nbsp; Shown below is what happens when
29multiple polygons are present in each input polygon set.</p>
30<p><img border="0" src="images/convolution2.PNG" width="547" height="432"></p>
31<p>In each of these examples the origin of the coordinate system is in the lower
32left corner of the image and the sum of the x and y locations of the input
33polygons places the result in the upper right hand corner of the images.&nbsp;
34In the example above the lower left red triangle is the convolution of the small
35blue triangle with the small green triangle.&nbsp; The upper right red triangle
36is the convolution of the large blue and large green triangle.&nbsp; The two
37medium sized red polygons are the result of the convolution of the small with
38large and large with small blue and green triangles.&nbsp; The test case was
39carefully contrived to prevent the result from merging together, though that
40could certainly happen.</p>
41<p>The algorithm implemented for Minkowski sum in this tutorial is very simple.&nbsp;
42It is based on the convolution of polygon edges.&nbsp; The convolution of two
43edges is very easy to compute and is in general a parallelogram.&nbsp; An
44example of two edges being convolved to produce a parallelogram is shown below.</p>
45<p><img border="0" src="images/convolve_edges.PNG" width="491" height="461"></p>
46<p>Now that we know what we need from a function to convolve two edges, let's
47implement one now.&nbsp; Below we show the code for convolving two edges along
48with some type definitions we will be using throughout the tutorial.&nbsp; The
49code for this tutorial is available in <a href="tutorial/minkowski.cpp">
50minkowski.cpp</a>.</p>
51<p><font face="Courier New" size="2">typedef boost::polygon::point_data&lt;int&gt;
52point;<br>
53typedef boost::polygon::polygon_set_data&lt;int&gt; polygon_set;<br>
54typedef boost::polygon::polygon_with_holes_data&lt;int&gt; polygon;<br>
55typedef std::pair&lt;point, point&gt; edge;<br>
56using namespace boost::polygon::operators;<br>
57<br>
58void convolve_two_segments(std::vector&lt;point&gt;&amp; figure, const edge&amp; a, const
59edge&amp; b) {<br>
60&nbsp; using namespace boost::polygon;<br>
61&nbsp; figure.clear();<br>
62&nbsp; figure.push_back(point(a.first));<br>
63&nbsp; figure.push_back(point(a.first));<br>
64&nbsp; figure.push_back(point(a.second));<br>
65&nbsp; figure.push_back(point(a.second));<br>
66&nbsp; convolve(figure[0], b.second);<br>
67&nbsp; convolve(figure[1], b.first);<br>
68&nbsp; convolve(figure[2], b.first);<br>
69&nbsp; convolve(figure[3], b.second);<br>
70}</font></p>
71<p>This function for convolving two line segments just convolves the end points
72of the two line segments in all combinations to produce the four points of a
73parallelogram and populates a vector of points with them in the correct order.&nbsp;
74We are using the Boost.Polygon library function for convolving two points and
75the library point data structure.</p>
76<p>To compute the convolution of two polygon sets we start by taking the union
77of the convolution of all pairs of edges between the two polygon sets.&nbsp;
78Given an operation for convolving two edges it is pretty easy to convolve all
79pairs of edges of two polygon sets.&nbsp; The result is the convolution the
80perimeters of the polygon sets, but doesn't handle the convolution of their
81interiors.&nbsp; To illustrate this we show what happens when one of the above
82examples is computed using just the all pairs of edges convolution.</p>
83<p>&nbsp; <img border="0" src="images/perimeter_convolve.PNG" width="546" height="432"></p>
84<p>As we can see, the result is as if the small triangles were slid around the
85perimeter of the large triangles leaving a hole in the center that should be
86filled in if the small triangle were allowed to slide freely within the large
87triangle.&nbsp; Also available in Boost.Polygon is the <font face="Courier New">
88convolve</font> function for <a href="gtl_polygon_concept.htm">polygon_concept</a>
89that convolves a polygon over a point.&nbsp; All this does is translate the
90polygon by the x and y value of the point.&nbsp; To fill in the interior regions
91of the result of the convolution of two polygon sets we perform an all pairs of
92polygon convolution to the first vertex of the other polygon and merge that into
93the union of edge convolutions.</p>
94<p>Let's implement the rest of Minkowski sum of two polygon sets as the union of
95all pairs edges convolutions and the all pairs of polygons to point
96convolutions.&nbsp; First we implement a function that convolves all pairs of
97edges represented by iterator pairs over points.&nbsp; We assume that the first
98point is equal to the last point in each sequence because we know the polygons
99that gave rise to the iterators were produce by the Boost.Polygon algorithm for
100general polygon formation.</p>
101<p><font face="Courier New" size="2">template &lt;typename itrT1, typename itrT2&gt;<br>
102void convolve_two_point_sequences(polygon_set&amp; result, itrT1 ab, itrT1 ae, itrT2
103bb, itrT2 be) {<br>
104&nbsp; using namespace boost::polygon;<br>
105&nbsp; if(ab == ae || bb == be)<br>
106&nbsp;&nbsp;&nbsp; return;<br>
107&nbsp; point prev_a = *ab;<br>
108&nbsp; std::vector&lt;point&gt; vec;<br>
109&nbsp; polygon poly;<br>
110&nbsp; ++ab;<br>
111&nbsp; for( ; ab != ae; ++ab) {<br>
112&nbsp;&nbsp;&nbsp; point prev_b = *bb;<br>
113&nbsp;&nbsp;&nbsp; itrT2 tmpb = bb;<br>
114&nbsp;&nbsp;&nbsp; ++tmpb;<br>
115&nbsp;&nbsp;&nbsp; for( ; tmpb != be; ++tmpb) {<br>
116&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; convolve_two_segments(vec, std::make_pair(prev_b,
117*tmpb), std::make_pair(prev_a, *ab));<br>
118&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; set_points(poly, vec.begin(), vec.end());<br>
119&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result.insert(poly);<br>
120&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; prev_b = *tmpb;<br>
121&nbsp;&nbsp;&nbsp; }<br>
122&nbsp;&nbsp;&nbsp; prev_a = *ab;<br>
123&nbsp; }<br>
124}</font></p>
125<p>Using the function defined above we can implement a function for computing
126the convolution of all pairs of edges represented by an iterator pair over
127points and edges in a collection of polygons.&nbsp; We just call the
128convolve_two_point_sequences for the input point sequence and all outer shell
129and hole point sequences from the container of polygons.</p>
130<p><font face="Courier New" size="2">template &lt;typename itrT&gt;<br>
131void convolve_point_sequence_with_polygons(polygon_set&amp; result, itrT b, itrT e,
132const std::vector&lt;polygon&gt;&amp; polygons) {<br>
133&nbsp; using namespace boost::polygon;<br>
134&nbsp; for(std::size_t i = 0; i &lt; polygons.size(); ++i) {<br>
135&nbsp;&nbsp;&nbsp; convolve_two_point_sequences(result, b, e,
136begin_points(polygons[i]), end_points(polygons[i]));<br>
137&nbsp;&nbsp;&nbsp; for(polygon_with_holes_traits&lt;polygon&gt;::iterator_holes_type
138itrh = begin_holes(polygons[i]);<br>
139&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; itrh != end_holes(polygons[i]); ++itrh)
140{<br>
141&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; convolve_two_point_sequences(result, b, e,
142begin_points(*itrh), end_points(*itrh));<br>
143&nbsp;&nbsp;&nbsp; }<br>
144&nbsp; }<br>
145}</font></p>
146<p>Using the function defined above we can implement a function for computing
147the convolution of all pairs of edges from polygons contained within two polygon
148sets.&nbsp; We also convolve each polygon with the first vertex of every polygon
149from the other set to fill in the interiors of the result.</p>
150<p><font face="Courier New" size="2">void convolve_two_polygon_sets(polygon_set&amp;
151result, const polygon_set&amp; a, const polygon_set&amp; b) {<br>
152&nbsp; using namespace boost::polygon;<br>
153&nbsp; result.clear();<br>
154&nbsp; std::vector&lt;polygon&gt; a_polygons;<br>
155&nbsp; std::vector&lt;polygon&gt; b_polygons;<br>
156&nbsp; a.get(a_polygons);<br>
157&nbsp; b.get(b_polygons);<br>
158&nbsp; for(std::size_t ai = 0; ai &lt; a_polygons.size(); ++ai) {<br>
159&nbsp;&nbsp;&nbsp; convolve_point_sequence_with_polygons(result,
160begin_points(a_polygons[ai]), <br>
161&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
162end_points(a_polygons[ai]), b_polygons);<br>
163&nbsp;&nbsp;&nbsp; for(polygon_with_holes_traits&lt;polygon&gt;::iterator_holes_type
164itrh = begin_holes(a_polygons[ai]);<br>
165&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; itrh != end_holes(a_polygons[ai]); ++itrh)
166{<br>
167&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; convolve_point_sequence_with_polygons(result,
168begin_points(*itrh), <br>
169&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;
170end_points(*itrh), b_polygons);<br>
171&nbsp;&nbsp;&nbsp; }<br>
172&nbsp;&nbsp;&nbsp; for(std::size_t bi = 0; bi &lt; b_polygons.size(); ++bi) {<br>
173&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; polygon tmp_poly = a_polygons[ai];<br>
174&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result.insert(convolve(tmp_poly, *(begin_points(b_polygons[bi]))));<br>
175&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; tmp_poly = b_polygons[bi];<br>
176&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; result.insert(convolve(tmp_poly, *(begin_points(a_polygons[ai]))));<br>
177&nbsp;&nbsp;&nbsp; }<br>
178&nbsp; }<br>
179}</font></p>
180<p>We test the convolution of two polygon set with the code shown below that
181produces the first example shown in this tutorial.<font face="Courier New" size="2">
182</font></p>
183<p><font face="Courier New" size="2">polygon_set a, b, c;<br>
184a += boost::polygon::rectangle_data&lt;int&gt;(0+300, 0, 200+300, 200);<br>
185a -= boost::polygon::rectangle_data&lt;int&gt;(50+300, 50, 150+300, 150);<br>
186std::vector&lt;polygon&gt; polys;<br>
187std::vector&lt;point&gt; pts;<br>
188pts.push_back(point(-40, 0+300));<br>
189pts.push_back(point(-10, 10+300));<br>
190pts.push_back(point(0, 40+300));<br>
191pts.push_back(point(10, 10+300));<br>
192pts.push_back(point(40, 0+300));<br>
193pts.push_back(point(10, -10+300));<br>
194pts.push_back(point(0, -40+300));<br>
195pts.push_back(point(-10, -10+300));<br>
196pts.push_back(point(-40, 0+300));<br>
197polygon poly;<br>
198boost::polygon::set_points(poly, pts.begin(), pts.end());<br>
199b+=poly;<br>
200polys.clear();<br>
201convolve_two_polygon_sets(c, a, b);</font></p>
202<p>Output (a is blue, b is green and c is red):</p>
203<p><img border="0" src="images/convolution1.PNG" width="438" height="404"></p>
204<p>This concludes our tutorial on how to implement Minkowski sum of polygons as
205the convolution of polygon sets based on the Boolean OR operation of geometry
206produced by simpler convolution features provided by the Boost.Polygon library.</p>
207
208
209<table class="docinfo" rules="none" frame="void" id="table1">
210 <colgroup>
211 <col class="docinfo-name"><col class="docinfo-content">
212 </colgroup>
213 <tbody vAlign="top">
214 <tr>
215 <th class="docinfo-name">Copyright:</th>
216