1
1
#include " paparazzi.h"
2
2
3
- #include < prime_server/logging.hpp>
4
-
5
- using namespace Tangram ;
6
-
7
3
#define AA_SCALE 1.0
8
- #define MAX_WAITING_TIME 100.0
9
4
#define IMAGE_DEPTH 4
10
5
11
6
#if PLATFORM_LINUX
12
7
#include " platform_linux.h"
13
- std::shared_ptr<LinuxPlatform> platform;
14
8
#elif PLATFORM_OSX
15
9
#include " platform_osx.h"
16
- std::shared_ptr<OSXPlatform> platform;
17
10
#endif
11
+
18
12
#include " log.h"
19
13
#include " gl/texture.h"
20
14
@@ -23,19 +17,15 @@ std::shared_ptr<OSXPlatform> platform;
23
17
#include < functional>
24
18
#include < csignal>
25
19
#include < fstream>
26
- #include < regex>
27
20
#include < sstream>
28
21
#include < sys/time.h>
29
22
#include < unistd.h>
30
23
#include " glm/trigonometric.hpp"
31
24
32
25
#include " stb_image_write.h"
33
26
34
- const headers_t ::value_type CORS{" Access-Control-Allow-Origin" , " *" };
35
- const headers_t ::value_type PNG_MIME{" Content-type" , " image/png" };
36
- const headers_t ::value_type TXT_MIME{" Content-type" , " text/plain;charset=utf-8" };
37
27
38
- const std::regex TILE_REGEX ( " \\ /( \\ d*) \\ /( \\ d*) \\ /( \\ d*) \\ .png " ) ;
28
+ using namespace Tangram ;
39
29
40
30
unsigned long long timeStart;
41
31
@@ -68,9 +58,9 @@ Paparazzi::Paparazzi()
68
58
#if PLATFORM_LINUX
69
59
UrlClient::Options urlClientOptions;
70
60
urlClientOptions.numberOfThreads = 10 ;
71
- platform = std::make_shared<LinuxPlatform>(urlClientOptions);
61
+ auto platform = std::make_shared<LinuxPlatform>(urlClientOptions);
72
62
#elif PLATFORM_OSX
73
- platform = std::make_shared<OSXPlatform>();
63
+ auto platform = std::make_shared<OSXPlatform>();
74
64
#endif
75
65
76
66
timeStart = getTime ();
@@ -162,12 +152,11 @@ void Paparazzi::setSceneContent(const std::string &_yaml_content) {
162
152
m_map->loadScene (name.c_str (), false , {SceneUpdate (" global.sdk_mapzen_api_key" , " mapzen-y6KCsnw" )});
163
153
}
164
154
165
- bool Paparazzi::update () {
155
+ bool Paparazzi::update (int32_t _maxWaitTime ) {
166
156
double startTime = getTime ();
167
157
float delta = 0.0 ;
168
158
169
- while (delta < MAX_WAITING_TIME) {
170
- logMsg (" Update: waiting %f\n " , delta);
159
+ while (_maxWaitTime < 0 || delta < _maxWaitTime) {
171
160
172
161
bool bFinish = m_map->update (10 .);
173
162
delta = float (getTime () - startTime);
@@ -182,225 +171,20 @@ bool Paparazzi::update() {
182
171
return false ;
183
172
}
184
173
185
- struct coord_s {
186
- /* * @brief coordinate x or column value */
187
- uint32_t x;
188
- /* * @brief coordinate y or row value */
189
- uint32_t y;
190
- /* * @brief coordinate z or zoom value */
191
- uint32_t z;
192
- };
193
-
194
- static double radians_to_degrees (double radians) {
195
- return radians * 180 / M_PI;
196
- }
197
-
198
- static double degrees_to_radians (double degrees) {
199
- return degrees * M_PI / 180 ;
200
- }
201
-
202
- // http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
203
- // TODO make output into point
204
- void coord_to_lnglat (coord_s *coord, double *out_lng_deg, double *out_lat_deg) {
205
- double n = pow (2 , coord->z );
206
- double lng_deg = coord->x / n * 360.0 - 180.0 ;
207
- double lat_rad = atan (sinh (M_PI * (1 - 2 * coord->y / n)));
208
- double lat_deg = radians_to_degrees (lat_rad);
209
- *out_lng_deg = lng_deg;
210
- *out_lat_deg = lat_deg;
211
- }
212
-
213
- // http://wiki.openstreetmap.org/wiki/Slippy_map_tilenames
214
- // make input point
215
- void lnglat_to_coord (double lng_deg, double lat_deg, int zoom, coord_s *out) {
216
- double lat_rad = degrees_to_radians (lat_deg);
217
- double n = pow (2.0 , zoom);
218
- out->x = (lng_deg + 180.0 ) / 360.0 * n;
219
- out->y = (1.0 - log (tan (lat_rad) + (1 / cos (lat_rad))) / M_PI) / 2.0 * n;
220
- out->z = zoom;
221
- }
222
-
223
- worker_t ::result_t Paparazzi::work (const std::list<zmq::message_t >& job, void * request_info){
224
- // false means this is going back to the client, there is no next stage of the pipeline
225
- worker_t ::result_t result{false , {}, " " };
226
-
227
- // This type differs per protocol hence the void* fun
228
- auto & info = *static_cast <http_request_info_t *>(request_info);
229
-
230
- // Try to generate a response
231
- http_response_t response;
232
- try {
233
- // double start_call = getTime();
234
-
235
- logging::INFO (std::string (" Handle request: " ) + static_cast <const char *>(job.front ().data ()));
236
- // TODO:
237
- // - actually use/validate the request parameters
238
- auto request = http_request_t::from_string (static_cast <const char *>(job.front ().data ()),
239
- job.front ().size ());
240
-
241
- if (request.path == " /check" ) {
242
- // ELB check
243
- response = http_response_t (200 , " OK" , " OK" , headers_t {CORS, TXT_MIME}, " HTTP/1.1" );
244
- response.from_info (info);
245
- result.messages .emplace_back (response.to_string ());
246
- return result;
247
- }
248
-
249
- // SCENE
250
- // ---------------------
251
- auto scene_itr = request.query .find (" scene" );
252
- if (scene_itr == request.query .cend () || scene_itr->second .size () == 0 ) {
253
- // If there is NO SCENE QUERY value
254
- if (request.body .empty ())
255
- // if there is not POST body content return error...
256
- throw std::runtime_error (" Missing scene parameter" );
257
-
258
- // ... other whise load content
259
- setSceneContent (request.body );
260
-
261
- // The size of the custom scene is unique enough
262
- result.heart_beat = std::to_string (request.body .size ());
263
- } else {
264
- // If there IS a SCENE QUERRY value load it
265
- setScene (scene_itr->second .front ());
266
-
267
- result.heart_beat = scene_itr->second .front ();
268
- }
269
-
270
- bool size_and_pos = true ;
271
- float pixel_density = 1 .0f ;
272
-
273
- // SIZE
274
- auto width_itr = request.query .find (" width" );
275
- if (width_itr == request.query .cend () || width_itr->second .size () == 0 )
276
- size_and_pos = false ;
277
- auto height_itr = request.query .find (" height" );
278
- if (height_itr == request.query .cend () || height_itr->second .size () == 0 )
279
- size_and_pos = false ;
280
- auto density_itr = request.query .find (" density" );
281
- if (density_itr != request.query .cend () && density_itr->second .size () > 0 )
282
- pixel_density = fmax (1 .,std::stof (density_itr->second .front ()));
283
-
284
- // POSITION
285
- auto lat_itr = request.query .find (" lat" );
286
- if (lat_itr == request.query .cend () || lat_itr->second .size () == 0 )
287
- size_and_pos = false ;
288
- auto lon_itr = request.query .find (" lon" );
289
- if (lon_itr == request.query .cend () || lon_itr->second .size () == 0 )
290
- size_and_pos = false ;
291
- auto zoom_itr = request.query .find (" zoom" );
292
- if (zoom_itr == request.query .cend () || zoom_itr->second .size () == 0 )
293
- size_and_pos = false ;
294
-
295
- std::smatch match;
296
-
297
- if (size_and_pos) {
298
- // Set Map and OpenGL context size
299
- setSize (std::stoi (width_itr->second .front ()),
300
- std::stoi (height_itr->second .front ()),
301
- pixel_density);
302
- setPosition (std::stod (lon_itr->second .front ()),
303
- std::stod (lat_itr->second .front ()));
304
- setZoom (std::stof (zoom_itr->second .front ()));
305
-
306
- } else if (std::regex_search (request.path , match, TILE_REGEX) && match.size () == 4 ) {
307
- setSize (256 , 256 , pixel_density);
308
-
309
- int tile_coord[3 ] = {0 ,0 ,0 };
310
- for (int i = 0 ; i < 3 ; i++) {
311
- std::istringstream cur (match.str (i+1 ));
312
- cur >> tile_coord[i];
313
- }
314
- coord_s tile;
315
- tile.z = tile_coord[0 ];
316
- setZoom (tile.z );
317
-
318
- tile.x = tile_coord[1 ];
319
- tile.y = tile_coord[2 ];
320
-
321
- double n = pow (2 , tile.z );
322
- double lng_deg = (tile.x + 0.5 ) / n * 360.0 - 180.0 ;
323
- double lat_rad = atan (sinh (M_PI * (1 - 2 * (tile.y + 0.5 ) / n)));
324
- double lat_deg = radians_to_degrees (lat_rad);
325
-
326
- setPosition (lng_deg, lat_deg);
327
- } else {
328
- throw std::runtime_error (" Missing parameters to construct image" );
329
- }
330
-
331
- // OPTIONAL tilt and rotation
332
- // ---------------------
333
- auto tilt_itr = request.query .find (" tilt" );
334
- if (tilt_itr != request.query .cend () && tilt_itr->second .size () != 0 ) {
335
- // If TILT QUERRY is provided assigned ...
336
- setTilt (std::stof (tilt_itr->second .front ()));
337
- }
338
- else {
339
- // othewise use default (0.)
340
- setTilt (0 .0f );
341
- }
174
+ void Paparazzi::render (std::string& _image) {
175
+ m_glContext->makeCurrent ();
342
176
343
- auto rotation_itr = request.query .find (" rotation" );
344
- if (rotation_itr != request.query .cend () && rotation_itr->second .size () != 0 ) {
345
- // If ROTATION QUERRY is provided assigned ...
346
- setRotation (std::stof (rotation_itr->second .front ()));
347
- }
348
- else {
349
- // othewise use default (0.)
350
- setRotation (0 .0f );
351
- }
352
-
353
- // Time to render
354
- // ---------------------
355
-
356
- if (!update ()) {
357
- throw std::runtime_error (" Image creation timeout" );
358
- }
359
-
360
- m_glContext->makeCurrent ();
361
-
362
- // Render Tangram Scene
363
- // m_glContext->bind();
364
- m_map->render ();
365
-
366
- GL::finish ();
367
-
368
- // m_glContext->unbind();
369
-
370
- // Once the main FBO is draw take a picture
371
- // m_glContext->getPixelsAsString(image);
372
- // double total_time = getTime()-start_call;
373
- // LOG("TOTAL CALL: %f", total_time);
374
- // LOG("TOTAL speed: %f millisec per pixel", (total_time/((m_width * m_height)/1000.0)));
375
-
376
- std::string image;
377
-
378
- // m_glContext->writeImage("test.ppm");
379
-
380
- // Texture::flipImageData(m_glContext->buffer(), m_glContext->width(), m_glContext->height(), IMAGE_DEPTH);
381
-
382
- stbi_write_png_to_func ([](void *context, void *data, int size) {
383
- static_cast <std::string*>(context)->append (static_cast <const char *>(data), size);
384
- },
385
- &image,
386
- m_glContext->width (),
387
- m_glContext->height (),
388
- IMAGE_DEPTH,
389
- m_glContext->buffer (),
390
- m_glContext->width () * IMAGE_DEPTH);
391
-
392
- response = http_response_t (200 , " OK" , image, headers_t {CORS, PNG_MIME}, " HTTP/1.1" );
393
- }
394
- catch (const std::exception & e) {
395
- response = http_response_t (400 , " Bad Request" , e.what (), headers_t {CORS}, " HTTP/1.1" );
396
- }
397
-
398
- response.from_info (info);
399
- result.messages .emplace_back (response.to_string ());
400
-
401
- return result;
402
- }
177
+ m_map->render ();
403
178
404
- void Paparazzi::cleanup () {
179
+ GL::finish ();
405
180
181
+ stbi_write_png_to_func ([](void *context, void *data, int size) {
182
+ static_cast <std::string*>(context)->append (static_cast <const char *>(data), size);
183
+ },
184
+ &_image,
185
+ m_glContext->width (),
186
+ m_glContext->height (),
187
+ IMAGE_DEPTH,
188
+ m_glContext->buffer (),
189
+ m_glContext->width () * IMAGE_DEPTH);
406
190
}
0 commit comments