1 //
2 // Test Suite for C-API GEOSNode
3
4 #include <tut/tut.hpp>
5 // geos
6 #include <geos_c.h>
7 // std
8 #include <cstdarg>
9 #include <cstdio>
10 #include <cstdlib>
11 #include <memory>
12
13 namespace tut {
14 //
15 // Test Group
16 //
17
18 // Common data used in test cases.
19 struct test_capigeosnode_data {
20 GEOSGeometry* geom1_;
21 GEOSGeometry* geom2_;
22 GEOSWKTWriter* w_;
23
24 static void
noticetut::test_capigeosnode_data25 notice(const char* fmt, ...)
26 {
27 std::fprintf(stdout, "NOTICE: ");
28
29 va_list ap;
30 va_start(ap, fmt);
31 std::vfprintf(stdout, fmt, ap);
32 va_end(ap);
33
34 std::fprintf(stdout, "\n");
35 }
36
test_capigeosnode_datatut::test_capigeosnode_data37 test_capigeosnode_data()
38 : geom1_(nullptr), geom2_(nullptr), w_(nullptr)
39 {
40 initGEOS(notice, notice);
41 w_ = GEOSWKTWriter_create();
42 GEOSWKTWriter_setTrim(w_, 1);
43 }
44
~test_capigeosnode_datatut::test_capigeosnode_data45 ~test_capigeosnode_data()
46 {
47 GEOSGeom_destroy(geom1_);
48 GEOSGeom_destroy(geom2_);
49 GEOSWKTWriter_destroy(w_);
50 geom1_ = nullptr;
51 geom2_ = nullptr;
52 finishGEOS();
53 }
54
55 };
56
57 typedef test_group<test_capigeosnode_data> group;
58 typedef group::object object;
59
60 group test_capigeosnode_group("capi::GEOSNode");
61
62 //
63 // Test Cases
64 //
65
66 /// Self-intersecting line
67 template<>
68 template<>
test()69 void object::test<1>
70 ()
71 {
72 geom1_ = GEOSGeomFromWKT("LINESTRING(0 0, 10 10, 10 0, 0 10)");
73 geom2_ = GEOSNode(geom1_);
74 ensure(nullptr != geom2_);
75
76 GEOSNormalize(geom2_);
77 char* wkt_c = GEOSWKTWriter_write(w_, geom2_);
78 std::string out(wkt_c);
79 free(wkt_c);
80
81 ensure_equals(out,
82 "MULTILINESTRING ((5 5, 10 10, 10 0, 5 5), (0 10, 5 5), (0 0, 5 5))"
83 );
84 }
85
86 /// Overlapping lines
87 template<>
88 template<>
test()89 void object::test<2>
90 ()
91 {
92 geom1_ = GEOSGeomFromWKT("MULTILINESTRING((0 0, 2 0, 4 0),(5 0, 3 0, 1 0))");
93 geom2_ = GEOSNode(geom1_);
94 ensure(nullptr != geom2_);
95
96 GEOSNormalize(geom2_);
97 char* wkt_c = GEOSWKTWriter_write(w_, geom2_);
98 std::string out(wkt_c);
99 free(wkt_c);
100
101 ensure_equals(out,
102 "MULTILINESTRING ((4 0, 5 0), (3 0, 4 0), (2 0, 3 0), (1 0, 2 0), (0 0, 1 0))"
103 );
104 }
105
106 /// Equal lines
107 template<>
108 template<>
test()109 void object::test<3>
110 ()
111 {
112 geom1_ = GEOSGeomFromWKT("MULTILINESTRING((0 0, 2 0, 4 0),(0 0, 2 0, 4 0))");
113 geom2_ = GEOSNode(geom1_);
114 ensure(nullptr != geom2_);
115
116 GEOSNormalize(geom2_);
117 char* wkt_c = GEOSWKTWriter_write(w_, geom2_);
118 std::string out(wkt_c);
119 free(wkt_c);
120
121 ensure_equals(out,
122 "MULTILINESTRING ((2 0, 4 0), (0 0, 2 0))"
123 );
124 }
125
126 // https://gis.stackexchange.com/questions/345341/get-location-of-postgis-geos-topology-exception/345482#345482
127 template<>
128 template<>
test()129 void object::test<4>
130 ()
131 {
132 std::string wkb = "010500000002000000010200000003000000dc874d65fcc25ec176032c6b350c5341b336429ffec25ec1f962bbd"
133 "9480c5341fc849518ffc25ec15be20f5f500c5341010200000006000000fa9bbfd3fcc25ec1b978232f390c5341"
134 "b336429ffec25ec1f962bbd9480c5341a77e6be5fec25ec1357c21334d0c5341c3eba27bfec25ec11be5a4c34a0"
135 "c5341b61d8cacfcc25ec1bcf273143c0c5341fa9bbfd3fcc25ec1b978232f390c5341";
136
137 geom1_ = GEOSGeomFromHEX_buf((const unsigned char*) wkb.c_str(), wkb.size());
138 geom2_ = GEOSNode(geom1_);
139
140 // Noding currently fails for this case.
141 // ensure(geom2_);
142 }
143
144
145 } // namespace tut
146
147