|
|
If differences between points are very small, it may lead to false result of a mathematical calculation performed on such points, what in turn, may cause algorithm result as inadequate to actual geometric situation. For example, a point which is located left from a segment, but very close to it, can be reported on that segment or right from it. Also if differences are a little larger, artifacts can be shown in geometric algorithms.
See for more backgrounds e.g.:
GGL is aware of these issues and provides several approaches to minimize the problems, or avoid them completely using
Also if the left edge is longer than that, or using double coordinates, those effects will be there. And of course not only in triangles, but any spiky feature in a polygon can result in non representable coordinates or zero-length edges.
By default, algorithms select the coordinate type of the input geometries. If there are two input geometries, and they have different coordinate types, the coordinate type with the most precision is selected. This is done by the meta-function select_most_precise.
GGL supports also high precision arithmetic types, by adaption. The numeric_adaptor, used for adaption, is not part of GGL itself but developed by us and sent (as preview) to the Boost List (as it turned out, that functionality might also be provided by Boost.Math bindings, but the mechanism is the same). Types from the following libraries are supported:
Note that the libraries themselves are not included in GGL, they are completely independant of each other.
These numeric types can be used as following:
ggl::point_xy<boost::numeric_adaptor::gmp_value_type> p4; ggl::point_xy<boost::numeric_adaptor::cln_value_type> p5;
{
typedef ggl::point_xy<double> point_type;
ggl::linear_ring<point_type> ring;
ring.push_back(ggl::make<point_type>(0.0, 0.0));
ring.push_back(ggl::make<point_type>(0.0, 0.0012));
ring.push_back(ggl::make<point_type>(1234567.89012345, 0.0));
ring.push_back(ring.front());
typedef boost::numeric_adaptor::gmp_value_type gmp;
gmp area = ggl::area(ring, ggl::strategy::area::by_triangles<point_type, gmp>());
std::cout << area << std::endl;
}
The image below is drawn in PowerPoint to predict what would happen at an intersection of two triangles using float coordinates in the range 1e-45.
If we perform the intersection using GGL, we get the effect that is presented on the pictures below, using float (left) and using double (right).
This shows how double can solve issues which might be present in float. However, there are also cases which cannot be solved by double or long double. And there are also cases which give more deviations than just a move of the intersection points.
We investigated this and created an artificial case. In this case, there are two stars, they are the same but one of them is rotated over an interval of about 1e-44. When those stars are intersected, the current GGL implementation using float, double or long double will give some artifacts.
Those artifacts are caused by taking the wrong paths on points where distances are zero (because they cannot be expressed in the used coordinate systems).
If using GMP or CLN, the intersection is correct.
Note again, these things happen in differences of about 1e-45. We can investigate if they can be reduced or sometimes even solved. However, they belong to the floating point approach, which is not exact.
For many users, this all is not relevant. Using double they will be able to do all operations without any problems or artefacts. They can occur in real life, where differences are very small, or very large. Those users can use GMP to use GGL without any problem.
Therefore we decided to go for supporting high precision numeric types first, and they are currently supported in most algorithms (a.o. area, length, perimeter, distance, centroid, intersection, union). However, we certainly are willing to take other measures as well.
|
November 19, 2009 |
Copyright © 1995-2009 Barend Gehrels, Geodan, Amsterdam Copyright © 2008-2009 Bruno Lalande, Paris Copyright © 2009 Mateusz Loskot, Cadcorp, London |