Boost C++ Libraries: Ticket #8652: boost::geometry::intersection fails for triangle-triangle intersection https://svn.boost.org/trac10/ticket/8652 <p> The following example fails. The computed intersection polygon is supposed to be identical to the smaller of the two triangles. However, the computed intersection polygon is more or less the outline of the larger of the two triangles with an extra collinear point. </p> <pre class="wiki">#include &lt;iostream&gt; #include &lt;deque&gt; #include &lt;boost/geometry.hpp&gt; #include &lt;boost/geometry/geometries/point_xy.hpp&gt; #include &lt;boost/geometry/geometries/polygon.hpp&gt; #include &lt;boost/foreach.hpp&gt; int main() { typedef boost::geometry::model::polygon&lt;boost::geometry::model::d2::point_xy&lt;double&gt; &gt; polygon; polygon green, blue; #define SMALL_VAL "1e-8" boost::geometry::read_wkt( "POLYGON((0 0, 0.05 0.04, 0.05 0, 0 0))", green); boost::geometry::read_wkt( "POLYGON((0.02 -2.77556e-17, 0.05 0.02, 0.05 -2.77556e-17, 0.02 -2.77556e-17))", blue); //#define SMALL_VAL "1e-8" //boost::geometry::read_wkt( "POLYGON((0.02 " SMALL_VAL ", 0.05 0.02, 0.05 " SMALL_VAL ", 0.02 " SMALL_VAL "))", blue); std::deque&lt;polygon&gt; output; boost::geometry::intersection(green, blue, output); int i = 0; std::cout &lt;&lt; "The computed difference is:" &lt;&lt; std::endl; BOOST_FOREACH(polygon const&amp; p, output) { std::cout &lt;&lt; boost::geometry::dsv(p) &lt;&lt; std::endl; } std::cout &lt;&lt; std::endl; std::cout &lt;&lt; "The expected output would be: " &lt;&lt; std::endl; std::cout &lt;&lt; "(((0.05, 0.02), (0.05, 0), (0.02, 0), (0.05, 0.02)))" &lt;&lt; std::endl; return 0; } </pre><p> The output (compiled with gcc version 4.7.2 (Debian 4.7.2-5) on a 64bit debian wheezy system) is: </p> <p> <em>The computed difference is: (((0.05, 0.02), (0.05, -2.77556e-17), (0, 0), (0.05, 0.04), (0.05, 0.02))) </em></p> <p> The expected output would be: (((0.05, 0.02), (0.05, 0), (0.02, 0), (0.05, 0.02)))<em> </em></p> <blockquote class="citation"> <p> g++ -v </p> </blockquote> <p> Using built-in specs. COLLECT_GCC=g++ COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.7/lto-wrapper Target: x86_64-linux-gnu Configured with: ../src/configure -v --with-pkgversion='Debian 4.7.2-5' --with-bugurl=<a class="ext-link" href="file:///usr/share/doc/gcc-4.7/README.Bugs"><span class="icon">​</span>file:///usr/share/doc/gcc-4.7/README.Bugs</a> --enable-languages=c,c++,go,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.7 --enable-shared --enable-linker-build-id --with-system-zlib --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.7 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --enable-plugin --enable-objc-gc --with-arch-32=i586 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu Thread model: posix gcc version 4.7.2 (Debian 4.7.2-5) </p> en-us Boost C++ Libraries /htdocs/site/boost.png https://svn.boost.org/trac10/ticket/8652 Trac 1.4.3 anonymous Wed, 05 Jun 2013 11:35:54 GMT <link>https://svn.boost.org/trac10/ticket/8652#comment:1 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/8652#comment:1</guid> <description> <p> Another funny effect: Uncomment the two SMALL_VAL lines and use them as a replacement for polygon blue. If the value of SMALL_VAL is set to 1e-15, no intersection is detected at all. </p> </description> <category>Ticket</category> </item> <item> <dc:creator>anonymous</dc:creator> <pubDate>Wed, 05 Jun 2013 12:04:06 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/8652#comment:2 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/8652#comment:2</guid> <description> <p> Is there any workaround for this problem? </p> </description> <category>Ticket</category> </item> <item> <dc:creator>anonymous</dc:creator> <pubDate>Wed, 05 Jun 2013 17:43:32 GMT</pubDate> <title/> <link>https://svn.boost.org/trac10/ticket/8652#comment:3 </link> <guid isPermaLink="false">https://svn.boost.org/trac10/ticket/8652#comment:3</guid> <description> <p> Mapping the floating point coordinates to integer values does not solve the problem either (see the following test program). The intersection remains empty. </p> <pre class="wiki">#include &lt;iostream&gt; #include &lt;deque&gt; #include &lt;limits&gt; #include &lt;boost/geometry.hpp&gt; #include &lt;boost/geometry/geometries/point_xy.hpp&gt; #include &lt;boost/geometry/geometries/polygon.hpp&gt; #include &lt;boost/geometry/algorithms/assign.hpp&gt; #include &lt;boost/assign/list_of.hpp&gt; #include &lt;boost/geometry/geometries/adapted/boost_tuple.hpp&gt; #include &lt;boost/geometry/views/identity_view.hpp&gt; #include &lt;boost/geometry/core/closure.hpp&gt; #include &lt;boost/geometry/core/exterior_ring.hpp&gt; #include &lt;boost/foreach.hpp&gt; #define INF__ (std::numeric_limits&lt;double&gt;::infinity()) inline void mapPointToInt(const double &amp;x, const double &amp;xOffset, const double &amp;xSize, int &amp;xi) { xi = ((x - xOffset)/xSize)*INT_MAX; } inline void mapPointToFloatingPoint(int xI, const double &amp;xOffset, const double &amp;xSize, double &amp;x) { x = (double(xI)/double(INT_MAX))*xSize + xOffset; } int main() { typedef boost::geometry::model::polygon&lt;boost::geometry::model::d2::point_xy&lt;int&gt; &gt; polygon; typedef boost::geometry::model::d2::point_xy&lt;int&gt; Point; polygon green, blue; double greenPoints[4][2] = {{ 0, 0}, {0.05, 0.04}, {0.05, 0}, {0, 0}}; double bluePoints[4][2] = {{ 0.02, -2.77556e-17}, {0.05, 0.02}, {0.05 -2.77556e-17}, {0.02 -2.77556e-17}}; // Get the maximum extension // double min[2] = { INF__, INF__ }; double max[2] = { -INF__, -INF__ }; for(int i = 0; i &lt; 3; ++i ) { for(int j = 0; j &lt; 2; ++j) { min[j] = (greenPoints[i][j] &lt; min[j]) ? greenPoints[i][j] : min[j]; min[j] = (bluePoints[i][j] &lt; min[j]) ? bluePoints[i][j] : min[j]; max[j] = (greenPoints[i][j] &gt; max[j]) ? greenPoints[i][j] : max[j]; max[j] = (bluePoints[i][j] &gt; max[j]) ? bluePoints[i][j] : max[j]; } } std::cout &lt;&lt; "x-range: " &lt;&lt; min[0] &lt;&lt; " - " &lt;&lt; max[0] &lt;&lt; std::endl; std::cout &lt;&lt; "y-range: " &lt;&lt; min[1] &lt;&lt; " - " &lt;&lt; max[1] &lt;&lt; std::endl; double size[2] = { max[0] - min[0], max[1] - min[1] }; for(int i = 0; i &lt; 4; ++i) { { int xI, yI; mapPointToInt(greenPoints[i][0], min[0], size[0], xI); mapPointToInt(greenPoints[i][1], min[1], size[1], yI); boost::geometry::append(green, boost::geometry::make&lt;Point&gt;(xI, yI)); } { int xI, yI; mapPointToInt(bluePoints[i][0], min[0], size[0], xI); mapPointToInt(bluePoints[i][1], min[1], size[1], yI); boost::geometry::append(blue, boost::geometry::make&lt;Point&gt;(xI, yI)); } } boost::geometry::correct(green); boost::geometry::correct(blue); std::cout &lt;&lt; "green poly: " &lt;&lt; boost::geometry::dsv(green) &lt;&lt; std::endl; std::cout &lt;&lt; "blue poly: " &lt;&lt; boost::geometry::dsv(blue) &lt;&lt; std::endl; std::deque&lt;polygon&gt; output; boost::geometry::intersection(green, blue, output); int i = 0; std::cout &lt;&lt; "The computed difference is:" &lt;&lt; std::endl; BOOST_FOREACH(polygon const&amp; p, output) { std::cout &lt;&lt; boost::geometry::dsv(p) &lt;&lt; std::endl; } typedef boost::geometry::identity_view&lt; typename boost::geometry::ring_type&lt;polygon&gt;::type//, //boost::geometry::open &gt; view_type; view_type view(boost::geometry::exterior_ring(output[0])); for(auto it = boost::begin(view); it != boost::end(view); ++it) { double x, y; mapPointToFloatingPoint( boost::geometry::get&lt;0&gt;(*it), min[0], size[0], x); mapPointToFloatingPoint( boost::geometry::get&lt;1&gt;(*it), min[1], size[1], y); std::cout &lt;&lt; " (" &lt;&lt; x &lt;&lt; ", " &lt;&lt; y &lt;&lt; ")" &lt;&lt; std::endl; } } </pre> </description> <category>Ticket</category> </item> <item> <dc:creator>Barend Gehrels</dc:creator> <pubDate>Tue, 27 Aug 2013 20:57:06 GMT</pubDate> <title>status changed; resolution set https://svn.boost.org/trac10/ticket/8652#comment:4 https://svn.boost.org/trac10/ticket/8652#comment:4 <ul> <li><strong>status</strong> <span class="trac-field-old">new</span> → <span class="trac-field-new">closed</span> </li> <li><strong>resolution</strong> → <span class="trac-field-new">fixed</span> </li> </ul> <p> The boundaries of double are reached by using coordinates as specified. This results in rounding errors and imprecise results. </p> <p> One of the imprecise points which was generated is fixed in commit 85451 (will be released in Boost 1.55). </p> <p> The output was: POLYGON((0.05 0.02,0.05 -2.77556e-17,0.02 -2.77556e-17,0.05 0.02)) Area: 0.0003 </p> <p> The new output is: POLYGON((0.05 0.02,0.05 0,0.02 -2.77556e-17,0.05 0.02)) Area: 0.0003 </p> <p> So still not as your expectation but it comes closer. </p> <p> If you use "long double" (better suited for cases like this), the output is correct: The computed intersection is: POLYGON((0.05 0.02,0.05 0,0.02 0,0.05 0.02)) Area: 0.0003 </p> <p> (I changed output to WKT and added area in your testprogram). </p> <p> I will add a testcase for this ticket to avoid future regressions. </p> <p> SQL Server gives: POLYGON ((0.019999999552965164 0, 0.049999999813735485 0, 0.049999999813735485 0.019999999552965164, 0.019999999552965164 0)) Area: 0.000299999995902181 </p> <p> I did not check your integer-sample, if that is a separate problem, please create a separate ticket. </p> <p> Thanks for your report. </p> Ticket Barend Gehrels Tue, 27 Aug 2013 21:01:35 GMT milestone changed https://svn.boost.org/trac10/ticket/8652#comment:5 https://svn.boost.org/trac10/ticket/8652#comment:5 <ul> <li><strong>milestone</strong> <span class="trac-field-old">To Be Determined</span> → <span class="trac-field-new">Boost 1.55.0</span> </li> </ul> Ticket