1 //
2 // Ported from JTS junit/algorithm/RobustLineIntersectorTest.java rev. 1.1
3 
4 #include <tut/tut.hpp>
5 // geos
6 #include <geos/io/WKBReader.h>
7 #include <geos/io/WKTReader.h>
8 #include <geos/algorithm/LineIntersector.h>
9 #include <geos/algorithm/PointLocation.h>
10 #include <geos/algorithm/Orientation.h>
11 #include <geos/geom/PrecisionModel.h>
12 #include <geos/geom/GeometryFactory.h>
13 #include <geos/geom/Geometry.h> // required for use in unique_ptr
14 #include <geos/geom/LineString.h>
15 #include <geos/geom/Coordinate.h>
16 #include <geos/geom/Point.h>
17 #include <geos/geom/CoordinateSequence.h>
18 #include <geos/geom/CoordinateArraySequence.h>
19 // std
20 #include <sstream>
21 #include <string>
22 #include <memory>
23 
24 
25 using namespace geos::geom; //
26 using geos::algorithm::LineIntersector;
27 using geos::algorithm::PointLocation;
28 using geos::algorithm::Orientation;
29 
30 
31 namespace tut {
32 //
33 // Test Group
34 //
35 
36 struct test_robustlineintersector_data {
37 
38     typedef std::unique_ptr<Geometry> GeomPtr;
39 
40     LineIntersector i;
41 
42 };
43 
44 typedef test_group<test_robustlineintersector_data> group;
45 typedef group::object object;
46 
47 group test_robustlineintersector_group(
48     "geos::algorithm::RobustLineIntersector");
49 
50 
51 
52 
53 //
54 // Test Cases
55 //
56 
57 // 1 - test2Lines
58 template<>
59 template<>
test()60 void object::test<1>
61 ()
62 {
63     Coordinate p1(10, 10);
64     Coordinate p2(20, 20);
65     Coordinate q1(20, 10);
66     Coordinate q2(10, 20);
67     Coordinate x(15, 15);
68     i.computeIntersection(p1, p2, q1, q2);
69 
70     ensure_equals(i.getIntersectionNum(), (unsigned int)LineIntersector::POINT_INTERSECTION);
71     ensure_equals(i.getIntersectionNum(), 1UL);
72     ensure_equals(i.getIntersection(0), x);
73     ensure("isProper", i.isProper());
74     ensure("hasIntersection", i.hasIntersection());
75 }
76 
77 // 2 - testCollinear1
78 template<>
79 template<>
test()80 void object::test<2>
81 ()
82 {
83     Coordinate p1(10, 10);
84     Coordinate p2(20, 10);
85     Coordinate q1(22, 10);
86     Coordinate q2(30, 10);
87     i.computeIntersection(p1, p2, q1, q2);
88 
89     ensure_equals(i.getIntersectionNum(), LineIntersector::NO_INTERSECTION);
90     ensure_equals(i.getIntersectionNum(), 0UL);
91     ensure("!isProper", !i.isProper());
92     ensure("!hasIntersection", !i.hasIntersection());
93 }
94 
95 // 3 - testCollinear2
96 template<>
97 template<>
test()98 void object::test<3>
99 ()
100 {
101     Coordinate p1(10, 10);
102     Coordinate p2(20, 10);
103     Coordinate q1(20, 10);
104     Coordinate q2(30, 10);
105     i.computeIntersection(p1, p2, q1, q2);
106 
107     ensure_equals(i.getIntersectionNum(), LineIntersector::POINT_INTERSECTION);
108     ensure_equals(i.getIntersectionNum(), 1UL);
109     ensure("!isProper", !i.isProper());
110     ensure("hasIntersection", i.hasIntersection());
111 }
112 
113 // 4 - testCollinear3
114 template<>
115 template<>
test()116 void object::test<4>
117 ()
118 {
119     Coordinate p1(10, 10);
120     Coordinate p2(20, 10);
121     Coordinate q1(15, 10);
122     Coordinate q2(30, 10);
123     i.computeIntersection(p1, p2, q1, q2);
124 
125     ensure_equals(i.getIntersectionNum(), LineIntersector::COLLINEAR_INTERSECTION);
126     ensure_equals(i.getIntersectionNum(), 2UL);
127     ensure("!isProper", !i.isProper());
128     ensure("hasIntersection", i.hasIntersection());
129 }
130 
131 // 5 - testCollinear4
132 template<>
133 template<>
test()134 void object::test<5>
135 ()
136 {
137     Coordinate p1(10, 10);
138     Coordinate p2(20, 10);
139     Coordinate q1(10, 10);
140     Coordinate q2(30, 10);
141     i.computeIntersection(p1, p2, q1, q2);
142 
143     ensure_equals(i.getIntersectionNum(), LineIntersector::COLLINEAR_INTERSECTION);
144     ensure_equals(i.getIntersectionNum(), 2UL);
145     ensure("!isProper", !i.isProper());
146     ensure("hasIntersection", i.hasIntersection());
147 }
148 
149 // 6 - testEndpointIntersection
150 template<>
151 template<>
test()152 void object::test<6>
153 ()
154 {
155     i.computeIntersection(Coordinate(100, 100), Coordinate(10, 100),
156                           Coordinate(100, 10), Coordinate(100, 100));
157     ensure("hasIntersection", i.hasIntersection());
158     ensure_equals(i.getIntersectionNum(), 1UL);
159 }
160 
161 // 7 - testEndpointIntersection2
162 template<>
163 template<>
test()164 void object::test<7>
165 ()
166 {
167     i.computeIntersection(Coordinate(190, 50), Coordinate(120, 100),
168                           Coordinate(120, 100), Coordinate(50, 150));
169     ensure("hasIntersection", i.hasIntersection());
170     ensure_equals(i.getIntersectionNum(), 1UL);
171     ensure_equals(i.getIntersection(1), Coordinate(120, 100));
172 }
173 
174 // 8 - testOverlap
175 template<>
176 template<>
test()177 void object::test<8>
178 ()
179 {
180     i.computeIntersection(Coordinate(180, 200), Coordinate(160, 180),
181                           Coordinate(220, 240), Coordinate(140, 160));
182     ensure("hasIntersection", i.hasIntersection());
183     ensure_equals(i.getIntersectionNum(), 2UL);
184 }
185 
186 // 9 - testIsProper1
187 template<>
188 template<>
test()189 void object::test<9>
190 ()
191 {
192     i.computeIntersection(Coordinate(30, 10), Coordinate(30, 30),
193                           Coordinate(10, 10), Coordinate(90, 11));
194     ensure("hasIntersection", i.hasIntersection());
195     ensure_equals(i.getIntersectionNum(), 1UL);
196     ensure("isProper", i.isProper());
197 }
198 
199 // 10 - testIsProper2
200 template<>
201 template<>
test()202 void object::test<10>
203 ()
204 {
205     i.computeIntersection(Coordinate(10, 30), Coordinate(10, 0),
206                           Coordinate(11, 90), Coordinate(10, 10));
207     ensure("hasIntersection", i.hasIntersection());
208     ensure_equals(i.getIntersectionNum(), 1UL);
209     ensure("!isProper", !i.isProper());
210 }
211 
212 // 11 - testIsCCW
213 template<>
214 template<>
test()215 void object::test<11>
216 ()
217 {
218     ensure_equals(Orientation::index(
219                       Coordinate(-123456789, -40),
220                       Coordinate(0, 0),
221                       Coordinate(381039468754763.0, 123456789)), 1);
222 }
223 
224 // 12 - testIsCCW2
225 template<>
226 template<>
test()227 void object::test<12>
228 ()
229 {
230     ensure_equals(Orientation::index(
231                       Coordinate(10, 10),
232                       Coordinate(20, 20),
233                       Coordinate(0, 0)), 0);
234 }
235 
236 // 13 - testA
237 template<>
238 template<>
test()239 void object::test<13>
240 ()
241 {
242     Coordinate p1(-123456789, -40);
243     Coordinate p2(381039468754763.0, 123456789);
244     Coordinate q(0, 0);
245 
246     using geos::geom::CoordinateSequence;
247     using geos::geom::GeometryFactory;
248     using geos::geom::LineString;
249 
250     GeometryFactory::Ptr factory = GeometryFactory::create();
251     CoordinateArraySequence* cs = new CoordinateArraySequence();
252     cs->add(p1);
253     cs->add(p2);
254 
255     GeomPtr l(factory->createLineString(cs));
256     GeomPtr p(factory->createPoint(q));
257     ensure(!l->intersects(p.get()));
258 
259     ensure(!PointLocation::isOnLine(q, cs));
260     ensure_equals(Orientation::index(p1, p2, q), -1);
261 
262 }
263 
264 // Test intersects: point on segment with FLOAT PM
265 // X coordinate of 3rd and 4th vertises of the line are not
266 // float-point exact with X coordinate of the point.
267 // The X values differ after 14th decimal place:
268 // POINT (-23.1094689600055080 50.5195368635957180)
269 // --------------------^^^^^^^------------^^^^^^^^
270 // LINESTRING 3rd and 4th points
271 //        -23.1094689600055150 50.5223376452201340,
272 //        -23.1094689600055010 50.5169177629559480,
273 // --------------------^^^^^^^------------^^^^^^^^
274 // So, in float-point precision model, the point does DOES NOT intersect the segment.
275 template<>
276 template<>
test()277 void object::test<14>
278 ()
279 {
280     geos::io::WKBReader reader;
281 
282     // POINT located between 3rd and 4th vertex of LINESTRING
283     // POINT(-23.1094689600055080 50.5195368635957180)
284     std::string point("01010000009a266328061c37c0e21a172f80424940");
285     // LINESTRING(-23.122057005539 50.5201976774794,-23.1153476966995 50.5133404815199,-23.1094689600055150 50.5223376452201340,-23.1094689600055010 50.5169177629559480,-23.0961967920942 50.5330464848094,-23.0887991006034 50.5258515213185,-23.0852302622362 50.5264582238409)
286     std::string
287     line("0102000000070000009909bf203f1f37c05c1d66d6954249404afe386d871d37c0a7eb1124b54149409c266328061c37c056d8bff5db42494098266328061c37c0034f7b5c2a42494060065c5aa01837c08ac001de3a4449408401b189bb1637c0b04e471a4f43494014ef84a6d11537c0b20dabfb62434940");
288     std::stringstream sPoint(point);
289     GeomPtr gPoint(reader.readHEX(sPoint));
290     std::stringstream sLine(line);
291     GeomPtr gLine(reader.readHEX(sLine));
292     int ret = gLine->intersects(gPoint.get());
293     ensure_equals(ret, 0);
294 }
295 
296 // Test intersects: point on segment with FIXED PM
297 // X coordinate of 3rd and 4th vertises of the line are not
298 // float-point exact with X coordinate of the point.
299 // The X values differ after 14th decimal place:
300 // POINT (-23.1094689600055080 50.5195368635957180)
301 // --------------------^^^^^^^------------^^^^^^^^
302 // LINESTRING 3rd and 4th points
303 //        -23.1094689600055150 50.5223376452201340,
304 //        -23.1094689600055010 50.5169177629559480,
305 // --------------------^^^^^^^------------^^^^^^^^
306 // So, if float-point values are trimmed up to 14 decimal digits, the point DOES intersect the segment.
307 
308 template<>
309 template<>
test()310 void object::test<15>
311 ()
312 {
313     using geos::geom::GeometryFactory;
314     geos::geom::PrecisionModel pm(1e+13);
315     GeometryFactory::Ptr factory = GeometryFactory::create(&pm);
316     geos::io::WKBReader reader(*factory);
317 
318     // POINT located between 3rd and 4th vertex of LINESTRING
319     // POINT(-23.1094689600055080 50.5195368635957180)
320     std::string point("01010000009a266328061c37c0e21a172f80424940");
321     // LINESTRING(-23.122057005539 50.5201976774794,-23.1153476966995 50.5133404815199,-23.1094689600055150 50.5223376452201340,-23.1094689600055010 50.5169177629559480,-23.0961967920942 50.5330464848094,-23.0887991006034 50.5258515213185,-23.0852302622362 50.5264582238409)
322     std::string
323     line("0102000000070000009909bf203f1f37c05c1d66d6954249404afe386d871d37c0a7eb1124b54149409c266328061c37c056d8bff5db42494098266328061c37c0034f7b5c2a42494060065c5aa01837c08ac001de3a4449408401b189bb1637c0b04e471a4f43494014ef84a6d11537c0b20dabfb62434940");
324     std::stringstream sPoint(point);
325     GeomPtr gPoint(reader.readHEX(sPoint));
326     std::stringstream sLine(line);
327     GeomPtr gLine(reader.readHEX(sLine));
328     int ret = gLine->intersects(gPoint.get());
329     ensure_equals(ret, 1);
330 }
331 
332 } // namespace tut
333 
334