]> mj.ucw.cz Git - leo.git/blob - simplify.c
Experiments with simplication of ways
[leo.git] / simplify.c
1 /*
2  *      Hic Est Leo -- Map Simplification
3  *
4  *      (c) 2022 Martin Mares <mj@ucw.cz>
5  */
6
7 #include "leo.h"
8
9 #include <ucw/lib.h>
10 #include <ucw/clists.h>
11 #include <ucw/mempool.h>
12
13 #include <stdio.h>
14 #include <math.h>
15
16 #include "osm.h"
17 #include "map.h"
18 #include "simplify.h"
19
20 static struct mempool *simp_pool;
21
22 struct coords {
23   double x, y;
24 };
25
26 struct simp_node_ref {
27   cnode n;
28   struct osm_node *to;
29 };
30
31 struct simp_way_ref {
32   cnode n;
33   struct osm_way *to;
34   bool is_end;
35 };
36
37 struct simp_node {
38   union {
39     struct coords c;
40     byte raw_coords[sizeof(struct coords)];
41   };
42   clist node_refs;
43   clist way_refs;
44   byte can_be_merged;
45 };
46
47 static void simp_hash_init_data(struct simp_node *s)
48 {
49   clist_init(&s->node_refs);
50   clist_init(&s->way_refs);
51   s->can_be_merged = false;
52 }
53
54 #define HASH_NODE struct simp_node
55 #define HASH_PREFIX(x) simp_hash_##x
56 #define HASH_KEY_MEMORY raw_coords
57 #define HASH_KEY_SIZE sizeof(struct coords)
58 #define HASH_WANT_LOOKUP
59 #define HASH_GIVE_INIT_DATA
60 #define HASH_USE_POOL simp_pool
61 #define HASH_TABLE_ALLOC
62 #include <ucw/hashtable.h>
63
64 static bool simp_can_be_merged(struct simp_node *s)
65 {
66   uint num_nodes = clist_size(&s->node_refs);
67   uint num_ways = clist_size(&s->way_refs);
68
69   ASSERT(num_nodes);
70   if (num_nodes > 1)
71     {
72       msg(L_WARN, "Simplify: Multiple (%u) nodes at [%f, %f]", num_nodes, s->c.x, s->c.y);
73       return false;
74     }
75
76   if (num_ways > 2)
77     return false;
78
79   return false;
80 }
81
82 static void simplify_source(struct data_source *ds)
83 {
84   msg(L_INFO, "Simplifying source %s", ds->file);
85   simp_pool = mp_new(65536);
86   simp_hash_init();
87   osm_this = ds->osm;
88
89   CLIST_FOR_EACH(struct osm_way *, w, osm_this->obj_list[OSM_TYPE_WAY])
90     {
91       struct osm_node *n_first = (struct osm_node *) osm_ref_head(&w->nodes);
92       struct osm_node *n_last = (struct osm_node *) osm_ref_tail(&w->nodes);
93
94       OSM_FOR_EACH_BEGIN(struct osm_node *, n, w->nodes)
95         {
96           struct coords c = { .x = n->x, .y = n->y };
97           struct simp_node *s = simp_hash_lookup((byte *) &c);
98
99           struct simp_node_ref *nref = mp_alloc(simp_pool, sizeof(*nref));
100           nref->to = n;
101           clist_add_tail(&s->node_refs, &nref->n);
102
103           struct simp_way_ref *wref = mp_alloc(simp_pool, sizeof(*wref));
104           wref->to = w;
105           wref->is_end = (n == n_first || n == n_last);
106           clist_add_tail(&s->way_refs, &wref->n);
107         }
108       OSM_FOR_EACH_END;
109     }
110
111   HASH_FOR_ALL(simp_hash, s)
112     {
113       s->can_be_merged = simp_can_be_merged(s);
114     }
115   HASH_END_FOR;
116
117   mp_delete(simp_pool);
118 }
119
120 void simplify(void)
121 {
122   CLIST_FOR_EACH(struct data_source *, ds, map_sources)
123     simplify_source(ds);
124 }