]> mj.ucw.cz Git - leo.git/blob - map.c
Moved auxiliary tools to their own directory
[leo.git] / map.c
1 /*
2  *      Hic Est Leo -- Global Map Operations
3  *
4  *      (c) 2014 Martin Mares <mj@ucw.cz>
5  */
6
7 #include <ucw/lib.h>
8 #include <ucw/conf.h>
9 #include <ucw/gary.h>
10 #include <ucw/mempool.h>
11
12 #include <stdio.h>
13 #include <math.h>
14
15 #include "leo.h"
16 #include "osm.h"
17 #include "map.h"
18
19 double map_min_x, map_min_y;
20 double map_max_x, map_max_y;
21 double page_width, page_height;
22 uns map_clip, map_draw_border;
23 char *map_xml_input;
24 char *map_projection;
25 char *map_style_sheet;
26 char *map_svg_output;
27
28 static struct cf_section map_cf = {
29   CF_ITEMS {
30     CF_DOUBLE("MinX", &map_min_x),
31     CF_DOUBLE("MinY", &map_min_y),
32     CF_DOUBLE("MaxX", &map_max_x),
33     CF_DOUBLE("MaxY", &map_max_y),
34     CF_DOUBLE("PageWidth", &page_width),
35     CF_DOUBLE("PageHeight", &page_height),
36     CF_UNS("Clip", &map_clip),
37     CF_UNS("DrawBorder", &map_draw_border),
38     CF_STRING("XMLInput", &map_xml_input),
39     CF_STRING("Projection", &map_projection),
40     CF_STRING("StyleSheet", &map_style_sheet),
41     CF_STRING("SVGOutput", &map_svg_output),
42     CF_END
43   }
44 };
45
46 static void CONSTRUCTOR map_preinit(void)
47 {
48   cf_declare_section("Map", &map_cf, 0);
49 }
50
51 // Calculated
52 double map_scale;
53 double page_offset_x, page_offset_y;
54 double page_map_width, page_map_height;
55
56 void map_set_scale(void)
57 {
58   double x_range = map_max_x - map_min_x;
59   double y_range = map_max_y - map_min_y;
60   double x_scale = page_width / x_range;
61   double y_scale = page_height / y_range;
62   map_scale = MIN(x_scale, y_scale);
63   page_map_width = x_range * map_scale;
64   page_map_height = y_range * map_scale;
65   page_offset_x = (page_width - page_map_width) / 2;
66   page_offset_y = (page_height - page_map_height) / 2;
67
68   msg(L_INFO, "Setting scale %.3g (orig window [%.6g,%.6g], page window [%.6g,%.6g]+[%.6g,%.6g] on [%.6g,%.6g])",
69     map_scale,
70     x_range, y_range,
71     page_map_width, page_map_height,
72     page_offset_x, page_offset_y,
73     page_width, page_height);
74
75   double pmin_x = INFINITY, pmax_x = -INFINITY;
76   double pmin_y = INFINITY, pmax_y = -INFINITY;
77   double rmin_x = INFINITY, rmax_x = -INFINITY;
78   double rmin_y = INFINITY, rmax_y = -INFINITY;
79   CLIST_FOR_EACH(struct osm_node *, n, osm_obj_list[OSM_TYPE_NODE])
80     {
81       pmin_x = MIN(pmin_x, n->x);
82       pmax_x = MAX(pmax_x, n->x);
83       pmin_y = MIN(pmin_y, n->y);
84       pmax_y = MAX(pmax_y, n->y);
85       n->x = (n->x - map_min_x) * map_scale + page_offset_x;
86       n->y = page_height - page_offset_y - (n->y - map_min_y) * map_scale;
87       rmin_x = MIN(rmin_x, n->x);
88       rmax_x = MAX(rmax_x, n->x);
89       rmin_y = MIN(rmin_y, n->y);
90       rmax_y = MAX(rmax_y, n->y);
91     }
92   msg(L_INFO, "Bounds before scaling: [%.10g,%.10g] x [%.10g,%.10g]", pmin_x, pmax_x, pmin_y, pmax_y);
93   msg(L_INFO, "Bounds after scaling: [%.10g,%.10g] x [%.10g,%.10g]", rmin_x, rmax_x, rmin_y, rmax_y);
94 }
95
96 bool map_object_visible_p(struct osm_object *o)
97 {
98   double margin = 10;
99
100   switch (o->type)
101     {
102     case OSM_TYPE_NODE:
103       {
104         struct osm_node *n = (struct osm_node *) o;
105         return (n->x >= page_offset_x - margin && n->x <= page_offset_x + page_map_width + margin &&
106                 n->y >= page_offset_y - margin && n->y <= page_offset_y + page_map_height + margin);
107       }
108     case OSM_TYPE_WAY:
109       {
110         struct osm_way *w = (struct osm_way *) o;
111         bool ok = 0;
112         OSM_FOR_EACH_BEGIN(struct osm_object *, n, w->nodes)
113           {
114             ok |= map_object_visible_p(n);
115           }
116         OSM_FOR_EACH_END;
117         return ok;
118       }
119     case OSM_TYPE_RELATION:
120       {
121         struct osm_relation *r = (struct osm_relation *) o;
122         bool ok = 0;
123         OSM_FOR_EACH_BEGIN(struct osm_object *, n, r->members)
124           {
125             ok |= map_object_visible_p(n);
126           }
127         OSM_FOR_EACH_END;
128         return ok;
129       }
130     case OSM_TYPE_MULTIPOLYGON:
131       return map_object_visible_p(&((struct osm_multipolygon *) o)->rel->o);
132     default:
133       ASSERT(0);
134     }
135 }