]> mj.ucw.cz Git - leo.git/blob - map.c
Rotation controlled by a config option
[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_rotate, 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("Rotate", &map_rotate),
38     CF_UNS("DrawBorder", &map_draw_border),
39     CF_STRING("XMLInput", &map_xml_input),
40     CF_STRING("Projection", &map_projection),
41     CF_STRING("StyleSheet", &map_style_sheet),
42     CF_STRING("SVGOutput", &map_svg_output),
43     CF_END
44   }
45 };
46
47 static void CONSTRUCTOR map_preinit(void)
48 {
49   cf_declare_section("Map", &map_cf, 0);
50 }
51
52 // Calculated
53 double map_scale;
54 double page_offset_x, page_offset_y;
55 double page_map_width, page_map_height;
56
57 void map_set_scale(void)
58 {
59   double x_range = map_max_x - map_min_x;
60   double y_range = map_max_y - map_min_y;
61   double x_scale = page_width / x_range;
62   double y_scale = page_height / y_range;
63   map_scale = MIN(x_scale, y_scale);
64   page_map_width = x_range * map_scale;
65   page_map_height = y_range * map_scale;
66   page_offset_x = (page_width - page_map_width) / 2;
67   page_offset_y = (page_height - page_map_height) / 2;
68
69   msg(L_INFO, "Setting scale %.3g (orig window [%.6g,%.6g], page window [%.6g,%.6g]+[%.6g,%.6g] on [%.6g,%.6g])",
70     map_scale,
71     x_range, y_range,
72     page_map_width, page_map_height,
73     page_offset_x, page_offset_y,
74     page_width, page_height);
75
76   double pmin_x = INFINITY, pmax_x = -INFINITY;
77   double pmin_y = INFINITY, pmax_y = -INFINITY;
78   double rmin_x = INFINITY, rmax_x = -INFINITY;
79   double rmin_y = INFINITY, rmax_y = -INFINITY;
80   CLIST_FOR_EACH(struct osm_node *, n, osm_obj_list[OSM_TYPE_NODE])
81     {
82       pmin_x = MIN(pmin_x, n->x);
83       pmax_x = MAX(pmax_x, n->x);
84       pmin_y = MIN(pmin_y, n->y);
85       pmax_y = MAX(pmax_y, n->y);
86       n->x = (n->x - map_min_x) * map_scale + page_offset_x;
87       n->y = page_height - page_offset_y - (n->y - map_min_y) * map_scale;
88       rmin_x = MIN(rmin_x, n->x);
89       rmax_x = MAX(rmax_x, n->x);
90       rmin_y = MIN(rmin_y, n->y);
91       rmax_y = MAX(rmax_y, n->y);
92     }
93   msg(L_INFO, "Bounds before scaling: [%.10g,%.10g] x [%.10g,%.10g]", pmin_x, pmax_x, pmin_y, pmax_y);
94   msg(L_INFO, "Bounds after scaling: [%.10g,%.10g] x [%.10g,%.10g]", rmin_x, rmax_x, rmin_y, rmax_y);
95 }
96
97 bool map_object_visible_p(struct osm_object *o)
98 {
99   double margin = 10;
100
101   switch (o->type)
102     {
103     case OSM_TYPE_NODE:
104       {
105         struct osm_node *n = (struct osm_node *) o;
106         return (n->x >= page_offset_x - margin && n->x <= page_offset_x + page_map_width + margin &&
107                 n->y >= page_offset_y - margin && n->y <= page_offset_y + page_map_height + margin);
108       }
109     case OSM_TYPE_WAY:
110       {
111         struct osm_way *w = (struct osm_way *) o;
112         bool ok = 0;
113         OSM_FOR_EACH_BEGIN(struct osm_object *, n, w->nodes)
114           {
115             ok |= map_object_visible_p(n);
116           }
117         OSM_FOR_EACH_END;
118         return ok;
119       }
120     case OSM_TYPE_RELATION:
121       {
122         struct osm_relation *r = (struct osm_relation *) o;
123         bool ok = 0;
124         OSM_FOR_EACH_BEGIN(struct osm_object *, n, r->members)
125           {
126             ok |= map_object_visible_p(n);
127           }
128         OSM_FOR_EACH_END;
129         return ok;
130       }
131     case OSM_TYPE_MULTIPOLYGON:
132       return map_object_visible_p(&((struct osm_multipolygon *) o)->rel->o);
133     default:
134       ASSERT(0);
135     }
136 }