Skip to content

Commit 4143db7

Browse files
committed
Use tighter bounds and faster filters in orientation and isInCircle predicates.
1 parent 701c868 commit 4143db7

File tree

2 files changed

+59
-45
lines changed

2 files changed

+59
-45
lines changed

include/geos/algorithm/CGAlgorithmsDD.h

Lines changed: 6 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
#include <geos/export.h>
2222
#include <geos/math/DD.h>
23+
#include <cmath>
2324

2425
// Forward declarations
2526
namespace geos {
@@ -92,41 +93,14 @@ class GEOS_DLL CGAlgorithmsDD {
9293
double pbx, double pby,
9394
double pcx, double pcy)
9495
{
95-
/**
96-
* A value which is safely greater than the relative round-off
97-
* error in double-precision numbers
98-
*/
99-
double constexpr DP_SAFE_EPSILON = 1e-15;
100-
101-
double detsum;
10296
double const detleft = (pax - pcx) * (pby - pcy);
10397
double const detright = (pay - pcy) * (pbx - pcx);
10498
double const det = detleft - detright;
105-
106-
if(detleft > 0.0) {
107-
if(detright <= 0.0) {
108-
return orientation(det);
109-
}
110-
else {
111-
detsum = detleft + detright;
112-
}
113-
}
114-
else if(detleft < 0.0) {
115-
if(detright >= 0.0) {
116-
return orientation(det);
117-
}
118-
else {
119-
detsum = -detleft - detright;
120-
}
121-
}
122-
else {
123-
return orientation(det);
124-
}
125-
126-
double const errbound = DP_SAFE_EPSILON * detsum;
127-
if((det >= errbound) || (-det >= errbound)) {
128-
return orientation(det);
129-
}
99+
// Coefficient due to https://doi.org/10.1007/s10543-015-0574-9
100+
double const error = std::abs(detleft + detright)
101+
* 3.3306690621773714e-16;
102+
if (std::abs(det) >= error)
103+
return (det > 0) - (det < 0);
130104
return CGAlgorithmsDD::FAILURE;
131105
};
132106

src/triangulate/quadedge/TrianglePredicate.cpp

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,16 +29,30 @@ namespace quadedge {
2929

3030
geom::Location
3131
TrianglePredicate::isInCircleNonRobust(
32-
const CoordinateXY& a, const CoordinateXY& b, const CoordinateXY& c,
33-
const CoordinateXY& p)
32+
const CoordinateXY& p, const CoordinateXY& q, const CoordinateXY& r,
33+
const CoordinateXY& t)
3434
{
35-
auto det =
36-
(a.x * a.x + a.y * a.y) * triArea(b, c, p)
37-
- (b.x * b.x + b.y * b.y) * triArea(a, c, p)
38-
+ (c.x * c.x + c.y * c.y) * triArea(a, b, p)
39-
- (p.x * p.x + p.y * p.y) * triArea(a, b, c);
40-
41-
return det > 0 ? geom::Location::EXTERIOR : (det < 0 ? geom::Location::INTERIOR : geom::Location::BOUNDARY);
35+
auto qpx = q.x - p.x;
36+
auto qpy = q.y - p.y;
37+
auto rpx = r.x - p.x;
38+
auto rpy = r.y - p.y;
39+
auto tpx = t.x - p.x;
40+
auto tpy = t.y - p.y;
41+
auto tqx = t.x - q.x;
42+
auto tqy = t.y - q.y;
43+
auto rqx = r.x - q.x;
44+
auto rqy = r.y - q.y;
45+
auto qpxtpy = qpx * tpy;
46+
auto qpytpx = qpy * tpx;
47+
auto tpxtqx = tpx * tqx;
48+
auto tpytqy = tpy * tqy;
49+
auto qpxrpy = qpx * rpy;
50+
auto qpyrpx = qpy * rpx;
51+
auto rpxrqx = rpx * rqx;
52+
auto rpyrqy = rpy * rqy;
53+
auto det = (qpxtpy - qpytpx) * (rpxrqx + rpyrqy)
54+
- (qpxrpy - qpyrpx) * (tpxtqx + tpytqy);
55+
return static_cast<geom::Location>( (det > 0) - (det < 0) + 1 );
4256
}
4357

4458
geom::Location
@@ -91,11 +105,37 @@ TrianglePredicate::triArea(const CoordinateXY& a,
91105

92106
geom::Location
93107
TrianglePredicate::isInCircleRobust(
94-
const CoordinateXY& a, const CoordinateXY& b, const CoordinateXY& c,
95-
const CoordinateXY& p)
108+
const CoordinateXY& q, const CoordinateXY& p, const CoordinateXY& r,
109+
const CoordinateXY& t)
96110
{
97-
// This implementation is not robust, name is ported from JTS.
98-
return isInCircleNormalized(a, b, c, p);
111+
// This implementation is not robust and defaults to BOUNDARY in case of
112+
// uncertainty.
113+
auto qpx = q.x - p.x;
114+
auto qpy = q.y - p.y;
115+
auto rpx = r.x - p.x;
116+
auto rpy = r.y - p.y;
117+
auto tpx = t.x - p.x;
118+
auto tpy = t.y - p.y;
119+
auto tqx = t.x - q.x;
120+
auto tqy = t.y - q.y;
121+
auto rqx = r.x - q.x;
122+
auto rqy = r.y - q.y;
123+
auto qpxtpy = qpx * tpy;
124+
auto qpytpx = qpy * tpx;
125+
auto tpxtqx = tpx * tqx;
126+
auto tpytqy = tpy * tqy;
127+
auto qpxrpy = qpx * rpy;
128+
auto qpyrpx = qpy * rpx;
129+
auto rpxrqx = rpx * rqx;
130+
auto rpyrqy = rpy * rqy;
131+
auto det = (qpxtpy - qpytpx) * (rpxrqx + rpyrqy)
132+
- (qpxrpy - qpyrpx) * (tpxtqx + tpytqy);
133+
auto deterror = ((std::abs(qpxtpy) + std::abs(qpytpx))
134+
* (std::abs(rpxrqx) + std::abs(rpyrqy))
135+
+ (std::abs(qpxrpy) + std::abs(qpyrpx))
136+
* (std::abs(tpxtqx) + std::abs(tpytqy)))
137+
* 9.99200719823023e-16;
138+
return static_cast<geom::Location>( (det > deterror) - (det < -deterror) + 1 );
99139
}
100140

101141
} // namespace geos.triangulate.quadedge

0 commit comments

Comments
 (0)