1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
|
#include <emscripten/emscripten.h>
#include <GL/glfw.h>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <llmr/llmr.hpp>
#include <llmr/map/tile.hpp>
bool dirty = true;
class MapView;
static MapView *view;
class MapView {
public:
MapView() :
dirty(true),
platform(new llmr::platform(this)),
painter(new llmr::painter(platform)),
map(new llmr::map(platform, painter)) {
// Initialize GLFW
if (!glfwInit()) {
fprintf(stderr, "Failed to initialize GLFW\n");
exit(1);
}
int width, height;
emscripten_get_canvas_size(&width, &height, NULL);
glfwSetMousePosCallback(mousemove);
glfwSetMouseButtonCallback(mouseclick);
glfwSetMouseWheelCallback(scroll);
// Open a window and create its OpenGL context
if (!glfwOpenWindow(width, height, 8, 8, 8, 8, 16, 8, GLFW_WINDOW)) {
fprintf(stderr, "Failed to open GLFW window\n");
glfwTerminate();
exit(1);
}
painter->setup();
painter->resize(width, height);
}
~MapView() {
delete map;
delete painter;
delete platform;
glfwTerminate();
}
static void mousemove(int x, int y) {
if (view->tracking) {
view->map->moveBy(x - view->last_x, y - view->last_y);
}
view->last_x = x;
view->last_y = y;
}
static void scroll(float pos) {
double delta = pos;
bool is_wheel = delta != 0 && fmod(delta, 4.000244140625) == 0;
double absdelta = delta < 0 ? -delta : delta;
double scale = 2.0 / (1.0 + exp(-absdelta / 100.0));
// Make the scroll wheel a bit slower.
// if (!is_wheel) {
// scale = (scale - 1.0) / 2.0 + 1.0;
// }
// Zooming out.
if (delta < 0 && scale != 0) {
scale = 1.0 / scale;
}
view->map->scaleBy(scale, view->last_x, view->last_y);
}
static void mouseclick(int button, int action) {
if (button == GLFW_MOUSE_BUTTON_1) {
view->tracking = action == GLFW_PRESS;
}
}
int run() {
emscripten_set_main_loop(render, 60, 1);
return 0;
}
static void render() {
if (view->dirty) {
view->map->render();
// glClearColor(1, 1, 0, 1);
// glClear(GL_COLOR_BUFFER_BIT);
view->dirty = false;
}
}
bool dirty;
double last_x, last_y;
bool tracking;
llmr::platform *platform;
llmr::painter *painter;
llmr::map *map;
};
void llmr::platform::restart() {
view->dirty = true;
}
void ontileload(void* custom, void* bytes, int length) {
fprintf(stderr, "data loaded successfully: length: %d\n", length);
llmr::tile *tile = (llmr::tile *)custom;
tile->setData((uint8_t *)bytes, length);
if (tile->parse()) {
view->map->tileLoaded(tile);
return;
}
}
void ontileerror(void* custom) {
fprintf(stderr, "data load error\n");
llmr::tile *tile = (llmr::tile *)custom;
view->map->tileFailed(tile);
}
void llmr::platform::request(tile *tile) {
const char *urlTemplate = "http://api.tiles.mapbox.com/v3/mapbox.mapbox-streets-v4/%d/%d/%d.vector.pbf";
char urlString[255];
snprintf(urlString, 255, urlTemplate, tile->z, tile->x, tile->y);
fprintf(stderr, "requesting %s\n", urlString);
emscripten_async_wget_data(urlString, tile, ontileload, ontileerror);
}
int main() {
view = new MapView();
int ret = view->run();
delete view;
return ret;
}
|