]> mj.ucw.cz Git - leo.git/blob - leo.c
Switched to UCW configure and build system
[leo.git] / leo.c
1 /*
2  *      Hic Est Leo -- Main Program
3  *
4  *      (c) 2014 Martin Mares <mj@ucw.cz>
5  */
6
7 #include <ucw/lib.h>
8 #include <ucw/conf.h>
9 #include <ucw/opt.h>
10
11 #include <stdio.h>
12
13 #include "leo.h"
14 #include "osm.h"
15 #include "svg.h"
16 #include "style.h"
17 #include "css.h"
18 #include "sym.h"
19 #include "map.h"
20
21 #undef ROTATE
22
23 uns debug_dump_source, debug_dump_after_proj, debug_dump_after_scaling;
24 uns debug_dump_multipolygons, debug_dump_css, debug_dump_styling, debug_dump_symbols;
25
26 static struct cf_section debug_cf = {
27   CF_ITEMS {
28     CF_UNS("DumpSource", &debug_dump_source),
29     CF_UNS("DumpAfterProj", &debug_dump_after_proj),
30     CF_UNS("DumpAfterScaling", &debug_dump_after_scaling),
31     CF_UNS("DumpMultipolygons", &debug_dump_multipolygons),
32     CF_UNS("DumpCSS", &debug_dump_css),
33     CF_UNS("DumpStyling", &debug_dump_styling),
34     CF_UNS("DumpSymbols", &debug_dump_symbols),
35     CF_END
36   }
37 };
38
39 static const struct opt_section options = {
40   OPT_ITEMS {
41     OPT_HELP("Hic Est Leo -- Experimental Map Renderer"),
42     OPT_HELP(""),
43     OPT_HELP("Options:"),
44     OPT_HELP_OPTION,
45     OPT_CONF_OPTIONS,
46     OPT_END
47   }
48 };
49
50 // FIXME: Make generic
51 static void draw_scale(struct svg *svg)
52 {
53   double dist = 1000;
54   double width = dist * map_scale;
55   double x = page_width - 10 - width;
56   double y = 50;
57
58   svg_push_element(svg, "g");
59   svg_set_attr(svg, "id", "scale");
60   svg_set_attr_format(svg, "transform", "translate(%.6g,%.6g)", x * svg->scale, y * svg->scale);
61
62   for (int outline=1; outline>=0; outline--)
63     {
64       svg_push_element(svg, "g");
65       svg_set_attr(svg, "stroke-linecap", "square");
66       if (outline)
67         {
68           svg_set_attr_dimen(svg, "stroke-width", 1.5);
69           svg_set_attr_color(svg, "stroke", 0xffffff);
70         }
71       else
72         {
73           svg_set_attr_dimen(svg, "stroke-width", 0.5);
74           svg_set_attr_color(svg, "stroke", 0);
75         }
76
77       svg_push_element(svg, "line");
78       svg_set_attr_dimen(svg, "x1", 0);
79       svg_set_attr_dimen(svg, "y1", 0);
80       svg_set_attr_dimen(svg, "x2", width);
81       svg_set_attr_dimen(svg, "y2", 0);
82       svg_pop(svg);
83
84       for (int i=0; i<=10; i++)
85         {
86           double tick;
87           switch (i)
88             {
89             case 0:
90             case 10:
91               tick = 3;
92               break;
93             case 5:
94               tick = 2;
95               break;
96             default:
97               tick = 1;
98             }
99           svg_push_element(svg, "line");
100           svg_set_attr_dimen(svg, "x1", width * i/10);
101           svg_set_attr_dimen(svg, "y1", 0);
102           svg_set_attr_dimen(svg, "x2", width * i/10);
103           svg_set_attr_dimen(svg, "y1", -tick);
104           svg_pop(svg);
105         }
106
107       svg_pop(svg);
108     }
109
110   scale_text(svg, 0, 5, osm_val_encode("0"));
111   scale_text(svg, width, 5, osm_val_encode("1 km"));
112   svg_pop(svg);
113 }
114
115 int main(int argc UNUSED, char **argv)
116 {
117   cf_def_file = "map.cf";
118   cf_declare_section("Debug", &debug_cf, 0);
119   opt_parse(&options, argv+1);
120
121   osm_init();
122   styles_init();
123
124   msg(L_INFO, "Parsing OSM");
125   osm_xml_parse(map_xml_input);
126   if (debug_dump_source)
127     {
128       puts("=== Source data ===");
129       osm_dump();
130     }
131   osm_make_multipolygons();
132
133   msg(L_INFO, "Projecting");
134   osm_project(map_projection);
135   if (debug_dump_after_proj)
136     {
137       puts("=== Map after projection ===");
138       osm_dump();
139     }
140
141   map_set_scale();
142   if (debug_dump_after_scaling)
143     {
144       puts("=== Map after scaling ===");
145       osm_dump();
146     }
147
148   struct css_sheet *ss = css_load(map_style_sheet);
149   if (debug_dump_css)
150     {
151       puts("=== Stylesheet ===");
152       css_dump(ss);
153     }
154
155   struct svg *svg = svg_open(map_svg_output);
156 #ifndef ROTATE
157   svg_set_attr_dimen(svg, "width", page_width);
158   svg_set_attr_dimen(svg, "height", page_height);
159 #else
160   svg_set_attr_dimen(svg, "width", page_height);
161   svg_set_attr_dimen(svg, "height", page_width);
162 #endif
163
164   struct style_results r;
165   style_init(&r);
166   sym_init();
167
168   msg(L_INFO, "Applying stylesheet");
169   for (uns i = OSM_TYPE_NODE; i <= OSM_TYPE_MULTIPOLYGON; i++)
170     CLIST_FOR_EACH(struct osm_object *, o, osm_obj_list[i])
171       {
172         if (debug_dump_styling)
173           {
174             puts("===============================");
175             osm_obj_dump(o);
176           }
177         if (!map_object_visible_p(o))
178           {
179             if (debug_dump_styling)
180               printf("--> invisible\n");
181             continue;
182           }
183         style_begin(&r, o);
184         css_apply(ss, &r);
185         if (debug_dump_styling)
186           style_dump(&r);
187         sym_from_style(o, &r, svg);
188         style_end(&r);
189       }
190
191   if (map_clip)
192     {
193       svg_push_element(svg, "defs");
194       svg_push_element(svg, "clipPath");
195       svg_set_attr(svg, "id", "boundary");
196       svg_push_path(svg);
197       svg_path_move_to(svg, page_offset_x, page_offset_y);
198       svg_path_line_to_rel(svg, page_map_width, 0);
199       svg_path_line_to_rel(svg, 0, page_map_height);
200       svg_path_line_to_rel(svg, -page_map_width, 0);
201       svg_path_close(svg);
202       svg_path_end(svg);
203       svg_pop(svg);
204       svg_pop(svg);
205       svg_pop(svg);
206
207       svg_push_element(svg, "g");
208       svg_set_attr_format(svg, "clip-path", "url(#boundary)");
209 #ifdef ROTATE
210       svg_set_attr_format(svg, "transform", "translate(%.6g,0) rotate(90)", page_height * svg->scale);
211 #endif
212     }
213
214   // FIXME: Replace by generic logo drawing facility
215   struct svg_icon *logo = svg_icon_load(svg, "../logo/kocka-s-okrajem.svg");
216
217   sym_draw_all(svg);
218
219   // Draw logo
220   double logo_width = 36.12;
221   double logo_height = 36.12 / logo->width * logo->height;
222   struct svg_icon_request sir = {
223     .icon = logo,
224     .x = page_width - 12 - logo_width / 2,
225     .y = 10 + logo_height / 2,
226     .width = logo_width,
227     .height = logo_height,
228   };
229   svg_icon_put(svg, &sir);
230
231   draw_scale(svg);
232
233   if (map_clip)
234     svg_pop(svg);
235
236   if (map_draw_border)
237     {
238       svg_push_element(svg, "rect");
239       svg_set_attr_dimen(svg, "x", page_offset_x);
240       svg_set_attr_dimen(svg, "y", page_offset_y);
241       svg_set_attr_dimen(svg, "width", page_map_width);
242       svg_set_attr_dimen(svg, "height", page_map_height);
243       svg_set_attr(svg, "fill", "none");
244       svg_set_attr(svg, "stroke", "blue");
245       svg_set_attr_dimen(svg, "stroke-width", 0.2);
246       svg_pop(svg);
247     }
248
249   svg_close(svg);
250
251   msg(L_INFO, "Finished");
252   return 0;
253 }