Boost C++ Libraries: Ticket #6063: resize does not offset rectangles (etc.) correctly or crashes https://svn.boost.org/trac10/ticket/6063 <p> When using the 'corner_fill_arc' parameter to polygon_set_concept&lt;T&gt;::resize(), a minkowski sum using a polygonalized circle is used to get the offset shape. </p> <p> A symptom of the problem is demonstrated by the following code: </p> <pre class="wiki"> { polygon_set_data&lt;int&gt; ps1, ps2, ps3; ps1.insert(rectangle_data&lt;int&gt;(0, 0, 50, 50)); ps2.insert(rectangle_data&lt;int&gt;(0, 0, 50, 50)); ps3.insert(rectangle_data&lt;int&gt;(0, 0, 50, 50)); std::cout &lt;&lt; "rect before resize: " &lt;&lt; ps1 &lt;&lt; std::endl; ps1.resize(6, true, 0); ps2.resize(6, true, 5); ps3.resize(6, true, 6); rectangle_data&lt;int&gt; ps1_extents, ps2_extents, ps3_extents; extents(ps1_extents, ps1); extents(ps2_extents, ps2); extents(ps3_extents, ps3); std::cout &lt;&lt; "extents of resized rect with '0' (4) segments in circle: " &lt;&lt; ps1_extents &lt;&lt; std::endl; std::cout &lt;&lt; "extents of resized rect with 5 segments in circle: " &lt;&lt; ps2_extents &lt;&lt; std::endl; std::cout &lt;&lt; "extents of resized rect with 6 segments in circle: " &lt;&lt; ps3_extents &lt;&lt; std::endl; } </pre><p> If I put this at the end of the gtl_boost_unit_test.cpp, I get the following output: </p> <pre class="wiki">rect before resize: Polygon Set Data { &lt;0 0, 50 0&gt;:1 &lt;50 0, 50 50&gt;:-1 &lt;0 50, 50 50&gt;:-1 &lt;0 0, 0 50&gt;:1 } extents of resized rect with '0' (4) segments in circle: -5 54 -5 54 extents of resized rect with 5 segments in circle: -6 54 -6 55 extents of resized rect with 6 segments in circle: -6 55 -6 56 </pre><p> This shows that the extents of the offset shape vary as the number of segments does - which should not be the case! </p> <p> The extents should all be: -6 56 -6 56 </p> <hr /> <p> The problem (to my eyes) is that the polygonalized circle does not generally have the right shape to get proper offsets in axis-oriented directions, so the offset is basically multiplied by some factor of sqrt(2). Attached is an image of the circle generated with num_circle_segments=16. The radius of the circle - i.e. distance from center to each vertex - is 2. The grid spacing is 1. As can be seen, the top/bottom and left/right sides of the circle do not lie on the grid. If the circle started with a vertex at(0,2) this would not occur and one would presumably get proper offsets in axis-aligned directions. Alternately one could offset all the vertices slightly farther, but this would offset some vertices farther than desired. </p> <p> I would guess the fix is to change the behaviour of make_arc(), which generates these points, but I'm not sure exactly what the original author's intent was - so maybe just using a new function would be best (after all, the complexity of make_arc is overkill when you're generating a simple full circle) </p> <hr /> <p> Another problem is that the behaviour of the 'corner_fill_arc' parameter is not really well described. Using this gives much more than corner-filling behaviour - it gives different offsets in different directions. I would suggest explaining it as it is - a minkowski sum with a polygonalized circle, with all that implies. </p> <p> E.g. for a 45-degree segment the offset will differ from a 90-degree segment unless you pick the right value of num_circle_segments. </p> <p> Maybe a more comprehensible solution would be to implement corner rounding by the intersection of the normal resize()d shape (as given by corner_fill_arc=false) with the resize()d shape given by corner_fill_arc=true with a larger 'resizing' (picked so that the minimum resizing equals the original resizing). </p> <p> This would only affect corners, instead of the whole shape. </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/6063 Trac 1.4.3 dbfaken@… Wed, 26 Oct 2011 21:20:30 GMT attachment set https://svn.boost.org/trac10/ticket/6063 https://svn.boost.org/trac10/ticket/6063 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">make_arc_16segments.PNG</span> </li> </ul> <p> output of boost::polygon's make_arc for 16 segments </p> Ticket dbfaken@… Thu, 27 Oct 2011 16:38:34 GMT attachment set https://svn.boost.org/trac10/ticket/6063 https://svn.boost.org/trac10/ticket/6063 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">boost_polygon_bug6063.diff</span> </li> </ul> <p> patch for ticket 6063 </p> Ticket dbfaken@… Thu, 27 Oct 2011 16:40:25 GMT <link>https://svn.boost.org/trac10/ticket/6063#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6063#comment:1</guid> <description> <p> Attaching a patch which implements the final suggestion: </p> <ol><li>scale the circle generated by make_arc() so that the *minimum* (instead of maximum) bloating distance is given by 'resizing'. (or, for resizing &lt; 0, the maximum shrinking distance) </li><li>intersect the results of the minkowski sum with the 'normal offset' of the initial shape (or its inverse, for resizing &lt; 0). </li></ol> </description> <category>Ticket</category> </item> <item> <author>dbfaken@…</author> <pubDate>Thu, 27 Oct 2011 20:00:55 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6063#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6063#comment:2</guid> <description> <p> Attaching another version of the patch (this time in 'unified diff' patch format) which adds an optional parameter <em>double minUnroundedAngleDegrees</em>. </p> <p> This fixes another problem in the corner-rounding - that all corners get rounded, even though <strong>the docs say</strong> that rounding is only applied to "acute corners". </p> <p> The new parameter allows the caller to control which corners get rounded. For example, setting it to 90.0 will only allow acute-angled corners (&lt;90) to get rounded. This is typically desired in, e.g. VLSI layout - you don't want your purely-90-degree corners to get rounded! </p> <p> Setting it to 45.0 will likewise preserve Polygon_45-type objects as containing only 45-degree angles. </p> <p> I have set the default to 180.0 to preserve the original behaviour, but as mentioned above I would suggest making it 90.0 to match the docs. </p> <p> Note this patch includes/supercedes the previous .diff file I attached. </p> <p> For simplicity in the patch I have only added this parameter to the boost::polygon::polygon_set_data&lt;T&gt;::resize() function, not to the generic boost::polygon::resize() operator. </p> <p> If this extra parameter is found pleasing, the parameter should be propagated through to the other versions, with the default value. (if you want me to post a patch for this just say so in a comment) </p> <hr /> <p> Quick description of the fix (see also the comments in the code): </p> <p> This builds upon the previous fix. </p> <p> I simply set the radius of the convolved circle to the distance of the 'elbow' generated by a corner of angle <em>minUnroundedAngleDegrees</em>. The extra area generated by the larger circle still gets trimmed off by the intersection with the 'unrounded offset', as before. </p> </description> <category>Ticket</category> </item> <item> <author>dbfaken@…</author> <pubDate>Thu, 27 Oct 2011 20:02:10 GMT</pubDate> <title>attachment set https://svn.boost.org/trac10/ticket/6063 https://svn.boost.org/trac10/ticket/6063 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">boost_polygon_bug6063_fix2.patch</span> </li> </ul> <p> Second version of fix for ticket 6063. Created against boost 1.47.0. </p> Ticket dbfaken@… Tue, 07 Feb 2012 19:45:51 GMT <link>https://svn.boost.org/trac10/ticket/6063#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6063#comment:3</guid> <description> <p> Another wrinkle: Corner-rounding-offset is being done via a minkowski sum of the given shape with a polygonalized "circle", but the vertices are being snapped to integral values (e.g. int) via round_down(). This causes the 'circle' to be skewed toward the lower-left-hand quadrant, instead of being symmetric about its center-point. </p> <p> This in turn can cause improper offsetting of a simple square with the given code, since even with the 'arcRadScaling' and 'elbowDist' compensation in polygon_set_data&lt;T&gt;::resize(), a circle passed through round_down() may not reach the appropriate corners when minUnroundedAngleDegrees=90. </p> <p> The solution is to use a circle where the points are symmetrically rounded 'away' from the center of the circle. </p> <p> The next patch fixes this by adding a required parameter 'round_away_from_center' to make_arc. It is set to true when called from polygon_set_data&lt;T&gt;::resize(). I have left it as false (so that round_down&lt;T&gt;() is still used - same behaviour as in 1.47) when called from make_resizing_vertex_list() for now, though this case should presumably also be fixed. There is also a small tweak to avoid dividing by zero, and a tweak to make_arc so it doesn't include the center in the polygon when generating a full circle. </p> </description> <category>Ticket</category> </item> <item> <author>dbfaken@…</author> <pubDate>Tue, 07 Feb 2012 19:47:34 GMT</pubDate> <title>attachment set https://svn.boost.org/trac10/ticket/6063 https://svn.boost.org/trac10/ticket/6063 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">boost_polygon_bug6063_fix3.patch</span> </li> </ul> <p> Third version of fix for boost::polygon bug ticket <a class="assigned ticket" href="https://svn.boost.org/trac10/ticket/6063" title="#6063: Bugs: resize does not offset rectangles (etc.) correctly or crashes (assigned)">#6063</a>. Also includes a patch for ticket 6051 (commented and easily removed if desired). </p> Ticket dbfaken@… Tue, 07 Feb 2012 19:48:55 GMT <link>https://svn.boost.org/trac10/ticket/6063#comment:4 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6063#comment:4</guid> <description> <p> Forgot to note - last patch ('fix3') was against boost 1.47.0. </p> </description> <category>Ticket</category> </item> <item> <author>dbfaken@…</author> <pubDate>Thu, 05 Jul 2012 18:34:07 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6063#comment:5 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6063#comment:5</guid> <description> <p> Attaching a patch that works with boost 1.49.0. </p> <p> This does not include the patch for ticket 6051. </p> <p> Could someone please integrate this into the next release? </p> <p> thanks, Daniel </p> </description> <category>Ticket</category> </item> <item> <author>dbfaken@…</author> <pubDate>Thu, 05 Jul 2012 18:35:35 GMT</pubDate> <title>attachment set https://svn.boost.org/trac10/ticket/6063 https://svn.boost.org/trac10/ticket/6063 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">boost_polygon_bug6063_diffForBoost1_49_0.patch</span> </li> </ul> <p> Patch for boost v1.49.0 </p> Ticket Lucanus Simonson Wed, 19 Sep 2012 01:38:55 GMT <link>https://svn.boost.org/trac10/ticket/6063#comment:6 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6063#comment:6</guid> <description> <p> I'll have to follow up on this. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Andrii Sydorchuk</dc:creator> <pubDate>Sun, 16 Jun 2013 01:52:56 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6063#comment:7 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6063#comment:7</guid> <description> <p> Hi, </p> <p> There was a change in maintainers of the Boost Polygon, and this ticket was lost for a while. First of all thanks for your patches. I am going to have a deeper look in the following few weeks. </p> <p> Andrii </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Andrii Sydorchuk</dc:creator> <pubDate>Sun, 16 Jun 2013 01:53:34 GMT</pubDate> <title>owner, status changed https://svn.boost.org/trac10/ticket/6063#comment:8 https://svn.boost.org/trac10/ticket/6063#comment:8 <ul> <li><strong>owner</strong> changed from <span class="trac-author">Lucanus Simonson</span> to <span class="trac-author">Andrii Sydorchuk</span> </li> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">assigned</span> </li> </ul> Ticket Andrii Sydorchuk Wed, 06 Nov 2013 23:42:51 GMT <link>https://svn.boost.org/trac10/ticket/6063#comment:9 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6063#comment:9</guid> <description> <p> Adding duplicate ticket <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/6080" title="#6080: Bugs: bug in polygonset::resize() (closed: duplicate)">#6080</a>: </p> <p> """ Hi, </p> <p> I found two bug in polygonset::resize() as follows, </p> <blockquote> <p> <em>bug1 </em></p> <blockquote> <p> std::vector&lt;Point&gt; pts; Polygon poly; <a class="missing wiki">PolygonSet</a> polySet, polySetResult; </p> </blockquote> </blockquote> <blockquote> <blockquote> <p> pts.clear(); pts.push_back(Point( 6300, 0)); pts.push_back(Point( 0, 0)); pts.push_back(Point( 0, 4750)); pts.push_back(Point( 1250, 6000)); pts.push_back(Point( 1250, 7500)); pts.push_back(Point( 2850, 7500)); pts.push_back(Point( 2850, 5950)); pts.push_back(Point( 5950, 5950)); pts.push_back(Point( 5950, 5750)); pts.push_back(Point( 6300, 5400)); </p> </blockquote> </blockquote> <blockquote> <blockquote> <p> boost::polygon::set_points(poly, pts.begin(), pts.end()); </p> </blockquote> </blockquote> <blockquote> <blockquote> <p> polySet += poly; polySetResult += polySet-1000; </p> </blockquote> </blockquote> <blockquote> <p> <em>bug2 </em></p> <blockquote> <p> std::vector&lt;Point&gt; pts2; Polygon poly2; <a class="missing wiki">PolygonSet</a> polySet2, polySetResult2; </p> </blockquote> </blockquote> <blockquote> <blockquote> <p> pts2.clear(); pts2.push_back(Point(2100, 2575)); pts2.push_back(Point(1700, 2575)); pts2.push_back(Point(1700, 2365)); pts2.push_back(Point(1800, 2265)); pts2.push_back(Point(1835, 2265)); pts2.push_back(Point(1835, 1945)); pts2.push_back(Point(1645, 1945)); pts2.push_back(Point(1645, 2305)); pts2.push_back(Point(1440, 2305)); pts2.push_back(Point(1440, 2790)); pts2.push_back(Point(1145, 2790)); pts2.push_back(Point(1145, 1805)); pts2.push_back(Point(2100, 1805)); </p> </blockquote> </blockquote> <blockquote> <blockquote> <p> boost::polygon::set_points(poly2, pts2.begin(), pts2.end()); </p> </blockquote> </blockquote> <blockquote> <blockquote> <p> polySet2 += poly2; polySetResult2 += polySet2+100; </p> </blockquote> </blockquote> <p> For bug one, </p> <p> current result : { 1000 4336, 1000 1000, 5300 1000, 5300 4986, 4950 5336, 4950 4950, 1850 4950, 1850 5186} </p> <p> correct result : { 1000 4336, 1000 1000, 5300 1000, 5300 4950, 1850 4950, 1850 5186} </p> <p> For bug two, the result is a polygon with hole. However, I think there shall be no hole in the result. </p> <p> Please check and thanks for your help. </p> <p> Regards, </p> <p> Jay Huang """ </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Andrii Sydorchuk</dc:creator> <pubDate>Wed, 06 Nov 2013 23:44:15 GMT</pubDate> <title>attachment set https://svn.boost.org/trac10/ticket/6063 https://svn.boost.org/trac10/ticket/6063 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">test.cpp</span> </li> </ul> <p> ticket_9036 </p> Ticket Andrii Sydorchuk Wed, 06 Nov 2013 23:45:07 GMT <link>https://svn.boost.org/trac10/ticket/6063#comment:10 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6063#comment:10</guid> <description> <p> Adding duplicate ticket <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/9036" title="#9036: Bugs: polygon resize() crashes with access violation (closed: duplicate)">#9036</a>: </p> <p> """ On some data (attached) boost::polygon::resize crashes with access violation in release version, in debug there is an assert about invalid iterator access. """ </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Andrii Sydorchuk</dc:creator> <pubDate>Wed, 06 Nov 2013 23:46:33 GMT</pubDate> <title>attachment set https://svn.boost.org/trac10/ticket/6063 https://svn.boost.org/trac10/ticket/6063 <ul> <li><strong>attachment</strong> → <span class="trac-field-new">test_resize.cpp</span> </li> </ul> <p> ticket_9168 </p> Ticket Andrii Sydorchuk Wed, 06 Nov 2013 23:47:07 GMT <link>https://svn.boost.org/trac10/ticket/6063#comment:11 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6063#comment:11</guid> <description> <p> Adding duplicate ticket <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/9168" title="#9168: Bugs: polygon resize -1 of a 1 point wide polygon doesn't make it disappear (closed: duplicate)">#9168</a>: </p> <p> """ I tried to use resize(pset, -1); resize(pset, 1) to filter the results of a xor which should remove all polygon with only 1 or 2 database unit differences. resize -1 generates wrong output if the polygon are not orthogonal. </p> <p> input: 0,0 0,5 1,5 1,0 3,-3 resize -1: 0,1 -3,5 0,0 0,1 """ </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Andrii Sydorchuk</dc:creator> <pubDate>Thu, 21 Nov 2013 00:19:07 GMT</pubDate> <title>summary changed https://svn.boost.org/trac10/ticket/6063#comment:12 https://svn.boost.org/trac10/ticket/6063#comment:12 <ul> <li><strong>summary</strong> <span class="trac-field-old">resize does not offset rectangles (etc.) correctly when using corner_fill_arc</span> → <span class="trac-field-new">resize does not offset rectangles (etc.) correctly or crashes</span> </li> </ul> Ticket Andrii Sydorchuk Thu, 21 Nov 2013 20:37:15 GMT <link>https://svn.boost.org/trac10/ticket/6063#comment:13 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6063#comment:13</guid> <description> <p> dbfaken@ I'd like to thank you for the patches you provided, unfortunately the problem with resize is deeper than it looks, the current approach is basically wrong (numerically and topologically). Without going much into details, the steps to fix the current implementation are the following:<br /> 1) The proper implementation for the resize with corner_fill_arc set to false should be based on the straight skeleton extraction.<br /> 2) The proper implementation for the resize with corner_fill_arc set to true should be based on the Voronoi diagram extraction. Fortunately Polygon already has robust implementation of Voronoi diagram extraction. However it's not philosophically compatible with the legacy Polygon code (step 3 explains why).<br /> 3) Most of the algorithms operating on polygons should accept only integral coordinates (this is already sort of true), however they should return polygons or primitives with floating-point coordinates. It should be the user decision to do the snap and rounding and the library should provide the utilities to do so.<br /> <br /> I am still evaluating work to be done to fix the step 3. I will also update the documentation for the next release to clarify that resize implementation is broken. </p> </description> <category>Ticket</category> </item> <item> <author>dbfaken@…</author> <pubDate>Thu, 21 Nov 2013 22:43:25 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6063#comment:14 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6063#comment:14</guid> <description> <p> Replying to <a class="ticket" href="https://svn.boost.org/trac10/ticket/6063#comment:13" title="Comment 13">asydorchuk</a>: </p> <blockquote class="citation"> <p> dbfaken@ I'd like to thank you for the patches you provided, unfortunately the problem with resize is deeper than it looks, the current approach is basically wrong (numerically and topologically). </p> </blockquote> <p> Thank you for looking into this and glad you have a plan. Separation of the snapping logic from the offset operation does seem like a good idea. </p> </description> <category>Ticket</category> </item> <item> <author>z@…</author> <pubDate>Thu, 06 Feb 2014 23:53:25 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6063#comment:15 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6063#comment:15</guid> <description> <p> what's the time line for fixing resize() according to your stated plan? I also ran into the problems with resize(). This is a showstopper for us to switch using Boost polygon. </p> <p> First, with the resize with corner_fill_arc set to false. Apparently, it does bad thing to resulting polygon (see Ticket <a class="closed ticket" href="https://svn.boost.org/trac10/ticket/5358" title="#5358: Bugs: polygon resize() generates bad/broken vertices (closed: invalid)">#5358</a>) when "very small features before shrinking can become very large after if the angle is acute. That is what happened in this case". I don't understand why it was closed as 'invalid'. </p> <p> Second, with the resize with corner_fill_arc set to true. Apparently, this fixes the problem above, but introduces new problem. That is resize 'offset' is not correct. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>Andrii Sydorchuk</dc:creator> <pubDate>Mon, 10 Feb 2014 22:06:28 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/6063#comment:16 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/6063#comment:16</guid> <description> <p> There is no explicit timeline for the plan I mentioned before. </p> </description> <category>Ticket</category> </item> </channel> </rss>