Open Zeratul-Aiur opened 4 months ago
Thanks for opening this issue, I can reproduce it. It seems like a numerical issue. With more precision (long double
) boost geometry computes the desired result, i.e. ring2, result do not intersect nor overlap nor touch.
What's a good way to handle getting higher precision results from calculations performed with lower precision data?
As a user you have to create your input geometry with higher precision e.g.
using Point = bg::model::point<long double, 2, bg::cs::cartesian>;
or use a more precise data type e.g. from boost multiprecision.
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/geometries.hpp>
#include <iostream>
#include <iomanip>
namespace bg = boost::geometry;
template <typename T>
void test()
{
using point_t = bg::model::point<T, 2, bg::cs::cartesian>;
using ring_t = bg::model::ring<point_t, false, false>;
using polygon_t = bg::model::polygon<point_t, false, false>;
using mp_t = bg::model::multi_polygon<polygon_t>;
ring_t ring1{{255.999985, 255.999954},
{376.0, 223.846039},
{376.0, 421.0},
{368.0, 421.0},
{368.0, 420.0},
{350.685455, 420.0}};
ring_t ring2{{437.019287, -57.5347023},
{503.276947, 189.742279},
{8.72293091, 322.257660},
{-57.5347290, 74.9806824}};
bg::correct(ring1);
bg::correct(ring2);
mp_t diff, inters;
bg::difference(ring1, ring2, diff);
bg::intersection(ring1, ring2, inters);
std::cout << std::setprecision(12) << std::boolalpha;
std::cout
<< "Type: " << typeid(T).name()
<< " a: " << bg::area(ring1)
<< " b: " << bg::area(ring2)
<< " d: " << bg::area(diff)
<< " i: " << bg::area(inters)
<< " b-a: " << bg::area(ring2) - bg::area(ring1)
<< " overlaps: " << bg::overlaps(diff, ring2)
<< " intersects: " << bg::intersects(diff, ring2)
<< " touch: " << bg::touches(diff, ring2)
<< std::endl;
}
int main() {
test<float>();
test<double>();
test<long double>();
}
Type: f a: 13853.0324104 b: 131071.982442 d: 13853.0324104 i: 0 b-a: 117218.950032 intersects: true overlaps: true touch: false
Type: d a: 13853.0324034 b: 131071.982438 d: 13853.0320132 i: 0.000390214508673 b-a: 117218.950035 intersects: false overlaps: false touch: false
Type: e a: 13853.0324034 b: 131071.982438 d: 13853.0320132 i: 0.000390214508673 b-a: 117218.950035 intersects: false overlaps: false touch: false
So yes, it looks like I can reproduce it as well (note that on my mac there is no difference in double/long double types). The difference/intersections themselves look OK, is that correct? (I didn't visualize it) So there must be an error in the boolean predicates.
BTW the reason that I checked it again is that I have a concept fix for another recent issue and wanted to check if it would fix this as well. But that is related to the spatial set operations, and not to the predicates.
Hi,
I obtained the difference between the two rings and found that the result intersects with the original ring, but it neither overlaps nor touches it. I think in the case of intersection,
overlaps(A, B) == !touches(A, B)
.example code:
version: 1.85.0