1 #ifndef LNANOHTMLTILEDMAP_HTML_C
2 #define LNANOHTMLTILEDMAP_HTML_C
5 #include <ulinux/compiler_types.h>
6 #include <ulinux/types.h>
8 #include <ulinux/utils/ascii/string/vsprintf.h>
9 #include <ulinux/utils/ascii/block/conv/decimal/decimal.h>
13 /*============================================================================*/
14 #include "common_cpp.h"
15 #include "namespace/ulinux.h"
16 /*============================================================================*/
18 * decimal longitude/latitude: sign + integer part = 3 decimal digits (180)
19 * + radix + fractional part = 9 digits (micron/overkill precision)
21 #define GEO_DECIMAL_MAX "-123.123456789"
22 #define U32_DECIMAL_DIGITS_N_MAX "4294967295"
23 #define U64_HEXA_DIGITS_N_MAX "XXXXXXXXXXXXXXXX"
25 * this is an html template
26 * p suffix means prolog/header
27 * e suffix means epilog/trailer
29 /* we cheat: we generate the http response headers here */
32 cache-control:no-cache\r\n\
34 content-type:text/html;charset=utf-8\r\n\
38 <table rules=\"all\" id=\"major_layout_table\">\n\
41 <td id=\"tiles_cell\" align=\"center\">\n"
43 <table rules=\"all\" id=\"tiles_layout_table\" cellpadding=\"0\" cellspacing=\"0\">\n\
45 /* min longitude, max longitude */
46 #define VIEWTBL_VERTHDRS_P "\
48 #define VIEWTBL_VERTHDRS_WEST "\
49 <th scope=\"col\" align=\"left\">%s</th>\n"
50 #define VIEWTBL_VERTHDRS_EAST "\
51 <th scope=\"col\" align=\"right\">%s</th>\n"
52 #define VIEWTBL_VERTHDRS_E "\
55 #define VIEWTBL_MAINROW_P "\
57 /* span horizontal headers rows and vertical header columns */
58 #define VIEWTBL_TILE "\
59 <td colspan=\"2\" rowspan=\"2\" align=\"center\" valign=\"middle\">\n\
60 <img src=\"" CONFIG_TILE_SVR "\"/>\n\
63 #define VIEWTBL_MAINROW_HORIZTRAILER_CELL_TOP "\
64 <th valign=\"top\">%s</th>\n"
65 #define VIEWTBL_MAINROW_E "\
68 #define VIEWTBL_HORIZTRAILER_ROW_BOT "\
70 <th valign=\"bottom\">%s</th>\n\
75 #define MAJORTBL_VIEWTBL_TO_NAVFORM "\
79 <td id=\"navigation_cell\" align=\"center\">\n\
80 <form action=\".\" method=\"get\">\n"
82 <input type=\"hidden\" name=\"urandom\" value=\"%u\"/>\n"
84 <input type=\"hidden\" name=\"x\" value=\"%u\"/>\n"
86 <input type=\"hidden\" name=\"y\" value=\"%u\"/>\n"
88 <table rules=\"all\">\n\
91 <td colspan=\"2\" align=\"center\">\n\
93 <legend><em>center coordinates</em></legend>\n"
95 <label>longitude = <input name=\"lo\" type=\"text\" maxlength=\"14\" value=\"%s\"/></label>\n"
97 <label>latitude = <input name=\"la\" type=\"text\" maxlength=\"14\" value=\"%s\"/></label>\n"
98 #define NAVTBL_MIDDLE "\
99 <button name=\"nav\" value=\"geo_modify\">MODIFY</button>\n\
104 <td align=\"center\">\n\
106 <legend><em>translation</em></legend>\n\
110 <td colspan=\"2\" align=\"center\">\n\
111 <button name=\"nav\" value=\"translation_north\">NORTH</button>\n\
116 <button name=\"nav\" value=\"translation_west\">WEST</button>\n\
119 <button name=\"nav\" value=\"translation_east\">EAST</button>\n\
123 <td colspan=\"2\" align=\"center\">\n\
124 <button name=\"nav\" value=\"translation_south\">SOUTH</button>\n\
131 <td align=\"center\">\n\
133 <legend><em>zoom</em></legend>\n"
134 #define NAVTBL_ZOOM "\
135 <label>level = <input name=\"zoom\" type=\"text\" maxlength=\"2\" value=\"%u\"/></label>\n"
137 <button name=\"nav\" value=\"zoom_modify\">MODIFY</button>\n\
138 <button name=\"nav\" value=\"zoom_plus\">PLUS</button>\n\
139 <button name=\"nav\" value=\"zoom_minus\">MINUS</button>\n\
145 #define MAJORTBL_E "\
153 /* maximum sizes of template parts */
154 #define VIEWTBL_VERTHDRS_WEST_SZ_MAX \
155 (SZ(VIEWTBL_VERTHDRS_WEST) - SZ("%s") + SZ(GEO_DECIMAL_MAX))
157 #define VIEWTBL_VERTHDRS_EAST_SZ_MAX \
158 (SZ(VIEWTBL_VERTHDRS_EAST) - SZ("%s") + SZ(GEO_DECIMAL_MAX))
160 #define VIEWTBL_TILE_SZ_MAX \
161 (SZ(VIEWTBL_TILE) - (SZ("%c") + CONFIG_HORIZS_N_MAX * SZ("%u")) \
162 + SZ(CONFIG_TILE_SVR_MAX))
164 #define VIEWTBL_MAINROW_HORIZTRAILER_CELL_TOP_SZ_MAX \
165 (SZ(VIEWTBL_MAINROW_HORIZTRAILER_CELL_TOP) - SZ("%s") + SZ(GEO_DECIMAL_MAX))
167 #define VIEWTBL_HORIZTRAILER_ROW_BOT_SZ_MAX \
168 (SZ(VIEWTBL_HORIZTRAILER_ROW_BOT) - SZ("%s") + SZ(GEO_DECIMAL_MAX))
170 #define URANDOM_SZ_MAX \
171 (SZ(URANDOM) - SZ("%u") + SZ(U64_HEXA_DIGITS_N_MAX))
173 #define NAV_X_SZ_MAX \
174 (SZ(NAV_X) - SZ("%u") + SZ(U32_DECIMAL_DIGITS_N_MAX))
176 #define NAV_Y_SZ_MAX \
177 (SZ(NAV_Y) - SZ("%u") + SZ(U32_DECIMAL_DIGITS_N_MAX))
179 #define NAVTBL_LO_SZ_MAX \
180 (SZ(NAVTBL_LO) - SZ("%s") + SZ(GEO_DECIMAL_MAX))
182 #define NAVTBL_LA_SZ_MAX \
183 (SZ(NAVTBL_LA) - SZ("%s") + SZ(GEO_DECIMAL_MAX))
185 #define NAVTBL_ZOOM_SZ_MAX \
186 (SZ(NAVTBL_ZOOM) - SZ("%u") + SZ("99"))
187 static void tmpl_to_html(struct html_ctx_t
*c
, u8
*tmpl
, u64 tmpl_sz_max
, ...)
192 va_start(ap
, tmpl_sz_max
);
193 sz
= vsnprintf(c
->p
, tmpl_sz_max
, tmpl
, ap
);
195 if (sz
> tmpl_sz_max
)
196 ++(c
->p
); /* ERROR: empty string */
200 /* lo or la, longitude or latitude */
201 static void tmpl_lx_to_html(struct html_ctx_t
*c
, u8
*tmpl
, u64 tmpl_sz_max
,
204 u8 lx_str
[SZ(GEO_DECIMAL_MAX
) + 1];
206 f64_to_str(lx
, lx_str
, sizeof(lx_str
));
207 tmpl_to_html(c
, tmpl
, tmpl_sz_max
, lx_str
);
209 #define TMPL_LX_TO_HTML(c,tmpl,lx) \
210 tmpl_lx_to_html(c, tmpl, tmpl##_SZ_MAX, lx)
211 #define TMPL_TO_HTML(c,tmpl,...) \
212 tmpl_to_html(c,tmpl,tmpl##_SZ_MAX, __VA_ARGS__)
213 #define TXT_TO_HTML(x) \
214 memcpy(c->p, x, SZ(x));\
216 /* XXX: should have the best 64bits float hex value (double) for PI approx */
217 #define PI 3.141592653589793238462643383279502884
218 static void html_geo_to_tile_center(struct html_ctx_t
*c
)
220 f64 la_rad
; /* latitude in radian */
221 f64 arsinh_tan_la_rad
;
222 /* exact location in "web mercator" coords */
226 * degree longitude: from -180 to +180, east -> positive,
228 * tile coordinate: x coordinate starts at the internation date line
229 * (longitude * 180) degrees and goes from east to west. x >= 0.
230 * zoom: its power of 2 is the number of divisions of the raw degree
233 * degree latitute: from 90 to -90, north -> positive
235 * tile coordinate: y coordinate starts an the north pole, then toward
236 * the south pole. y >= 0.
237 * zoom: it the power of 2 of the number of divisions of the "web
238 * mercator" (spherical->cylindrical) latitude projection
240 x_exact
= (c
->lo
+ 180.0) / 360.0 * (f64
)(1 << c
->zoom
);
241 c
->x
= (u64
)floor(x_exact
);
242 la_rad
= c
->la
* PI
/ 180.0;
243 /* arsinh(tan(α)) = ln((1 + sin(α)) / cos(α)) */
244 arsinh_tan_la_rad
= log((1 + sin(la_rad
)) / cos(la_rad
));
245 y_exact
= (1.0 - (arsinh_tan_la_rad
/ PI
)) / 2.0
246 * (f64
)(1 << c
->zoom
);
247 c
->y
= (u64
)floor(y_exact
);
249 static void html_geo_modify(struct html_ctx_t
*c
, struct html_query_t
*q
)
254 html_geo_to_tile_center(c
);
256 static void html_tile_center_to_geo(struct html_ctx_t
*c
)
262 x_center
= (f64
)(c
->x
) + 0.5;
263 c
->lo
= (x_center
* 360.0) / (f64
)(1 << c
->zoom
) - 180.0;
265 y_center
= (f64
)(c
->y
) + 0.5;
266 tmp
= PI
- 2.0 * PI
* y_center
/ (f64
)(1 << c
->zoom
);
267 c
->la
= 180.0 / PI
* atan(0.5 * (exp(tmp
) - exp(-tmp
)));
269 static void html_translate_north(struct html_ctx_t
*c
, struct html_query_t
*q
)
272 c
->y
= (q
->y
- 1) % (u32
)(1 << q
->zoom
);
275 html_tile_center_to_geo(c
);
277 static void html_translate_south(struct html_ctx_t
*c
, struct html_query_t
*q
)
280 c
->y
= (q
->y
+ 1) % (u32
)(1 << q
->zoom
);
283 html_tile_center_to_geo(c
);
285 static void html_translate_west(struct html_ctx_t
*c
, struct html_query_t
*q
)
287 c
->x
= (q
->x
- 1) % (u32
)(1 << q
->zoom
);
291 html_tile_center_to_geo(c
);
293 static void html_translate_east(struct html_ctx_t
*c
, struct html_query_t
*q
)
295 c
->x
= (q
->x
+ 1) % (u32
)(1 << q
->zoom
);
299 html_tile_center_to_geo(c
);
301 static void html_zoom_plus(struct html_ctx_t
*c
, struct html_query_t
*q
)
305 c
->zoom
= q
->zoom
+ 1;
306 html_geo_to_tile_center(c
);
308 static void html_zoom_minus(struct html_ctx_t
*c
, struct html_query_t
*q
)
313 c
->zoom
= q
->zoom
- 1;
316 html_geo_to_tile_center(c
);
318 static void html_zoom_modify(struct html_ctx_t
*c
, struct html_query_t
*q
)
320 html_geo_modify(c
, q
);
322 static void html_gen_ctx_init_from_query(struct html_ctx_t
*c
,
323 struct html_query_t
*q
, u8
*buf
, u64 urandom
)
325 switch (q
->nav_cmd
) {
326 case HTML_QUERY_NAV_CMD_TRANSLATION_NORTH
:
327 html_translate_north(c
, q
);
329 case HTML_QUERY_NAV_CMD_TRANSLATION_SOUTH
:
330 html_translate_south(c
, q
);
332 case HTML_QUERY_NAV_CMD_TRANSLATION_WEST
:
333 html_translate_west(c
, q
);
335 case HTML_QUERY_NAV_CMD_TRANSLATION_EAST
:
336 html_translate_east(c
, q
);
338 case HTML_QUERY_NAV_CMD_ZOOM_PLUS
:
339 html_zoom_plus(c
, q
);
341 case HTML_QUERY_NAV_CMD_ZOOM_MINUS
:
342 html_zoom_minus(c
, q
);
344 case HTML_QUERY_NAV_CMD_ZOOM_MODIFY
:
345 html_zoom_modify(c
, q
);
347 case HTML_QUERY_NAV_CMD_GEO_MODIFY
:
349 html_geo_modify(c
, q
);
352 c
->verts_n
= CONFIG_VERTS_N_MAX
;
353 c
->horizs_n
= CONFIG_HORIZS_N_MAX
;
354 c
->urandom
= urandom
;
357 static void html_viewtbl_verthdrs_gen(struct html_ctx_t
*c
)
361 TXT_TO_HTML(VIEWTBL_VERTHDRS_P
);
362 /*--------------------------------------------------------------------*/
369 if (vert
== c
->verts_n
)
371 x
= (f64
)((c
->x
- (u64
)c
->verts_n
/ 2 + (u64
)vert
)
373 lo_west
= (x
* 360.0) / (f64
)(1 << c
->zoom
) - 180.0;
374 lo_east
= ((x
+ (CONFIG_TILE_PIXS_N_MAX
- 1.0)
375 / CONFIG_TILE_PIXS_N_MAX
) * 360.0) / (f64
)(1 << c
->zoom
)
377 TMPL_LX_TO_HTML(c
, VIEWTBL_VERTHDRS_WEST
, lo_west
);
378 TMPL_LX_TO_HTML(c
, VIEWTBL_VERTHDRS_EAST
, lo_east
);
381 /*--------------------------------------------------------------------*/
382 TXT_TO_HTML(VIEWTBL_VERTHDRS_E
);
384 static void html_viewtbl_tile(struct html_ctx_t
*c
, u8 horiz
)
393 if (vert
== c
->verts_n
)
395 x
= (c
->x
- (u64
)c
->verts_n
/ 2 + (u64
)vert
) % (1 << c
->zoom
);
396 y
= (c
->y
- (u64
)c
->horizs_n
/ 2 + (u64
)horiz
) % (1 << c
->zoom
);
397 TMPL_TO_HTML(c
, VIEWTBL_TILE
, config_row_svrs
[horiz
% 3],
402 static void html_viewtbl_mainrow_horiztrailer_cell_top(struct html_ctx_t
*c
,
409 y
= (f64
)((c
->y
- (u64
)c
->horizs_n
/ 2 + (u64
)horiz
) % (1 << c
->zoom
));
410 tmp
= PI
- 2.0 * PI
* y
/ (f64
)(1 << c
->zoom
);
411 la
= 180.0 / PI
* atan(0.5 * (exp(tmp
) - exp(-tmp
)));
412 TMPL_LX_TO_HTML(c
, VIEWTBL_MAINROW_HORIZTRAILER_CELL_TOP
,la
);
414 static void html_viewtbl_mainrow_gen(struct html_ctx_t
*c
, u8 horiz
)
416 TXT_TO_HTML(VIEWTBL_MAINROW_P
);
417 html_viewtbl_tile(c
, horiz
);
418 html_viewtbl_mainrow_horiztrailer_cell_top(c
, horiz
);
419 TXT_TO_HTML(VIEWTBL_MAINROW_E
);
421 static void html_viewtbl_horiztrailer_row_bot(struct html_ctx_t
*c
, u8 horiz
)
427 y
= (f64
)((c
->y
- (u64
)c
->horizs_n
/ 2 + (u64
)horiz
) % (1 << c
->zoom
));
428 tmp
= PI
- 2.0 * PI
* (y
+ (CONFIG_TILE_PIXS_N_MAX
- 1.0)
429 / CONFIG_TILE_PIXS_N_MAX
) / (f64
)(1 << c
->zoom
);
430 la
= 180.0 / PI
* atan(0.5 * (exp(tmp
) - exp(-tmp
)));
431 TMPL_LX_TO_HTML(c
, VIEWTBL_HORIZTRAILER_ROW_BOT
, la
);
433 static void html_viewtbl_gen(struct html_ctx_t
*c
)
437 TXT_TO_HTML(VIEWTBL_P
);
438 html_viewtbl_verthdrs_gen(c
);
441 if (horiz
== c
->horizs_n
)
443 html_viewtbl_mainrow_gen(c
, horiz
);
444 html_viewtbl_horiztrailer_row_bot(c
, horiz
);
447 TXT_TO_HTML(VIEWTBL_E
);
449 static void html_navform_navtbl_gen(struct html_ctx_t
*c
)
451 TXT_TO_HTML(NAVTBL_P
);
452 TMPL_LX_TO_HTML(c
, NAVTBL_LO
, c
->lo
);
453 TMPL_LX_TO_HTML(c
, NAVTBL_LA
, c
->la
);
454 TXT_TO_HTML(NAVTBL_MIDDLE
);
455 TMPL_TO_HTML(c
, NAVTBL_ZOOM
, c
->zoom
);
456 TXT_TO_HTML(NAVTBL_E
);
458 static void html_navform_gen(struct html_ctx_t
*c
)
460 TMPL_TO_HTML(c
, URANDOM
, c
->urandom
);
461 TMPL_TO_HTML(c
, NAV_X
, c
->x
);
462 TMPL_TO_HTML(c
, NAV_Y
, c
->y
);
463 html_navform_navtbl_gen(c
);
465 static void html_majortbl_gen(struct html_ctx_t
*c
)
467 TXT_TO_HTML(MAJORTBL_P
);
469 TXT_TO_HTML(MAJORTBL_VIEWTBL_TO_NAVFORM
);
471 TXT_TO_HTML(MAJORTBL_E
);
473 static u32
html_sz_max(void)
478 SZ(VIEWTBL_VERTHDRS_P
) +
479 CONFIG_VERTS_N_MAX
* (
480 VIEWTBL_VERTHDRS_WEST_SZ_MAX
+
481 VIEWTBL_VERTHDRS_EAST_SZ_MAX
) +
482 SZ(VIEWTBL_VERTHDRS_E
) +
483 CONFIG_HORIZS_N_MAX
* (
484 SZ(VIEWTBL_MAINROW_P
) +
485 CONFIG_VERTS_N_MAX
* VIEWTBL_TILE_SZ_MAX
+
486 VIEWTBL_MAINROW_HORIZTRAILER_CELL_TOP_SZ_MAX
+
487 SZ(VIEWTBL_MAINROW_E
) +
488 VIEWTBL_HORIZTRAILER_ROW_BOT_SZ_MAX
) +
490 SZ(MAJORTBL_VIEWTBL_TO_NAVFORM
) +
502 #define NAV_IS(x) memcmp(x, s, e - s)
503 static void html_control_nav(struct html_query_t
*q
, u8
*s
, u8
*e
)
507 if (NAV_IS("geo_modify")) /* default if nav is missing */
508 q
->nav_cmd
= HTML_QUERY_NAV_CMD_GEO_MODIFY
;
509 else if (NAV_IS("translation_north"))
510 q
->nav_cmd
= HTML_QUERY_NAV_CMD_TRANSLATION_NORTH
;
511 else if (NAV_IS("translation_south"))
512 q
->nav_cmd
= HTML_QUERY_NAV_CMD_TRANSLATION_SOUTH
;
513 else if (NAV_IS("translation_west"))
514 q
->nav_cmd
= HTML_QUERY_NAV_CMD_TRANSLATION_WEST
;
515 else if (NAV_IS("translation_east"))
516 q
->nav_cmd
= HTML_QUERY_NAV_CMD_TRANSLATION_EAST
;
517 else if (NAV_IS("zoom_plus"))
518 q
->nav_cmd
= HTML_QUERY_NAV_CMD_ZOOM_PLUS
;
519 else if (NAV_IS("zoom_minus"))
520 q
->nav_cmd
= HTML_QUERY_NAV_CMD_ZOOM_MINUS
;
521 else if (NAV_IS("zoom_modify"))
522 q
->nav_cmd
= HTML_QUERY_NAV_CMD_ZOOM_MODIFY
;
525 static void html_control_x(struct html_query_t
*q
, u8
*s
, u8
*e
)
531 if (dec2u32_blk(&x
, s
, e
- 1))
534 static void html_control_y(struct html_query_t
*q
, u8
*s
, u8
*e
)
540 if (dec2u32_blk(&y
, s
, e
- 1))
543 static void html_control_zoom(struct html_query_t
*q
, u8
*s
, u8
*e
)
549 if (dec2u8_blk(&z
, s
, e
- 1))
552 static void html_control_la(struct html_query_t
*q
, u8
*s
, u8
*e
)
556 dec_to_f64(&la
, s
, e
- 1); /* only integers in ulinux */
557 if (-90.0 <= la
&& la
<= 90.0)
560 static void html_control_lo(struct html_query_t
*q
, u8
*s
, u8
*e
)
564 dec_to_f64(&lo
, s
, e
- 1); /* only integeres in ulinux */
565 if (-180.0 <= lo
&& lo
<= 180.0)
568 #define NAME_IS(x) memcmp(x, name, name_e - name)
569 static void html_control_decode(struct html_query_t
*q
, u8
*name
, u8
*name_e
,
570 u8
*value
, u8
*value_e
)
575 html_control_nav(q
, value
, value_e
);
576 else if (NAME_IS("x"))
577 html_control_x(q
, value
, value_e
);
578 else if (NAME_IS("y"))
579 html_control_y(q
, value
, value_e
);
580 else if (NAME_IS("zoom"))
581 html_control_zoom(q
, value
, value_e
);
582 else if (NAME_IS("lo"))
583 html_control_lo(q
, value
, value_e
);
584 else if (NAME_IS("la"))
585 html_control_la(q
, value
, value_e
);
588 static void html_query_decode(struct html_query_t
*q
, u8
*p
, u8
*e
)
603 if (p
== e
|| *p
== '=' || *p
== '&') {
609 if (*p
== '=') { /* value if any */
613 if (p
== e
|| *p
== '&') {
622 html_control_decode(q
, name
, name_e
, value
, value_e
);
624 static void html_query_init(struct html_query_t
*q
)
626 /* sane init values */
632 /* will ignore query x and y */
633 q
->nav_cmd
= HTML_QUERY_NAV_CMD_GEO_MODIFY
;
635 /*----------------------------------------------------------------------------*/
636 #undef GEO_DECIMAL_MAX
637 #undef U32_DECIMAL_DIGITS_N_MAX
638 #undef U64_HEXA_DIGITS_N_MAX
642 #undef VIEWTBL_VERTHDRS_P
643 #undef VIEWTBL_VERTHDRS_WEST
644 #undef VIEWTBL_VERTHDRS_WEST_SZ_MAX
645 #undef VIEWTBL_VERTHDRS_EAST
646 #undef VIEWTBL_VERTHDRS_EAST_SZ_MAX
647 #undef VIEWTBL_VERTHDRS_E
648 #undef VIEWTBL_MAINROW_P
650 #undef VIEWTBL_TILE_SZ_MAX
651 #undef VIEWTBL_MAINROW_HORIZTRAILER_CELL_TOP
652 #undef VIEWTBL_MAINROW_HORIZTRAILER_CELL_TOP_SZ_MAX
653 #undef VIEWTBL_MAINROW_E
654 #undef VIEWTBL_HORIZTRAILER_ROW_BOT
655 #undef VIEWTBL_HORIZTRAILER_ROW_BOT_SZ_MAX
657 #undef MAJORTBL_VIEWTBL_TO_NAVFORM
659 #undef URANDOM_SZ_MAX
666 #undef NAVTBL_LO_SZ_MAX
668 #undef NAVTBL_LA_SZ_MAX
674 #include "common_cpp.h"
675 /*============================================================================*/
676 #include "namespace/ulinux.h"
677 /*============================================================================*/