Codebase list geos / bfa475f
New upstream version 3.10.0~beta3 Bas Couwenberg 2 years ago
44 changed file(s) with 687 addition(s) and 218 deletion(s). Raw diff Collapse all Expand all
+0
-75
INSTALL less more
0 ## Building GEOS From Source
1
2 ### Prerequisites
3
4 GEOS has no external library dependencies and can be built with any C++11
5 compiler.
6
7 ### Unix
8
9 GEOS can be built on Unix systems using the CMake build system.
10
11 #### Using CMake:
12
13 To build `GEOS` using CMake, create a build directory and run the `cmake` command
14 from that location:
15
16 mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release ..
17
18 Setting `CMAKE_BUILD_TYPE` to `Release` is necessary to enable compiler
19 optimizations.
20
21 Once the `cmake` tool has run, GEOS can be built by running `make` and
22 installed by running `make install`.
23
24 The entire test suite can be run using `make check`.
25 Alternatively, the `ctest` command can be used, which provides more control over test execution.
26 For example, `ctest -R unit-capi -j2` uses a regular expression to run all tests
27 associated with the C API, using two processes in parallel.
28 A list of available tests can be obtained using `ctest -N`.
29
30 ### Microsoft Windows
31
32 GEOS can be built with Microsoft Visual C++ by opening the `CMakeLists.txt` in
33 the project root using `File > Open > CMake`.
34
35 If you prefer the command-line
36
37 #### Build with CMake generator for Ninja (fast)
38
39 In the Visual Studio 2019 command prompt, `x64 Native Tools Command Prompt for VS 2019` or `x64_x86 Cross Tools Command Prompt for VS 2019`:
40
41 ```
42 cmake -S . -B _build_vs2019_ninja -G Ninja -DCMAKE_BUILD_TYPE=Release
43 cmake --build _build_vs2019_ninja -j 16 --verbose
44 ```
45
46 #### Build with CMake generator for MSBuild (default)
47
48 In the non-specific Command Prompt:
49
50 ##### 64-bit
51
52 ```
53 cmake -S . -B _build_vs2019x64 -G "Visual Studio 16 2019" -A x64 -DCMAKE_GENERATOR_TOOLSET=host=x64
54 cmake --build _build_vs2019x64 --config Release -j 16 --verbose
55 ```
56
57 ##### 32-bit
58
59 ```
60 cmake -S . -B _build_vs2019x32 -G "Visual Studio 16 2019" -A x32 -DCMAKE_GENERATOR_TOOLSET=host=x64
61 cmake --build _build_vs2019x32 --config Release -j 16 --verbose
62 ```
63
64 #### Test using CMake
65
66 ```
67 cd <build directory>
68 ctest --show-only
69 ctest
70 ctest --output-on-failure
71 ctest -V
72 ctest -VV
73 ```
74
0 ## Building GEOS From Source
1
2 ### Prerequisites
3
4 GEOS has no external library dependencies and can be built with any C++11
5 compiler.
6
7 ### Unix
8
9 GEOS can be built on Unix systems using the CMake build system.
10
11 #### Using CMake:
12
13 To build `GEOS` using CMake, create a build directory and run the `cmake` command
14 from that location:
15
16 mkdir build && cd build && cmake -DCMAKE_BUILD_TYPE=Release ..
17
18 Setting `CMAKE_BUILD_TYPE` to `Release` is necessary to enable compiler
19 optimizations.
20
21 Once the `cmake` tool has run, GEOS can be built by
22
23 * running `make` and installed by running `make install`, or
24 * running `cmake --build .` and `cmake --build . --target install`
25
26 The entire test suite can be run by
27
28 * using `make check`, or
29 * using `ctest --output-on-failure .`
30
31 The `ctest` command can be used to control which tests are run.
32 For example, `ctest -R unit-capi -j2` uses a regular expression to run all tests
33 associated with the C API, using two processes in parallel.
34 A list of available tests can be obtained using `ctest -N`.
35
36 ### Microsoft Windows
37
38 GEOS can be built with Microsoft Visual C++ by opening the `CMakeLists.txt` in
39 the project root using `File > Open > CMake`.
40
41 If you prefer the command-line
42
43 #### Build with CMake generator for Ninja (fast)
44
45 In the Visual Studio 2019 command prompt, `x64 Native Tools Command Prompt for VS 2019` or `x64_x86 Cross Tools Command Prompt for VS 2019`:
46
47 ```
48 cmake -S . -B _build_vs2019_ninja -G Ninja -DCMAKE_BUILD_TYPE=Release
49 cmake --build _build_vs2019_ninja -j 16 --verbose
50 ```
51
52 #### Build with CMake generator for MSBuild (default)
53
54 In the non-specific Command Prompt:
55
56 ##### 64-bit
57
58 ```
59 cmake -S . -B _build_vs2019x64 -G "Visual Studio 16 2019" -A x64 -DCMAKE_GENERATOR_TOOLSET=host=x64
60 cmake --build _build_vs2019x64 --config Release -j 16 --verbose
61 ```
62
63 ##### 32-bit
64
65 ```
66 cmake -S . -B _build_vs2019x32 -G "Visual Studio 16 2019" -A x32 -DCMAKE_GENERATOR_TOOLSET=host=x64
67 cmake --build _build_vs2019x32 --config Release -j 16 --verbose
68 ```
69
113113 in the default build. To build the documentation, run:
114114
115115 cmake -DBUILD_DOCUMENTATION=YES
116 make docs
116 cmake --build . --target docs
117117
118118 ## Style
119119
44 GEOS_VERSION_PATCH=0
55
66 # OPTIONS: "", "dev", "rc1" etc.
7 GEOS_PATCH_WORD=beta2
7 GEOS_PATCH_WORD=beta3
88
99 # GEOS CAPI Versions
1010 #
3838 class GEOS_DLL Angle {
3939 public:
4040
41 static const double PI_TIMES_2; // 2.0 * PI;
42 static const double PI_OVER_2; // PI / 2.0;
43 static const double PI_OVER_4; // PI / 4.0;
41 static constexpr double PI_TIMES_2 = 2.0 * MATH_PI;
42 static constexpr double PI_OVER_2 = MATH_PI / 2.0;
43 static constexpr double PI_OVER_4 = MATH_PI / 4.0;
4444
4545 /// Constant representing counterclockwise orientation
4646 static const int COUNTERCLOCKWISE = Orientation::COUNTERCLOCKWISE;
139139 findNearestPoint(const geom::Coordinate& p,
140140 const std::vector<geom::Coordinate>& pts) const
141141 {
142 double minDistSq = std::numeric_limits<double>::max();
142 double minDistSq = DoubleInfinity;
143143 geom::Coordinate result = geom::Coordinate::getNull();
144144 for(std::size_t i = 0, n = pts.size(); i < n; ++i) {
145145 double distSq = p.distanceSquared(pts[i]);
1616 *
1717 *********************************************************************/
1818
19 #ifndef INCLUDE_GEOS_CONSTANTS_H_
20 #define INCLUDE_GEOS_CONSTANTS_H_
19 #pragma once
2120
2221 #ifdef _MSC_VER
2322 #ifndef NOMINMAX
3433
3534 constexpr double MATH_PI = 3.14159265358979323846;
3635
37
38
3936 // Some handy constants
4037 constexpr double DoubleNotANumber = std::numeric_limits<double>::quiet_NaN();
4138 constexpr double DoubleMax = (std::numeric_limits<double>::max)();
4239 constexpr double DoubleInfinity = (std::numeric_limits<double>::infinity)();
4340 constexpr double DoubleNegInfinity = (-(std::numeric_limits<double>::infinity)());
41 constexpr double DoubleEpsilon = std::numeric_limits<double>::epsilon();
4442
45 } // namespace geos
43 } // namespace geos
4644
47
48 #endif // INCLUDE_GEOS_CONSTANTS_H_
3434 /*public*/
3535 INLINE
3636 Envelope::Envelope() :
37 minx(std::numeric_limits<double>::quiet_NaN()),
38 maxx(std::numeric_limits<double>::quiet_NaN()),
39 miny(std::numeric_limits<double>::quiet_NaN()),
40 maxy(std::numeric_limits<double>::quiet_NaN())
37 minx(DoubleNotANumber),
38 maxx(DoubleNotANumber),
39 miny(DoubleNotANumber),
40 maxy(DoubleNotANumber)
4141 {}
4242
4343 /*public*/
297297 INLINE void
298298 Envelope::setToNull()
299299 {
300 minx = maxx = miny = maxy = std::numeric_limits<double>::quiet_NaN();
300 minx = maxx = miny = maxy = DoubleNotANumber;
301301 }
302302
303303 INLINE double
4646 }
4747
4848 ItemPair nearestNeighbour(NodePair& initPair) {
49 return nearestNeighbour(initPair, std::numeric_limits<double>::infinity());
49 return nearestNeighbour(initPair, DoubleInfinity);
5050 }
5151
5252 private:
144144 NodePair sp = isFlipped ? NodePair(nodeOther, *child, m_id) : NodePair(*child, nodeOther, m_id);
145145
146146 // only add to queue if this pair might contain the closest points
147 if (minDistance == std::numeric_limits<double>::infinity() || sp.getDistance() < minDistance) {
147 if (minDistance == DoubleInfinity || sp.getDistance() < minDistance) {
148148 priQ.push(sp);
149149 }
150150 }
2323 namespace geos {
2424 namespace algorithm { // geos.algorithm
2525
26 namespace {
27 const double PI = 3.14159265358979323846;
28 }
29
30 const double Angle::PI_TIMES_2 = 2.0 * PI;
31 const double Angle::PI_OVER_2 = PI / 2.0;
32 const double Angle::PI_OVER_4 = PI / 4.0;
3326
3427 /* public static */
3528 double
3629 Angle::toDegrees(double radians)
3730 {
38 return (radians * 180) / (PI);
31 return (radians * 180) / (MATH_PI);
3932 }
4033
4134 /* public static */
4235 double
4336 Angle::toRadians(double angleDegrees)
4437 {
45 return (angleDegrees * PI) / 180.0;
38 return (angleDegrees * MATH_PI) / 180.0;
4639 }
4740
4841 /* public static */
115108 double angDel = a2 - a1;
116109
117110 // normalize, maintaining orientation
118 if(angDel <= -PI) {
111 if(angDel <= -MATH_PI) {
119112 return angDel + PI_TIMES_2;
120113 }
121 if(angDel > PI) {
114 if(angDel > MATH_PI) {
122115 return angDel - PI_TIMES_2;
123116 }
124117 return angDel;
153146 double
154147 Angle::normalize(double angle)
155148 {
156 while(angle > PI) {
149 while(angle > MATH_PI) {
157150 angle -= PI_TIMES_2;
158151 }
159 while(angle <= -PI) {
152 while(angle <= -MATH_PI) {
160153 angle += PI_TIMES_2;
161154 }
162155 return angle;
200193 delAngle = ang1 - ang2;
201194 }
202195
203 if(delAngle > PI) {
204 delAngle = (2 * PI) - delAngle;
196 if(delAngle > MATH_PI) {
197 delAngle = (2 * MATH_PI) - delAngle;
205198 }
206199
207200 return delAngle;
3939
4040 InteriorPointLine::InteriorPointLine(const Geometry* g)
4141 {
42 minDistance = DoubleMax;
42 minDistance = DoubleInfinity;
4343 hasInterior = false;
4444 if (g->getCentroid(centroid)) {
4545 #if GEOS_DEBUG
3232 /*public*/
3333 InteriorPointPoint::InteriorPointPoint(const Geometry* g)
3434 {
35 minDistance = DoubleMax;
35 minDistance = DoubleInfinity;
3636 if (! g->getCentroid(centroid)) {
3737 hasInterior = false;
3838 }
346346 * intersect.
347347 */
348348 Coordinate p;
349 double z = std::numeric_limits<double>::quiet_NaN();
349 double z = DoubleNotANumber;
350350
351351 if(Pq1 == 0 || Pq2 == 0 || Qp1 == 0 || Qp2 == 0) {
352352
298298 Coordinate
299299 MinimumBoundingCircle::pointWitMinAngleWithX(std::vector<Coordinate>& pts, Coordinate& P)
300300 {
301 double minSin = std::numeric_limits<double>::max();
301 double minSin = DoubleInfinity;
302302 Coordinate minAngPt;
303303 minAngPt.setNull();
304304 for(const auto& p : pts) {
332332 MinimumBoundingCircle::pointWithMinAngleWithSegment(std::vector<Coordinate>& pts, Coordinate& P, Coordinate& Q)
333333 {
334334 assert(!pts.empty());
335 double minAng = std::numeric_limits<double>::max();
335 double minAng = DoubleInfinity;
336336 const Coordinate* minAngPt = &pts[0];
337337
338338 for(const auto& p : pts) {
214214 void
215215 MinimumDiameter::computeConvexRingMinDiameter(const CoordinateSequence* pts)
216216 {
217 minWidth = DoubleMax;
217 minWidth = DoubleInfinity;
218218 unsigned int currMaxIndex = 1;
219219 LineSegment seg;
220220
284284 double dx = minBaseSeg.p1.x - minBaseSeg.p0.x;
285285 double dy = minBaseSeg.p1.y - minBaseSeg.p0.y;
286286
287 double minPara = DoubleMax;
288 double maxPara = -DoubleMax;
289 double minPerp = DoubleMax;
290 double maxPerp = -DoubleMax;
287 double minPara = DoubleInfinity;
288 double maxPara = DoubleNegInfinity;
289 double minPerp = DoubleInfinity;
290 double maxPerp = DoubleNegInfinity;
291291
292292 // compute maxima and minima of lines parallel and perpendicular to base segment
293293 std::size_t const n = convexHullPts->getSize();
166166 BasicPreparedGeometry::distance(const geom::Geometry* g) const
167167 {
168168 std::unique_ptr<geom::CoordinateSequence> coords = nearestPoints(g);
169 if ( ! coords ) return std::numeric_limits<double>::infinity();
169 if ( ! coords ) return DoubleInfinity;
170170 return coords->getAt(0).distance( coords->getAt(1) );
171171 }
172172
2828 {
2929 if ( prepLine.getGeometry().isEmpty() || g->isEmpty() )
3030 {
31 return std::numeric_limits<double>::infinity();
31 return DoubleInfinity;
3232 }
3333
3434 // TODO: test if this shortcut be any useful
3232 {
3333 if ( prepPoly.getGeometry().isEmpty() || g->isEmpty() )
3434 {
35 return std::numeric_limits<double>::infinity();
35 return DoubleInfinity;
3636 }
3737
3838 if ( prepPoly.intersects(g) ) return 0.0;
135135 bp.reset(new BoundablePair(child, bndOther, itemDistance));
136136 }
137137
138 if (minDistance == std::numeric_limits<double>::infinity() || bp->getDistance() < minDistance) {
138 if (minDistance == DoubleInfinity || bp->getDistance() < minDistance) {
139139 priQ.push(bp.release());
140140 }
141141
155155 std::pair<const void*, const void*>
156156 STRtree::nearestNeighbour(BoundablePair* initBndPair)
157157 {
158 return nearestNeighbour(initBndPair, std::numeric_limits<double>::infinity());
158 return nearestNeighbour(initBndPair, DoubleInfinity);
159159 }
160160
161161 /*public*/
243243 /*private*/
244244 bool STRtree::isWithinDistance(BoundablePair* initBndPair, double maxDistance)
245245 {
246 double distanceUpperBound = std::numeric_limits<double>::infinity();
246 double distanceUpperBound = DoubleInfinity;
247247
248248 // initialize search queue
249249 BoundablePair::BoundablePairQueue priQ;
5858 std::pair<const void*, const void*>
5959 SimpleSTRdistance::nearestNeighbour(SimpleSTRpair* p_initPair)
6060 {
61 return nearestNeighbour(p_initPair, std::numeric_limits<double>::infinity());
61 return nearestNeighbour(p_initPair, DoubleInfinity);
6262 }
6363
6464
198198 bool
199199 SimpleSTRdistance::isWithinDistance(SimpleSTRpair* p_initPair, double maxDistance)
200200 {
201 double distanceUpperBound = std::numeric_limits<double>::infinity();
201 double distanceUpperBound = DoubleInfinity;
202202
203203 // initialize search queue
204204 STRpairQueue priQ;
1717 **********************************************************************/
1818
1919 #include <geos/io/StringTokenizer.h>
20 #include <geos/constants.h>
2021
2122 #include <string>
2223 #include <cstdlib>
5758
5859 if(stricmp(pos, "inf") == 0) {
5960 if(!sign || sign == '+') {
60 dbl = std::numeric_limits<double>::infinity();
61 dbl = DoubleInfinity;
6162 }
6263 else {
63 dbl = -(std::numeric_limits<double>::infinity)();
64 dbl = DoubleNegInfinity;
6465 }
6566 *str_end[0] = '\0';
6667 }
6768 else if(stricmp(pos, "nan") == 0) {
68 dbl = std::numeric_limits<double>::quiet_NaN();
69 dbl = DoubleNotANumber;
6970 *str_end[0] = '\0';
7071 }
7172 }
8383 double
8484 LengthIndexOfPoint::indexOfFromStart(const Coordinate& inputPt, double minIndex) const
8585 {
86 double minDistance = std::numeric_limits<double>::max();
86 double minDistance = DoubleInfinity;
8787
8888 double ptMeasure = minIndex;
8989 double segmentStartMeasure = 0.0;
3838 LocationIndexOfPoint::indexOfFromStart(const Coordinate& inputPt,
3939 const LinearLocation* minIndex) const
4040 {
41 double minDistance = std::numeric_limits<double>::max();
41 double minDistance = DoubleInfinity;
4242 std::size_t minComponentIndex = 0;
4343 std::size_t minSegmentIndex = 0;
4444 double minFrac = -1.0;
4848
4949 /*private data*/
5050 const double OffsetSegmentGenerator::CURVE_VERTEX_SNAP_DISTANCE_FACTOR = 1.0E-6;
51 const double OffsetSegmentGenerator::PI = 3.14159265358979;
5251 const double OffsetSegmentGenerator::OFFSET_SEGMENT_SEPARATION_FACTOR = 1.0E-3;
5352 const double OffsetSegmentGenerator::INSIDE_TURN_VERTEX_SNAP_DISTANCE_FACTOR = 1.0E-3;
5453 const double OffsetSegmentGenerator::SIMPLIFY_FACTOR = 100.0;
7978 {
8079 // compute intersections in full precision, to provide accuracy
8180 // the points are rounded as they are inserted into the curve line
82 filletAngleQuantum = PI / 2.0 / bufParams.getQuadrantSegments();
81 filletAngleQuantum = MATH_PI / 2.0 / bufParams.getQuadrantSegments();
8382
8483 /*
8584 * Non-round joins cause issues with short closing segments,
204203 case BufferParameters::CAP_ROUND:
205204 // add offset seg points with a fillet between them
206205 segList.addPt(offsetL.p1);
207 addDirectedFillet(p1, angle + PI / 2.0, angle - PI / 2.0,
206 addDirectedFillet(p1, angle + MATH_PI / 2.0, angle - MATH_PI / 2.0,
208207 Orientation::CLOCKWISE, distance);
209208 segList.addPt(offsetR.p1);
210209 break;
246245
247246 if(direction == Orientation::CLOCKWISE) {
248247 if(startAngle <= endAngle) {
249 startAngle += 2.0 * PI;
248 startAngle += 2.0 * MATH_PI;
250249 }
251250 }
252251 else { // direction==COUNTERCLOCKWISE
253252 if(startAngle >= endAngle) {
254 startAngle -= 2.0 * PI;
253 startAngle -= 2.0 * MATH_PI;
255254 }
256255 }
257256
291290 // add start point
292291 Coordinate pt(p.x + p_distance, p.y);
293292 segList.addPt(pt);
294 addDirectedFillet(p, 0.0, 2.0 * PI, -1, p_distance);
293 addDirectedFillet(p, 0.0, 2.0 * MATH_PI, -1, p_distance);
295294 segList.closeRing();
296295 }
297296
510509 // angle for bisector of the interior angle between the segments
511510 double midAng = Angle::normalize(ang0 + angDiffHalf);
512511 // rotating this by PI gives the bisector of the reflex angle
513 double mitreMidAng = Angle::normalize(midAng + PI);
512 double mitreMidAng = Angle::normalize(midAng + MATH_PI);
514513
515514 // the miterLimit determines the distance to the mitre bevel
516515 double mitreDist = p_mitreLimit * p_distance;
8181 DistanceOp::DistanceOp(const Geometry* g0, const Geometry* g1):
8282 geom{{g0, g1}},
8383 terminateDistance(0.0),
84 minDistance(DoubleMax)
84 minDistance(DoubleInfinity)
8585 {}
8686
8787 DistanceOp::DistanceOp(const Geometry& g0, const Geometry& g1):
8888 geom{{&g0, &g1}},
8989 terminateDistance(0.0),
90 minDistance(DoubleMax)
90 minDistance(DoubleInfinity)
9191 {}
9292
9393 DistanceOp::DistanceOp(const Geometry& g0, const Geometry& g1, double tdist)
9494 :
9595 geom{{&g0, &g1}},
9696 terminateDistance(tdist),
97 minDistance(DoubleMax)
97 minDistance(DoubleInfinity)
9898 {}
9999
100100 /**
527527 double distance)
528528 {
529529 // check envelope distance for a short-circuit negative result
530 if ( g0.isEmpty() || g1.isEmpty() ) return false;
530531 const Envelope* env0 = g0.getEnvelopeInternal();
531532 const Envelope* env1 = g1.getEnvelopeInternal();
532533 double envDist = env0->distance(*env1);
121121 const FacetSequence& facetSeq,
122122 std::vector<GeometryLocation> *locs) const
123123 {
124 double minDistance = std::numeric_limits<double>::infinity();
124 double minDistance = DoubleInfinity;
125125
126126 for(std::size_t i = facetSeq.start; i < facetSeq.end - 1; i++) {
127127 const Coordinate& q0 = facetSeq.pts->getAt(i);
159159 double
160160 FacetSequence::computeDistanceLineLine(const FacetSequence& facetSeq, std::vector<GeometryLocation> *locs) const
161161 {
162 double minDistance = std::numeric_limits<double>::infinity();
162 double minDistance = DoubleInfinity;
163163
164164 for(std::size_t i = start; i < end - 1; i++) {
165165 const Coordinate& p0 = pts->getAt(i);
141141 bool
142142 EdgeNodingBuilder::hasEdgesFor(uint8_t geomIndex) const
143143 {
144 assert(geomIndex >= 0 && geomIndex < 2);
144 assert(geomIndex < 2);
145145 return hasEdges[geomIndex];
146146 }
147147
2727 #include <geos/operation/valid/IndexedNestedHoleTester.h>
2828 #include <geos/operation/valid/IndexedNestedPolygonTester.h>
2929 #include <geos/util/UnsupportedOperationException.h>
30 #include <geos/util/IllegalArgumentException.h>
3031
3132 #include <cmath>
3233
8081 IsValidOp::isValidGeometry(const Geometry* g)
8182 {
8283 validErr.reset(nullptr);
84
85 if (!g)
86 throw util::IllegalArgumentException("Null geometry argument to IsValidOp");
8387
8488 // empty geometries are always valid
8589 if (g->isEmpty()) return true;
4545 compute();
4646
4747 // return empty line string if no min pts were found
48 if(minClearance == std::numeric_limits<double>::infinity()) {
48 if (minClearance == DoubleInfinity) {
4949 return inputGeom->getFactory()->createLineString();
5050 }
5151
7171
7272 public:
7373 MinClearanceDistance() :
74 minDist(std::numeric_limits<double>::infinity()),
74 minDist(DoubleInfinity),
7575 minPts(std::vector<Coordinate>(2))
7676 {}
7777
8383
8484 double operator()(const FacetSequence* fs1, const FacetSequence* fs2)
8585 {
86 minDist = std::numeric_limits<double>::infinity();
86 minDist = DoubleInfinity;
8787 return distance(fs1, fs2);
8888 }
8989
166166 // initialize to "No Distance Exists" state
167167 minClearancePts = std::unique_ptr<CoordinateSequence>(inputGeom->getFactory()->getCoordinateSequenceFactory()->create(2,
168168 2));
169 minClearance = std::numeric_limits<double>::infinity();
169 minClearance = DoubleInfinity;
170170
171171 // handle empty geometries
172172 if(inputGeom->isEmpty()) {
132132 std::size_t shortestHoleVertexIndex = 0;
133133 //--- pick the shell-hole vertex pair that gives the shortest distance
134134 if (std::abs(shellCoord.x - holeCoord.x) < EPS) {
135 double shortest = std::numeric_limits<double>::max();
135 double shortest = DoubleInfinity;
136136 for (std::size_t i = 0; i < holeLeftVerticesIndex.size(); i++) {
137137 for (std::size_t j = 0; j < shellCoordsList.size(); j++) {
138138 double shellCoordY = shellCoordsList[j].y;
1818
1919 typedef geos::algorithm::LineIntersector RobustLineIntersector;
2020
21 #define DoubleNaN std::numeric_limits<double>::quiet_NaN()
22
2321 namespace tut {
2422 //
2523 // Test Group
184182 {
185183 checkIntersection(
186184 line(1, 1, 1, 3, 3, 3),
187 line(1, 3, 10, 3, 1, DoubleNaN),
185 line(1, 3, 10, 3, 1, geos::DoubleNotANumber),
188186 pt(2, 2, 6));
189187 }
190188
205203 ()
206204 {
207205 checkIntersection( line(1, 1, 3, 3), line(3, 3, 3, 1),
208 pt(3, 3, DoubleNaN));
206 pt(3, 3, geos::DoubleNotANumber));
209207 }
210208
211209 // testEndpoint2D3D
1414 #include <geos/geom/PrecisionModel.h>
1515 #include <geos/io/WKTReader.h>
1616 #include <geos/io/WKTWriter.h>
17 #include <geos/constants.h>
1718 // std
1819 #include <sstream>
1920 #include <string>
88 #include <cstdarg>
99 #include <cstdio>
1010 #include <cstdlib>
11 #include <fenv.h>
1112 #include <memory>
1213 #include <math.h>
1314
116117 GEOSGeom_destroy(g2);
117118 }
118119
120 // point distance does not raise floating point exception
121 template<>
122 template<>
123 void object::test<4>
124 ()
125 {
126 GEOSGeometry* g1 = GEOSGeomFromWKT("POINT (0 0)");
127 GEOSGeometry* g2 = GEOSGeomFromWKT("POINT (1 1)");
128
129 // clear all floating point exceptions
130 feclearexcept (FE_ALL_EXCEPT);
131
132 double d;
133 int status = GEOSDistance(g1, g2, &d);
134
135 ensure_equals(status, 1);
136 ensure_equals(d, sqrt(2));
137
138 // check for floating point overflow exceptions
139 int raised = fetestexcept(FE_OVERFLOW);
140 ensure_equals(raised & FE_OVERFLOW, 0);
141
142 GEOSGeom_destroy(g1);
143 GEOSGeom_destroy(g2);
144 }
145
146 // same distance between boundables should not raise floating point exception
147 template<>
148 template<>
149 void object::test<5>
150 ()
151 {
152 GEOSGeometry* g1 = GEOSGeomFromWKT("LINESTRING (0 0, 1 1)");
153 GEOSGeometry* g2 = GEOSGeomFromWKT("LINESTRING (2 1, 1 2)");
154
155 // clear all floating point exceptions
156 feclearexcept (FE_ALL_EXCEPT);
157
158 double d;
159 int status = GEOSDistance(g1, g2, &d);
160
161 ensure_equals(status, 1);
162 // ensure_equals(d, sqrt(2));
163
164 // check for floating point overflow exceptions
165 int raised = fetestexcept(FE_OVERFLOW);
166 ensure_equals(raised & FE_OVERFLOW, 0);
167
168 GEOSGeom_destroy(g1);
169 GEOSGeom_destroy(g2);
170 }
171
119172 } // namespace tut
120173
00 //
1 // Test Suite for C-API GEOSDistance
1 // Test Suite for C-API GEOSDistanceWithin
22
33 #include <tut/tut.hpp>
44 // geos
5 #include <geos/constants.h>
56 #include <geos_c.h>
6 #include <geos/constants.h>
77 // std
8 #include <limits>
89 #include <cstdarg>
910 #include <cstdio>
1011 #include <cstdlib>
12 #include <math.h>
1113 #include <memory>
12 #include <math.h>
1314
1415 #include "capi_test_utils.h"
1516
1819 // Test Group
1920 //
2021
21 // Common data used in test cases.
2222 struct test_capigeosdistancewithin_data : public capitest::utility {
23 test_capigeosdistancewithin_data() {
24 GEOSWKTWriter_setTrim(wktw_, 1);
25 }
23 void testGEOSDistanceWithin(const char* wkt1, const char* wkt2,
24 double distance, char expectedResult) {
25
26 GEOSGeometry *input1 = GEOSGeomFromWKT(wkt1);
27 ensure(input1 != nullptr);
28 GEOSGeometry *input2 = GEOSGeomFromWKT(wkt2);
29 ensure(input2 != nullptr);
30
31 char ret = GEOSDistanceWithin(input1, input2, distance);
32
33 GEOSGeom_destroy(input1);
34 GEOSGeom_destroy(input2);
35
36 ensure_equals("return code", (int)ret, (int)expectedResult);
37
38 };
2639 };
2740
2841 typedef test_group<test_capigeosdistancewithin_data> group;
3043
3144 group test_capigeosdistancewithin_group("capi::GEOSDistanceWithin");
3245
33 //
34 // Test Cases
35 //
36
37 template<>
38 template<>
39 void object::test<1>
40 ()
41 {
42 geom1_ = GEOSGeomFromWKT("POINT(10 10)");
43 geom2_ = GEOSGeomFromWKT("POINT(3 6)");
44
45 double dist = 8.1;
46 char ret = GEOSDistanceWithin(geom1_, geom2_, dist);
47 ensure_equals(ret, 1);
48
49 ret = GEOSDistanceWithin(geom1_, geom2_, dist-0.1);
50 ensure_equals(ret, 0);
51 }
46 // point within distance should return true
47 template <>
48 template <>
49 void object::test<1>() {
50 testGEOSDistanceWithin(
51 "POINT(0 0)",
52 "POINT(0 1)",
53 1.0,
54 1
55 );
56 }
57
58 // point not within distance should return false
59 template <>
60 template <>
61 void object::test<2>() {
62 testGEOSDistanceWithin(
63 "POINT(0 0)",
64 "POINT(0 1)",
65 0.999999,
66 0
67 );
68 }
69
70 // point at same location should return true even if distance is 0
71 template <>
72 template <>
73 void object::test<3>() {
74 testGEOSDistanceWithin(
75 "POINT(0 0)",
76 "POINT(0 0)",
77 0.0,
78 1
79 );
80 }
81
82 // line within distance of another line should return true
83 template <>
84 template <>
85 void object::test<4>() {
86 testGEOSDistanceWithin(
87 "LINESTRING(0 0, 1 1)",
88 "LINESTRING(0 1, 1 2)",
89 1.0,
90 1
91 );
92 }
93
94 // line not within distance of another line should return false
95 template <>
96 template <>
97 void object::test<5>() {
98 testGEOSDistanceWithin(
99 "LINESTRING(0 0, 1 0)",
100 "LINESTRING(0 1, 1 1)",
101 0.999999,
102 0
103 );
104 }
105
106 // line that equals another line should return true even if distance is 0
107 template <>
108 template <>
109 void object::test<6>() {
110 testGEOSDistanceWithin(
111 "LINESTRING(0 0, 1 1)",
112 "LINESTRING(0 0, 1 1)",
113 0.0,
114 1
115 );
116 }
117
118 // line that intersects another line should return true even if distance is 0
119 template <>
120 template <>
121 void object::test<7>() {
122 testGEOSDistanceWithin(
123 "LINESTRING(0 0, 1 1)",
124 "LINESTRING(1 1, 0 0)",
125 0.0,
126 1
127 );
128 }
129
130 // line that shares segment with other line should return true even if distance is 0
131 template <>
132 template <>
133 void object::test<8>() {
134 testGEOSDistanceWithin(
135 "LINESTRING(0 0, 2 2)",
136 "LINESTRING(0 0, 1 1)",
137 0.0,
138 1
139 );
140 }
141
142
143 // point within distance of line should return true
144 template <>
145 template <>
146 void object::test<9>() {
147 testGEOSDistanceWithin(
148 "LINESTRING(0 0, 1 1)",
149 "POINT( 0 1)",
150 1.0,
151 1
152 );
153 }
154
155 // point not within distance of line should return false
156 template <>
157 template <>
158 void object::test<10>() {
159 testGEOSDistanceWithin(
160 "LINESTRING(0 0, 1 0)",
161 "POINT(0 1)",
162 0.999999,
163 0
164 );
165 }
166
167 // line within distance of point should return true
168 template <>
169 template <>
170 void object::test<11>() {
171 testGEOSDistanceWithin(
172 "POINT( 0 1)",
173 "LINESTRING(0 0, 1 1)",
174 1.0,
175 1
176 );
177 }
178
179 // line not within distance of point should return false
180 template <>
181 template <>
182 void object::test<12>() {
183 testGEOSDistanceWithin(
184 "POINT(0 1)",
185 "LINESTRING(0 0, 1 0)",
186 0.999999,
187 0
188 );
189 }
190
191
192
193 // point that intersects line should return true even if distance is 0
194 template <>
195 template <>
196 void object::test<13>() {
197 testGEOSDistanceWithin(
198 "LINESTRING(0 0, 1 1)",
199 "POINT(0.5 0.5)",
200 0.0,
201 1
202 );
203 }
204
205 // polygon within distance of other polygon should return true
206 template <>
207 template <>
208 void object::test<14>() {
209 testGEOSDistanceWithin(
210 "POLYGON((0 0, 1 1, 2 0, 0 0))",
211 "POLYGON((0 3, 2 3, 1 2, 0 3))",
212 1.0,
213 1
214 );
215 }
216
217 // polygon not within distance of other polygon should return true
218 template <>
219 template <>
220 void object::test<15>() {
221 testGEOSDistanceWithin(
222 "POLYGON((0 0, 1 1, 2 0, 0 0))",
223 "POLYGON((0 3, 2 3, 1 2, 0 3))",
224 0.999999,
225 0
226 );
227 }
228
229 // polygon that intersects polygon should return true even if distance is 0
230 template <>
231 template <>
232 void object::test<16>() {
233 testGEOSDistanceWithin(
234 "POLYGON((0 0, 1 1, 2 0, 0 0))",
235 "POLYGON((0 3, 2 3, 1 0, 0 3))",
236 0.0,
237 1
238 );
239 }
240
241 // polygon that is equal to polygon should return true even if distance is 0
242 template <>
243 template <>
244 void object::test<17>() {
245 testGEOSDistanceWithin(
246 "POLYGON((0 0, 1 1, 2 0, 0 0))",
247 "POLYGON((1 1, 2 0, 0 0, 1 1))",
248 0.0,
249 1
250 );
251 }
252
253 // point within distance of polygon should return true
254 template <>
255 template <>
256 void object::test<18>() {
257 testGEOSDistanceWithin(
258 "POLYGON((0 0, 1 1, 2 0, 0 0))",
259 "POINT(1 2)",
260 1.0,
261 1
262 );
263 }
264
265 // point not within distance of polygon should return false
266 template <>
267 template <>
268 void object::test<19>() {
269 testGEOSDistanceWithin(
270 "POLYGON((0 0, 1 1, 2 0, 0 0))",
271 "POINT(1 2)",
272 0.999999,
273 0
274 );
275 }
276
277
278 // polygon within distance of point should return true
279 template <>
280 template <>
281 void object::test<20>() {
282 testGEOSDistanceWithin(
283 "POINT(1 2)",
284 "POLYGON((0 0, 1 1, 2 0, 0 0))",
285 1.0,
286 1
287 );
288 }
289
290 // point not within distance of polygon should return false
291 template <>
292 template <>
293 void object::test<21>() {
294 testGEOSDistanceWithin(
295 "POINT(1 2)",
296 "POLYGON((0 0, 1 1, 2 0, 0 0))",
297 0.999999,
298 0
299 );
300 }
301
302 // polygon that intersects point should return true even if distance is 0
303 template <>
304 template <>
305 void object::test<22>() {
306 testGEOSDistanceWithin(
307 "POLYGON((0 0, 1 1, 2 0, 0 0))",
308 "POINT(1 0)",
309 0.0,
310 1
311 );
312 }
313
314 // polygon within distance of line should return true
315 template <>
316 template <>
317 void object::test<23>() {
318 testGEOSDistanceWithin(
319 "POLYGON((0 0, 1 1, 2 0, 0 0))",
320 "LINESTRING(0 -1, 2 -1)",
321 1.0,
322 1
323 );
324 }
325
326 // polygon not within distance of line should return false
327 template <>
328 template <>
329 void object::test<24>() {
330 testGEOSDistanceWithin(
331 "POLYGON((0 0, 1 1, 2 0, 0 0))",
332 "LINESTRING(0 -1, 2 -1)",
333 0.999999,
334 0
335 );
336 }
337
338 // polygon that intersects line should return true even if distance is 0
339 template <>
340 template <>
341 void object::test<25>() {
342 testGEOSDistanceWithin(
343 "POLYGON((0 0, 1 1, 2 0, 0 0))",
344 "LINESTRING(0 -1, 0.5 0.5, 2 -1)",
345 0.0,
346 1
347 );
348 }
349
350 // polygon that shares edge with line should return true even if distance is 0
351 template <>
352 template <>
353 void object::test<26>() {
354 testGEOSDistanceWithin(
355 "POLYGON((0 0, 1 1, 2 0, 0 0))",
356 "LINESTRING(0 0, 1 1, 2 0)",
357 0.0,
358 1
359 );
360 }
361
362
363 // empty geometries should return false (distance 1)
364 template <>
365 template <>
366 void object::test<27>() {
367 testGEOSDistanceWithin(
368 "POINT EMPTY",
369 "LINESTRING EMPTY",
370 1.0,
371 0
372 );
373 }
374
375 // empty geometries should return false (distance 0)
376 template <>
377 template <>
378 void object::test<28>() {
379 testGEOSDistanceWithin(
380 "POINT EMPTY",
381 "LINESTRING EMPTY",
382 0.0,
383 0
384 );
385 }
386
387 // empty geometries should return false (distance Infinity)
388 template <>
389 template <>
390 void object::test<29>() {
391 testGEOSDistanceWithin(
392 "POINT EMPTY",
393 "LINESTRING EMPTY",
394 geos::DoubleInfinity,
395 0
396 );
397 }
398
399 // empty geometry is never within any distance
400 template <>
401 template <>
402 void object::test<30>() {
403 testGEOSDistanceWithin(
404 "POINT EMPTY",
405 "LINESTRING(0 0, 20 0)",
406 geos::DoubleInfinity,
407 0
408 );
409 }
410
411 // empty geometry is never within any distance
412 template <>
413 template <>
414 void object::test<31>() {
415 testGEOSDistanceWithin(
416 "LINESTRING(0 0, 20 0)",
417 "POINT EMPTY",
418 geos::DoubleInfinity,
419 0
420 );
421 }
422
423
424
52425
53426 } // namespace tut
54
22
33 #include <tut/tut.hpp>
44 // geos
5 #include <geos/constants.h>
56 #include <geos_c.h>
67 // std
78 #include <cstdarg>
9697 {
9798 GEOSCoordSequence* cs = GEOSCoordSeq_create(5, 2);
9899
99 constexpr double nan = std::numeric_limits<double>::quiet_NaN();
100100 GEOSCoordSeq_setX(cs, 0, 1);
101101 GEOSCoordSeq_setY(cs, 0, 1);
102102 for(unsigned int i = 1; i < 4; ++i) {
103 GEOSCoordSeq_setX(cs, i, nan);
104 GEOSCoordSeq_setY(cs, i, nan);
103 GEOSCoordSeq_setX(cs, i, geos::DoubleNotANumber);
104 GEOSCoordSeq_setY(cs, i, geos::DoubleNotANumber);
105105 }
106106 GEOSCoordSeq_setX(cs, 4, 1);
107107 GEOSCoordSeq_setY(cs, 4, 1);
33 #include <tut/tut.hpp>
44 // geos
55 #include <geos_c.h>
6 #include <geos/constants.h>
67 // std
78 #include <cstdarg>
89 #include <cstdio>
9697 {
9798 GEOSCoordSequence* cs = GEOSCoordSeq_create(5, 2);
9899
99 constexpr double nan = std::numeric_limits<double>::quiet_NaN();
100 constexpr double nan = geos::DoubleNotANumber;
100101 GEOSCoordSeq_setX(cs, 0, 1);
101102 GEOSCoordSeq_setY(cs, 0, 1);
102103 for(unsigned int i = 1; i < 4; ++i) {
22 #include <tut/tut.hpp>
33 // geos
44 #include <geos_c.h>
5 #include <geos/constants.h>
56 // std
67 #include <cstdarg>
78 #include <cstdio>
4243 int error = GEOSMinimumClearance(input, &d);
4344
4445 ensure(!error);
45 if(clearance == std::numeric_limits<double>::infinity()) {
46 if(clearance == geos::DoubleInfinity) {
4647 ensure(d == clearance);
4748 }
4849 else {
7576 {
7677 testClearance("MULTIPOINT ((100 100), (100 100))",
7778 "LINESTRING EMPTY",
78 std::numeric_limits<double>::infinity());
79 geos::DoubleInfinity);
7980 }
8081
8182 template<>
115116 {
116117 testClearance("POLYGON EMPTY",
117118 "LINESTRING EMPTY",
118 std::numeric_limits<double>::infinity());
119 geos::DoubleInfinity);
119120 }
120121
121122 } // namespace tut
33 #include <tut/tut.hpp>
44 // geos
55 #include <geos_c.h>
6 #include <geos/constants.h>
67 // std
78 #include <cstdarg>
89 #include <cstdio>
6667 checkDistance(
6768 "POLYGON EMPTY",
6869 "POLYGON EMPTY",
69 std::numeric_limits<double>::infinity()
70 geos::DoubleInfinity
7071 );
7172 }
7273
139140 checkDistance(
140141 "LINESTRING EMPTY",
141142 "POINT EMPTY",
142 std::numeric_limits<double>::infinity()
143 geos::DoubleInfinity
143144 );
144145 }
145146
151152 checkDistance(
152153 "POINT EMPTY",
153154 "LINESTRING EMPTY",
154 std::numeric_limits<double>::infinity()
155 geos::DoubleInfinity
155156 );
156157 }
157158
33 #include <tut/tut.hpp>
44 // geos
55 #include <geos_c.h>
6 #include <geos/constants.h>
67 // std
78 #include <cstdarg>
89 #include <cstdio>
6465 checkDistanceWithin(
6566 "POLYGON EMPTY",
6667 "POLYGON EMPTY",
67 std::numeric_limits<double>::infinity(),
68 1
68 geos::DoubleInfinity,
69 0
6970 );
7071 }
7172
143144 checkDistanceWithin(
144145 "LINESTRING EMPTY",
145146 "POINT EMPTY",
146 std::numeric_limits<double>::infinity(),
147 1
147 geos::DoubleInfinity,
148 0
148149 );
149150 }
150151
156157 checkDistanceWithin(
157158 "POINT EMPTY",
158159 "LINESTRING EMPTY",
159 std::numeric_limits<double>::infinity(),
160 1
160 geos::DoubleInfinity,
161 0
162 );
163 }
164
165 template<>
166 template<>
167 void object::test<9>
168 ()
169 {
170 checkDistanceWithin(
171 "POINT EMPTY",
172 "POINT(0 0)",
173 geos::DoubleInfinity,
174 0
175 );
176 }
177
178 template<>
179 template<>
180 void object::test<10>
181 ()
182 {
183 checkDistanceWithin(
184 "LINESTRING(0 0, 10 0)",
185 "POLYGON EMPTY",
186 geos::DoubleInfinity,
187 0
161188 );
162189 }
163190
33 #include <tut/tut.hpp>
44 // geos
55 #include <geos_c.h>
6 #include <geos/constants.h>
67 // std
78 #include <cstdarg>
89 #include <cstdio>
114115 for(std::size_t i = 0; i < ngeoms; i++) {
115116 const GEOSGeometry* nearest = GEOSSTRtree_nearest(tree, queryPoints[i]);
116117 const GEOSGeometry* nearestBruteForce = nullptr;
117 double nearestBruteForceDistance = std::numeric_limits<double>::max();
118 double nearestBruteForceDistance = geos::DoubleInfinity;
118119 for(std::size_t j = 0; j < ngeoms; j++) {
119120 double distance;
120121 GEOSDistance(queryPoints[i], geoms[j], &distance);
88 // Test Group
99 //
1010
11 struct test_geosisvalid_data : public capitest::utility {};
11 struct test_geosisvalidreason_data : public capitest::utility {};
1212
13 typedef test_group<test_geosisvalid_data> group;
13 typedef test_group<test_geosisvalidreason_data> group;
1414 typedef group::object object;
1515
16 group test_geosisvalid("capi::GEOSisValid");
16 group test_geosisvalidreason("capi::GEOSisValidReason");
1717
1818 template<>
1919 template<>
2121 {
2222 GEOSGeometry* input = GEOSGeomFromWKT("LINESTRING (1 2, 4 5, 9 -2)");
2323
24 ensure_equals(1, GEOSisValid(input));
24 char* reason = GEOSisValidReason(input);
25
26 ensure_equals(std::string(reason), "Valid Geometry");
2527
2628 GEOSGeom_destroy(input);
29 GEOSFree(reason);
2730 }
2831
2932 template<>
3235 {
3336 GEOSGeometry* input = GEOSGeomFromWKT("POLYGON ((0 0, 1 0, 0 1, 1 1, 0 0))");
3437
35 ensure_equals(0, GEOSisValid(input));
38 char* reason = GEOSisValidReason(input);
39
40 ensure_equals(std::string(reason), "Self-intersection[0.5 0.5]");
3641
3742 GEOSGeom_destroy(input);
43 GEOSFree(reason);
3844 }
3945
4046
88 // Test Group
99 //
1010
11 struct test_geosisvalidreason_data : public capitest::utility {};
11 struct test_geosisvalid_data : public capitest::utility {};
1212
13 typedef test_group<test_geosisvalidreason_data> group;
13 typedef test_group<test_geosisvalid_data> group;
1414 typedef group::object object;
1515
16 group test_geosisvalidreason("capi::GEOSisValidReason");
16 group test_geosisvalid("capi::GEOSisValid");
1717
1818 template<>
1919 template<>
2121 {
2222 GEOSGeometry* input = GEOSGeomFromWKT("LINESTRING (1 2, 4 5, 9 -2)");
2323
24 char* reason = GEOSisValidReason(input);
25
26 ensure_equals(std::string(reason), "Valid Geometry");
24 ensure_equals(1, GEOSisValid(input));
2725
2826 GEOSGeom_destroy(input);
29 GEOSFree(reason);
3027 }
3128
3229 template<>
3532 {
3633 GEOSGeometry* input = GEOSGeomFromWKT("POLYGON ((0 0, 1 0, 0 1, 1 1, 0 0))");
3734
38 char* reason = GEOSisValidReason(input);
39
40 ensure_equals(std::string(reason), "Self-intersection[0.5 0.5]");
35 ensure_equals(0, GEOSisValid(input));
4136
4237 GEOSGeom_destroy(input);
43 GEOSFree(reason);
4438 }
4539
4640
41 // Unclosed polygon
42 template<>
43 template<>
44 void object::test<3>()
45 {
46 GEOSCoordSequence* shell_seq = GEOSCoordSeq_create(4, 2);
47 double shell_coords[] = {0,0, 0,10, 10,10, 10,0};
48 for (unsigned int i = 0; i < 4; i++) {
49 GEOSCoordSeq_setXY(shell_seq, i, shell_coords[2*i], shell_coords[2*i+1]);
50 }
51
52 // Unclosed ring fails in construction
53 // Linear ring takes ownership of coordinate sequence and
54 // frees it when construction fails
55 GEOSGeometry* shell = GEOSGeom_createLinearRing(shell_seq);
56 ensure(shell == nullptr);
57 // So we end up handing nullptr into create polygon
58 GEOSGeometry* polygon = GEOSGeom_createPolygon(shell, nullptr, 0);
59 ensure(polygon == nullptr);
60 // Which also returns nullptr and that goes into isvalid
61 char isvalid = GEOSisValid(polygon);
62 // Which causes an exception that we catch
63 ensure_equals(2, isvalid);
64 }
65
4766 } // namespace tut
48
99 #include <geos/geom/Geometry.h>
1010 #include <geos/geom/GeometryFactory.h>
1111 #include <geos/geom/Point.h>
12 #include <geos/constants.h>
1213
1314 #include <utility.h>
1415
153154 template<>
154155 void object::test<4>()
155156 {
156 std::unique_ptr<Point> pt = createPoint(0, std::numeric_limits<double>::infinity());
157 std::unique_ptr<Point> pt = createPoint(0, geos::DoubleInfinity);
157158 checkFix(pt.get() , "POINT EMPTY");
158159 }
159160
162163 template<>
163164 void object::test<5>()
164165 {
165 std::unique_ptr<Point> pt = createPoint(0, std::numeric_limits<double>::infinity());
166 std::unique_ptr<Point> pt = createPoint(0, geos::DoubleInfinity);
166167 checkFix(pt.get() , "POINT EMPTY");
167168 }
168169