]> mj.ucw.cz Git - leo.git/blobdiff - map.c
Průvodce: Identifying endpoints
[leo.git] / map.c
diff --git a/map.c b/map.c
index 8f318e23e9427bafa5a65a7baf5417a2d1ed68ad..366d17a77217ea787ccbc37706f76a8202bf2089 100644 (file)
--- a/map.c
+++ b/map.c
@@ -4,7 +4,8 @@
  *     (c) 2014 Martin Mares <mj@ucw.cz>
  */
 
-#include <ucw/lib.h>
+#include "leo.h"
+
 #include <ucw/conf.h>
 #include <ucw/gary.h>
 #include <ucw/mempool.h>
@@ -13,8 +14,8 @@
 #include <stdio.h>
 #include <math.h>
 
-#include "leo.h"
 #include "osm.h"
+#include "shp.h"
 #include "map.h"
 #include "css.h"
 #include "sym.h"
@@ -44,6 +45,7 @@ static const char * const map_formats[] = {
   "invalid",
   "osmxml",
   "fixed",
+  "shape",
 };
 
 static struct cf_section map_source_cf = {
@@ -234,12 +236,22 @@ static void map_load_source(struct data_source *ds)
       break;
     case DATA_SOURCE_FIXED:
       msg(L_INFO, "Adding fixed objects");
+      if (!ds->file)
+       ds->file = "fixed";
       fixed_add();
       break;
+    case DATA_SOURCE_SHAPE:
+      msg(L_INFO, "Parsing %s as shape file", ds->file);
+      if (!ds->file)
+       die("Shape data sources must have a file name");
+      shp_parse(ds->file);
+      need_proj = 1;
+      break;
     default:
       die("Invalid data source format");
     }
 
+  osm_stats();
   if (debug_dump_source)
     {
       puts("=== Source data ===");
@@ -300,3 +312,94 @@ void map_apply_styles(struct svg *svg)
 
   // FIXME: Ought to destroy the style_results
 }
+
+struct gen_context {
+  struct osm_way *w;
+  struct osm_ref **refs;
+  uint in_nodes;
+  uint out_nodes;
+};
+
+static void generalize_recursively(struct gen_context *gc, int first, int last)
+{
+  if (last - first <= 1)
+    return;
+
+  double max_err = 0;
+  struct osm_node *f = (struct osm_node *) gc->refs[first]->o, *l = (struct osm_node *) gc->refs[last]->o;
+  double fx = f->x;
+  double fy = f->y;
+  double dx = l->x - fx;
+  double dy = l->y - fy;
+  double dd = dx*dx + dy*dy;
+
+  for (int i = first + 1; i < last; i++)
+    {
+      struct osm_node *n = (struct osm_node *) gc->refs[i]->o;
+      double nx = n->x - f->x;
+      double ny = n->y - f->y;
+      double p = dx*nx + dy*ny;                // (px,py) = projection of (nx,ny) onto (dx,dy)
+      double px = dx*p / dd;
+      double py = dy*p / dd;
+      double ex = px - nx;             // (ex,ey) is the error vector: (nx,ny) minus its projection
+      double ey = py - ny;
+      double e = ex*ex + ey*ey;
+      max_err = MAX(max_err, e);
+    }
+
+  double close = 5;
+  if (max_err > close*close)
+    {
+      int mid = (first + last) / 2;
+      ASSERT(first < mid && mid < last);
+      generalize_recursively(gc, first, mid);
+      clist_add_tail(&gc->w->nodes, &gc->refs[mid]->n);
+      generalize_recursively(gc, mid, last);
+    }
+}
+
+static void generalize_way(struct gen_context *gc, struct osm_way *w)
+{
+  gc->w = w;
+  GARY_RESIZE(gc->refs, 0);
+
+  CLIST_FOR_EACH(struct osm_ref *, r, w->nodes)
+    *GARY_PUSH(gc->refs) = r;
+
+  int N = GARY_SIZE(gc->refs);
+  if (N <= 2)
+    return;
+
+  gc->in_nodes += N;
+
+#if 0
+  for (int i=0; i<N; i++)
+    {
+      struct osm_node *n = (struct osm_node *) gc->refs[i]->o;
+      msg(L_DEBUG, "Generalize: @%d #%jd [%f,%f]", i, (intmax_t) n->o.id, n->x, n->y);
+    }
+#endif
+
+  clist_init(&w->nodes);
+  clist_add_tail(&w->nodes, &gc->refs[0]->n);
+  generalize_recursively(gc, 0, N-1);
+  clist_add_tail(&w->nodes, &gc->refs[N-1]->n);
+
+  CLIST_FOR_EACH(struct osm_ref *, r, w->nodes)
+    gc->out_nodes++;
+}
+
+void map_generalize(void)
+{
+  msg(L_INFO, "Generalizing ways");
+  struct gen_context gc = { };
+  GARY_INIT(gc.refs, 0);
+
+  CLIST_FOR_EACH(struct data_source *, ds, map_sources)
+    CLIST_FOR_EACH(struct osm_way *, w, ds->osm->obj_list[OSM_TYPE_WAY])
+      generalize_way(&gc, w);
+
+  GARY_FREE(gc.refs);
+
+  msg(L_INFO, "Generalization: %u nodes in, %u nodes out", gc.in_nodes, gc.out_nodes);
+}