Branch data Line data Source code
1 : : #undef G_DISABLE_ASSERT
2 : :
3 : : #include <shumate/shumate.h>
4 : : #include "shumate/vector/vector_tile.pb-c.h"
5 : :
6 : : #define MOVE_TO 1
7 : : #define LINE_TO 2
8 : : #define CLOSE_PATH 7
9 : : #define CMD(op, rep) ((op & 7) | ((rep) << 3))
10 : : #define POINT(x, y) unzigzag (x), unzigzag (y)
11 : :
12 : : static uint32_t
13 : : unzigzag (int value)
14 : : {
15 : : return (value << 1) ^ (value >> 31);
16 : : }
17 : :
18 : : static VectorTile__Tile__Value *
19 : 9 : new_string_value (const char *value)
20 : : {
21 : 9 : VectorTile__Tile__Value *v = g_new0 (VectorTile__Tile__Value, 1);
22 : 9 : vector_tile__tile__value__init (v);
23 [ + - ]: 9 : v->string_value = g_strdup (value);
24 : 9 : return v;
25 : : }
26 : :
27 : : static void
28 : 54 : set_feature_geometry (VectorTile__Tile__Feature *feature, VectorTile__Tile__GeomType geom_type, const uint32_t *geometry)
29 : : {
30 : 54 : feature->type = geom_type;
31 : 54 : feature->has_type = TRUE;
32 [ + + ]: 837 : for (int i = 0; geometry[i] != G_MAXUINT32; i++)
33 : 783 : feature->n_geometry++;
34 [ - + - - ]: 54 : feature->geometry = g_new0 (uint32_t, feature->n_geometry);
35 [ + + ]: 837 : for (int i = 0; i < feature->n_geometry; i++)
36 : 783 : feature->geometry[i] = geometry[i];
37 : 54 : }
38 : :
39 : : static VectorTile__Tile__Feature *
40 : 54 : add_feature (VectorTile__Tile__Layer *layer, uint32_t id, uint32_t *tags, uint32_t n_tags)
41 : : {
42 : 54 : VectorTile__Tile__Feature *feature = g_new0 (VectorTile__Tile__Feature, 1);
43 : 54 : vector_tile__tile__feature__init (feature);
44 : 54 : feature->id = id;
45 : 54 : feature->has_id = TRUE;
46 : 54 : feature->n_tags = n_tags;
47 [ - + ]: 54 : feature->tags = g_new0 (uint32_t, n_tags);
48 [ + + ]: 72 : for (int i = 0; i < n_tags; i++)
49 : 18 : feature->tags[i] = tags[i];
50 : 54 : layer->n_features++;
51 [ - + - - ]: 54 : layer->features = g_renew (VectorTile__Tile__Feature *, layer->features, layer->n_features);
52 : 54 : layer->features[layer->n_features - 1] = feature;
53 : 54 : return feature;
54 : : }
55 : :
56 : : static VectorTile__Tile__Layer *
57 : 18 : add_layer (VectorTile__Tile *tile, char *name, int extent, char **keys, VectorTile__Tile__Value **values)
58 : : {
59 : 18 : VectorTile__Tile__Layer *layer = g_new0 (VectorTile__Tile__Layer, 1);
60 : 18 : vector_tile__tile__layer__init (layer);
61 [ + - ]: 18 : layer->name = g_strdup (name);
62 : 18 : layer->extent = extent;
63 : 18 : layer->has_extent = TRUE;
64 : 18 : layer->version = 2;
65 : 18 : layer->n_keys = g_strv_length (keys);
66 [ - + ]: 18 : layer->keys = g_new0 (char *, layer->n_keys);
67 [ + + ]: 27 : for (int i = 0; i < layer->n_keys; i++)
68 [ - + ]: 18 : layer->keys[i] = g_strdup (keys[i]);
69 : 18 : layer->n_values = g_strv_length ((char **)values);
70 [ - + ]: 18 : layer->values = g_new0 (VectorTile__Tile__Value *, layer->n_values);
71 [ + + ]: 27 : for (int i = 0; i < layer->n_values; i++)
72 : 9 : layer->values[i] = values[i];
73 : 18 : tile->n_layers++;
74 [ - + - - ]: 18 : tile->layers = g_renew (VectorTile__Tile__Layer *, tile->layers, tile->n_layers);
75 : 18 : tile->layers[tile->n_layers - 1] = layer;
76 : 18 : return layer;
77 : : }
78 : :
79 : : static GBytes *
80 : 9 : create_test_tile (void)
81 : : {
82 : 9 : VectorTile__Tile *tile;
83 : 9 : VectorTile__Tile__Layer *layer;
84 : 9 : VectorTile__Tile__Feature *feature;
85 : 9 : uint8_t *out;
86 : 9 : size_t out_len;
87 : :
88 : 9 : tile = g_new0 (VectorTile__Tile, 1);
89 : 9 : vector_tile__tile__init (tile);
90 : :
91 : 27 : layer = add_layer (tile, "helloworld", 4096,
92 : 9 : (char*[]){"hello", NULL},
93 : 9 : (VectorTile__Tile__Value*[]){new_string_value ("world"), NULL}
94 : : );
95 : :
96 : : /* Point feature*/
97 : 9 : feature = add_feature (layer, 1, (uint32_t[]){0, 0}, 2);
98 : 9 : set_feature_geometry (feature, VECTOR_TILE__TILE__GEOM_TYPE__POINT, (uint32_t[]){CMD (MOVE_TO, 1), POINT (1, 2), G_MAXUINT32});
99 : :
100 : : /* MultiPoint feature */
101 : 9 : feature = add_feature (layer, 2, (uint32_t[]){}, 0);
102 : 9 : set_feature_geometry (feature, VECTOR_TILE__TILE__GEOM_TYPE__POINT, (uint32_t[]){
103 : : CMD (MOVE_TO, 2),
104 : 9 : POINT (100, 200),
105 : 9 : POINT (300, 400),
106 : : G_MAXUINT32,
107 : : });
108 : :
109 : : /* LineString feature */
110 : 9 : feature = add_feature (layer, 3, (uint32_t[]){}, 0);
111 : 9 : set_feature_geometry (feature, VECTOR_TILE__TILE__GEOM_TYPE__LINESTRING, (uint32_t[]){
112 : : CMD (MOVE_TO, 1),
113 : 9 : POINT (100, 200),
114 : : CMD (LINE_TO, 2),
115 : 9 : POINT (300, 400),
116 : 9 : POINT (500, 600),
117 : : G_MAXUINT32,
118 : : });
119 : :
120 : : /* MultiLineString feature */
121 : 9 : feature = add_feature (layer, 4, (uint32_t[]){}, 0);
122 : 9 : set_feature_geometry (feature, VECTOR_TILE__TILE__GEOM_TYPE__LINESTRING, (uint32_t[]){
123 : : CMD (MOVE_TO, 1),
124 : 9 : POINT (100, 200),
125 : : CMD (LINE_TO, 2),
126 : 9 : POINT (300, 400),
127 : 9 : POINT (500, 600),
128 : : CMD (MOVE_TO, 1),
129 : 9 : POINT (100, 200),
130 : : CMD (LINE_TO, 2),
131 : 9 : POINT (300, 400),
132 : 9 : POINT (500, 600),
133 : : G_MAXUINT32,
134 : : });
135 : :
136 : : /* Polygon feature */
137 : 9 : feature = add_feature (layer, 5, (uint32_t[]){}, 0);
138 : 9 : set_feature_geometry (feature, VECTOR_TILE__TILE__GEOM_TYPE__POLYGON, (uint32_t[]){
139 : : /* Exterior ring */
140 : : CMD (MOVE_TO, 1),
141 : 9 : POINT (100, 200),
142 : : CMD (LINE_TO, 3),
143 : 9 : POINT (200, 0),
144 : 9 : POINT (0, 200),
145 : 9 : POINT (-200, 0),
146 : : CMD (CLOSE_PATH, 1),
147 : : /* Interior ring */
148 : : CMD (MOVE_TO, 1),
149 : 9 : POINT (50, -50),
150 : : CMD (LINE_TO, 3),
151 : 9 : POINT (100, 0),
152 : 9 : POINT (0, -100),
153 : 9 : POINT (-100, 0),
154 : : CMD (CLOSE_PATH, 1),
155 : : G_MAXUINT32,
156 : : });
157 : :
158 : : /* MultiPolygon feature */
159 : 9 : feature = add_feature (layer, 6, (uint32_t[]){}, 0);
160 : 9 : set_feature_geometry (feature, VECTOR_TILE__TILE__GEOM_TYPE__POLYGON, (uint32_t[]){
161 : : /* Exterior ring 1 (a square) */
162 : : CMD (MOVE_TO, 1),
163 : 9 : POINT (100, 200),
164 : : CMD (LINE_TO, 3),
165 : 9 : POINT (200, 0),
166 : 9 : POINT (0, 200),
167 : 9 : POINT (-200, 0),
168 : : CMD (CLOSE_PATH, 1),
169 : : /* Interior ring (another square)*/
170 : : CMD (MOVE_TO, 1),
171 : 9 : POINT (50, -50),
172 : : CMD (LINE_TO, 3),
173 : 9 : POINT (100, 0),
174 : 9 : POINT (0, -100),
175 : 9 : POINT (-100, 0),
176 : : CMD (CLOSE_PATH, 1),
177 : : /* Exterior ring 2 (square rotated 45 degrees, overlapping ring 1) */
178 : : CMD (MOVE_TO, 1),
179 : 9 : POINT (51, 51),
180 : : CMD (LINE_TO, 3),
181 : 9 : POINT (49, -51),
182 : 9 : POINT (100, 50),
183 : 9 : POINT (-100, 50),
184 : : CMD (CLOSE_PATH, 1),
185 : : G_MAXUINT32,
186 : : });
187 : :
188 : :
189 : 18 : layer = add_layer (tile, "helloworld2", 100,
190 : 9 : (char*[]){NULL},
191 : 9 : (VectorTile__Tile__Value*[]){NULL}
192 : : );
193 : :
194 : 9 : out_len = vector_tile__tile__get_packed_size (tile);
195 : 9 : out = g_new0 (uint8_t, out_len);
196 : 9 : vector_tile__tile__pack (tile, out);
197 : :
198 : 9 : vector_tile__tile__free_unpacked (tile, NULL);
199 : :
200 : 9 : return g_bytes_new_take (out, out_len);
201 : : }
202 : :
203 : : static void
204 : 3 : test_vector_reader_layers (void)
205 : : {
206 : 6 : g_autoptr(ShumateVectorReader) reader = NULL;
207 [ + - ]: 3 : g_autoptr(ShumateVectorReaderIter) iter = NULL;
208 [ + - ]: 6 : g_autoptr(GBytes) tile_data = create_test_tile ();
209 [ + - ]: 3 : g_auto(GValue) value = G_VALUE_INIT;
210 : :
211 [ - + ]: 3 : g_assert_nonnull (tile_data);
212 : :
213 : 3 : reader = shumate_vector_reader_new (tile_data);
214 [ - + ]: 3 : g_assert_nonnull (reader);
215 : :
216 : 3 : iter = shumate_vector_reader_iterate (reader);
217 [ - + ]: 3 : g_assert_nonnull (iter);
218 : :
219 [ - + ]: 3 : g_assert_cmpint (shumate_vector_reader_iter_get_layer_count (iter), ==, 2);
220 : :
221 : 3 : shumate_vector_reader_iter_read_layer (iter, 0);
222 [ - + ]: 3 : g_assert_cmpstr (shumate_vector_reader_iter_get_layer_name (iter), ==, "helloworld");
223 [ - + ]: 3 : g_assert_cmpint (shumate_vector_reader_iter_get_layer_extent (iter), ==, 4096);
224 [ - + ]: 3 : g_assert_cmpint (shumate_vector_reader_iter_get_layer_feature_count (iter), ==, 6);
225 : :
226 : 3 : shumate_vector_reader_iter_read_layer (iter, 1);
227 [ - + ]: 3 : g_assert_cmpstr (shumate_vector_reader_iter_get_layer_name (iter), ==, "helloworld2");
228 [ - + ]: 3 : g_assert_cmpint (shumate_vector_reader_iter_get_layer_extent (iter), ==, 100);
229 [ - + ]: 3 : g_assert_cmpint (shumate_vector_reader_iter_get_layer_feature_count (iter), ==, 0);
230 : 3 : }
231 : :
232 : : static void
233 : 3 : test_vector_reader_tags (void)
234 : : {
235 : 6 : g_autoptr(ShumateVectorReader) reader = NULL;
236 [ + - ]: 3 : g_autoptr(ShumateVectorReaderIter) iter = NULL;
237 [ + - ]: 6 : g_autoptr(GBytes) tile_data = create_test_tile ();
238 [ + - ]: 3 : g_auto(GValue) value = G_VALUE_INIT;
239 : 3 : g_autofree const char **keys;
240 : :
241 [ - + ]: 3 : g_assert_nonnull (tile_data);
242 : :
243 : 3 : reader = shumate_vector_reader_new (tile_data);
244 [ - + ]: 3 : g_assert_nonnull (reader);
245 : :
246 : 3 : iter = shumate_vector_reader_iterate (reader);
247 [ - + ]: 3 : g_assert_nonnull (iter);
248 : :
249 [ - + ]: 3 : g_assert_true (shumate_vector_reader_iter_read_layer_by_name (iter, "helloworld"));
250 [ - + ]: 3 : g_assert_true (shumate_vector_reader_iter_next_feature (iter));
251 [ - + ]: 3 : g_assert_cmpint (shumate_vector_reader_iter_get_feature_id (iter), ==, 1);
252 [ - + ]: 3 : g_assert_true (shumate_vector_reader_iter_get_feature_tag (iter, "hello", &value));
253 : :
254 : 3 : keys = shumate_vector_reader_iter_get_feature_keys (iter);
255 [ - + ]: 3 : g_assert_cmpint (g_strv_length ((char **)keys), ==, 1);
256 [ - + ]: 3 : g_assert_cmpstr (keys[0], ==, "hello");
257 [ - + ]: 3 : g_assert_null (keys[1]);
258 : :
259 [ - + ]: 3 : g_assert_cmpstr (g_value_get_string (&value), ==, "world");
260 : 3 : }
261 : :
262 : : static void
263 : 3 : test_vector_reader_geometry (void)
264 : : {
265 : 6 : g_autoptr(ShumateVectorReader) reader = NULL;
266 [ + - ]: 3 : g_autoptr(ShumateVectorReaderIter) iter = NULL;
267 [ + - ]: 6 : g_autoptr(GBytes) tile_data = create_test_tile ();
268 [ + - ]: 3 : g_auto(GValue) value = G_VALUE_INIT;
269 : 3 : double x, y;
270 : :
271 [ - + ]: 3 : g_assert_nonnull (tile_data);
272 : :
273 : 3 : reader = shumate_vector_reader_new (tile_data);
274 [ - + ]: 3 : g_assert_nonnull (reader);
275 : :
276 : 3 : iter = shumate_vector_reader_iterate (reader);
277 [ - + ]: 3 : g_assert_nonnull (iter);
278 : :
279 [ - + ]: 3 : g_assert_true (shumate_vector_reader_iter_read_layer_by_name (iter, "helloworld"));
280 : :
281 : : /* Point */
282 [ - + ]: 3 : g_assert_true (shumate_vector_reader_iter_next_feature (iter));
283 [ - + ]: 3 : g_assert_cmpint (shumate_vector_reader_iter_get_feature_geometry_type (iter), ==, SHUMATE_GEOMETRY_TYPE_POINT);
284 [ - + ]: 3 : g_assert_true (shumate_vector_reader_iter_get_feature_point (iter, &x, &y));
285 [ - + ]: 3 : g_assert_cmpfloat (x, ==, 1.0);
286 [ - + ]: 3 : g_assert_cmpfloat (y, ==, 2.0);
287 : :
288 : : /* MultiPoint */
289 [ - + ]: 3 : g_assert_true (shumate_vector_reader_iter_next_feature (iter));
290 [ - + ]: 3 : g_assert_cmpint (shumate_vector_reader_iter_get_feature_geometry_type (iter), ==, SHUMATE_GEOMETRY_TYPE_MULTIPOINT);
291 : :
292 : : /* LineString */
293 [ - + ]: 3 : g_assert_true (shumate_vector_reader_iter_next_feature (iter));
294 [ - + ]: 3 : g_assert_cmpint (shumate_vector_reader_iter_get_feature_geometry_type (iter), ==, SHUMATE_GEOMETRY_TYPE_LINESTRING);
295 : :
296 : : /* MultiLineString */
297 [ - + ]: 3 : g_assert_true (shumate_vector_reader_iter_next_feature (iter));
298 [ - + ]: 3 : g_assert_cmpint (shumate_vector_reader_iter_get_feature_geometry_type (iter), ==, SHUMATE_GEOMETRY_TYPE_MULTILINESTRING);
299 : :
300 : : /* Polygon */
301 [ - + ]: 3 : g_assert_true (shumate_vector_reader_iter_next_feature (iter));
302 [ - + ]: 3 : g_assert_cmpint (shumate_vector_reader_iter_get_feature_geometry_type (iter), ==, SHUMATE_GEOMETRY_TYPE_POLYGON);
303 [ - + ]: 3 : g_assert_true (shumate_vector_reader_iter_feature_contains_point (iter, 105, 205));
304 [ - + ]: 3 : g_assert_false (shumate_vector_reader_iter_feature_contains_point (iter, 175, 300));
305 [ - + ]: 3 : g_assert_false (shumate_vector_reader_iter_feature_contains_point (iter, 0, 0));
306 : :
307 : : /* Multipolygon */
308 [ - + ]: 3 : g_assert_true (shumate_vector_reader_iter_next_feature (iter));
309 [ - + ]: 3 : g_assert_cmpint (shumate_vector_reader_iter_get_feature_geometry_type (iter), ==, SHUMATE_GEOMETRY_TYPE_MULTIPOLYGON);
310 : : /* Simple case */
311 [ - + ]: 3 : g_assert_true (shumate_vector_reader_iter_feature_contains_point (iter, 105, 205));
312 : : /* Overlap */
313 [ - + ]: 3 : g_assert_true (shumate_vector_reader_iter_feature_contains_point (iter, 275, 300));
314 : : /* Interior ring + overlap*/
315 [ - + ]: 3 : g_assert_true (shumate_vector_reader_iter_feature_contains_point (iter, 225, 300));
316 : : /* Interior ring */
317 [ - + ]: 3 : g_assert_false (shumate_vector_reader_iter_feature_contains_point (iter, 175, 300));
318 : : /* Outside */
319 [ - + ]: 3 : g_assert_false (shumate_vector_reader_iter_feature_contains_point (iter, 0, 0));
320 : : /* Ray might pass through a corner */
321 [ - + ]: 3 : g_assert_false (shumate_vector_reader_iter_feature_contains_point (iter, 350, 299));
322 [ - + ]: 3 : g_assert_false (shumate_vector_reader_iter_feature_contains_point (iter, 350, 301));
323 [ - + ]: 3 : g_assert_false (shumate_vector_reader_iter_feature_contains_point (iter, 351, 300));
324 [ - + ]: 3 : g_assert_true (shumate_vector_reader_iter_feature_contains_point (iter, 349, 300));
325 : : /* Horizontal/vertical edges */
326 [ - + ]: 3 : g_assert_false (shumate_vector_reader_iter_feature_contains_point (iter, 99, 200));
327 [ - + ]: 3 : g_assert_false (shumate_vector_reader_iter_feature_contains_point (iter, 301, 200));
328 [ - + ]: 3 : g_assert_false (shumate_vector_reader_iter_feature_contains_point (iter, 100, 199));
329 [ - + ]: 3 : g_assert_false (shumate_vector_reader_iter_feature_contains_point (iter, 100, 401));
330 : 3 : }
331 : :
332 : : int
333 : 3 : main (int argc, char *argv[])
334 : : {
335 : 3 : g_test_init (&argc, &argv, NULL);
336 : :
337 : 3 : g_test_add_func ("/vector-reader/layers", test_vector_reader_layers);
338 : 3 : g_test_add_func ("/vector-reader/tags", test_vector_reader_tags);
339 : 3 : g_test_add_func ("/vector-reader/geometry", test_vector_reader_geometry);
340 : :
341 : 3 : return g_test_run ();
342 : : }
|