]> mj.ucw.cz Git - leo.git/commitdiff
Simplify: Splitting of ways to non-branching segments
authorMartin Mares <mj@ucw.cz>
Sun, 27 Mar 2022 21:03:03 +0000 (23:03 +0200)
committerMartin Mares <mj@ucw.cz>
Sun, 27 Mar 2022 21:03:03 +0000 (23:03 +0200)
This is to make the segments mergeable.

leo.c
simplify.c

diff --git a/leo.c b/leo.c
index e957ec8a1a9842f3a40f361b96535a8946ede1ae..d7a39bd0f18aea3456ead193fad04b618dd93b6c 100644 (file)
--- a/leo.c
+++ b/leo.c
@@ -126,7 +126,7 @@ int main(int argc UNUSED, char **argv)
   map_load_sources();
   graph_build();
   map_set_scale();
-  map_generalize();
+  // map_generalize();
 
   struct svg *svg = svg_open(map_svg_output);
   if (!map_rotate)
index 7c69cf3135ff4cb08019d7b8cd30cb171af81690..f5dc717edad92b0c4eecacd3e820428da2e62021 100644 (file)
@@ -4,6 +4,7 @@
  *     (c) 2022 Martin Mares <mj@ucw.cz>
  */
 
+// #define LOCAL_DEBUG
 // #pragma GCC optimize("-O0")
 
 #include "leo.h"
@@ -32,6 +33,7 @@ struct simp_way_ref {
   cnode n;
   struct simp_node *snode;
   struct symbol *sym;
+  z_index_t zindex;
   struct osm_way *way;
   struct osm_node *node;
   struct simp_way_ref *prev_on_way;
@@ -68,7 +70,7 @@ static struct simp_node *simp_lookup_node(struct osm_node *n)
   return simp_hash_lookup((byte *) &c);
 }
 
-static void simp_register_symbol(struct symbol *sym)
+static void simp_register_symbol(struct symbol *sym, z_index_t zindex)
 {
   struct osm_object *o = sym->o;
 
@@ -109,6 +111,7 @@ static void simp_register_symbol(struct symbol *sym)
            struct simp_way_ref *wref = mp_alloc(simp_pool, sizeof(*wref));
            wref->snode = s;
            wref->sym = sym;
+           wref->zindex = zindex;
            wref->node = n;
            wref->way = w;
            wref->prev_on_way = wr_last;
@@ -161,8 +164,10 @@ static struct simp_way_ref *wref_only_other(struct simp_node *sn, struct simp_wa
   return out_wr;
 }
 
+/*** Merging of ways ***/
+
 static struct simp_way_ref **merge_wrefs;
-static uint simp_merged_ways, simp_merged_segments;
+static uint num_merged_ways, num_merged_segments;
 
 static void simp_merge_way(struct simp_node *s)
 {
@@ -239,7 +244,7 @@ static void simp_merge_way(struct simp_node *s)
     return;
 
   DBG("Will merge");
-  simp_merged_ways++;
+  num_merged_ways++;
 
   struct osm_way *nw = osm_way_new(++simp_last_id);
   struct symbol *main_sym = NULL;
@@ -275,11 +280,11 @@ static void simp_merge_way(struct simp_node *s)
            }
        }
 
-      simp_merged_segments++;
+      num_merged_segments++;
     }
 
   // osm_obj_dump(&nw->o);
-  simp_register_symbol(main_sym);
+  simp_register_symbol(main_sym, wr1->zindex);
   // ((struct sym_line *) main_sym)->color = 0x0000ff;
 }
 
@@ -291,7 +296,81 @@ static void simp_merge_ways(void)
     }
   HASH_END_FOR;
 
-  msg(L_INFO, "Simplify: Merged %u segments to %u new ways", simp_merged_segments, simp_merged_ways);
+  msg(L_INFO, "Simplify: Merged %u segments to %u new ways", num_merged_segments, num_merged_ways);
+}
+
+/*** Splitting of ways ***/
+
+static struct simp_way_ref **split_breakpoints;
+static uint num_split_ways, num_split_segments;
+
+static void simp_split_way(struct simp_way_ref *wr)
+{
+  GARY_RESIZE(split_breakpoints, 0);
+  for (struct simp_way_ref *tr=wr; tr; tr=tr->next_on_way)
+    if (tr->prev_on_way && tr->next_on_way)
+      {
+       struct simp_node *sn = tr->snode;
+       struct simp_way_ref *x = clist_head(&sn->way_refs);
+       if (x && clist_next(&sn->way_refs, &x->n))
+         *GARY_PUSH(split_breakpoints) = tr;
+      }
+
+  uint num_bp = GARY_SIZE(split_breakpoints);
+  if (!num_bp)
+    return;
+
+  DBG("Split: Want to split wr %p (%u times)", wr, num_bp);
+  // ((struct sym_line *) wr->sym)->color = 0x0000ff;
+  num_split_ways++;
+
+  uint bp = 0;
+  struct symbol *orig_sym = wr->sym;
+  struct symbol *sym = NULL;
+  struct osm_way *w = NULL;
+
+  for (struct simp_way_ref *tr=wr; tr; tr=tr->next_on_way)
+    {
+      clist_remove(&tr->n);
+      if (!sym)
+       {
+         w = osm_way_new(++simp_last_id);
+         sym = sym_clone(orig_sym);
+         sym->o = &w->o;
+       }
+      osm_way_add_node(w, tr->node);
+      if (bp < num_bp && split_breakpoints[bp] == tr)
+       {
+         sym_plan(sym, wr->zindex);
+         num_split_segments++;
+         sym = NULL;
+         w = NULL;
+         bp++;
+       }
+    }
+
+  if (sym)
+    {
+      num_split_segments++;
+      sym_plan(sym, wr->zindex);
+      simp_register_symbol(sym, wr->zindex);
+    }
+
+  sym_disable(orig_sym);
+}
+
+static void simp_split_ways(void)
+{
+  HASH_FOR_ALL(simp_hash, s)
+    {
+      struct simp_way_ref *wr, *tmp;
+      CLIST_WALK_DELSAFE(wr, s->way_refs, tmp)
+       if (!wr->prev_on_way && wr->next_on_way)
+         simp_split_way(wr);
+    }
+  HASH_END_FOR;
+
+  msg(L_INFO, "Simplify: Split %u ways to %u segments", num_split_ways, num_split_segments);
 }
 
 void simplify(void)
@@ -300,9 +379,11 @@ void simplify(void)
   simp_pool = mp_new(65536);
   simp_osm = osm_init();
   GARY_INIT_ALLOC(merge_wrefs, 0, &simp_pool->allocator);
+  GARY_INIT_ALLOC(split_breakpoints, 0, &simp_pool->allocator);
   simp_hash_init();
 
   sym_for_all_planned(simp_register_symbol);
+  simp_split_ways();
   simp_merge_ways();
 
   mp_delete(simp_pool);