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