/[zanavi_public1]/navit/navit/vehicle.c
ZANavi

Contents of /navit/navit/vehicle.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 27 - (show annotations) (download)
Mon Apr 9 21:27:36 2012 UTC (10 years, 7 months ago) by zoff99
File MIME type: text/plain
File size: 22947 byte(s)
lots of new stuff, tranlsations, bug fixes ...
1 /**
2 * ZANavi, Zoff Android Navigation system.
3 * Copyright (C) 2011-2012 Zoff <zoff@zoff.cc>
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * version 2 as published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the
16 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17 * Boston, MA 02110-1301, USA.
18 */
19
20 /**
21 * Navit, a modular navigation system.
22 * Copyright (C) 2005-2009 Navit Team
23 *
24 * This program is free software; you can redistribute it and/or
25 * modify it under the terms of the GNU General Public License
26 * version 2 as published by the Free Software Foundation.
27 *
28 * This program is distributed in the hope that it will be useful,
29 * but WITHOUT ANY WARRANTY; without even the implied warranty of
30 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
31 * GNU General Public License for more details.
32 *
33 * You should have received a copy of the GNU General Public License
34 * along with this program; if not, write to the
35 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
36 * Boston, MA 02110-1301, USA.
37 */
38
39 #include <stdio.h>
40 #include <string.h>
41 #include <glib.h>
42 #include <time.h>
43 #include "config.h"
44 #include "debug.h"
45 #include "coord.h"
46 #include "item.h"
47 #include "log.h"
48 #include "plugin.h"
49 #include "transform.h"
50 #include "util.h"
51 #include "event.h"
52 #include "coord.h"
53 #include "transform.h"
54 #include "projection.h"
55 #include "point.h"
56 #include "graphics.h"
57 #include "callback.h"
58 #include "color.h"
59 #include "layout.h"
60 #include "vehicle.h"
61
62 struct vehicle
63 {
64 struct vehicle_methods meth;
65 struct vehicle_priv *priv;
66 struct callback_list *cbl;
67 struct log *nmea_log, *gpx_log;
68 char *gpx_desc;
69 struct attr **attrs;
70
71 // cursor
72 struct cursor *cursor;
73 int cursor_fixed;
74 struct callback *animate_callback;
75 struct event_timeout *animate_timer;
76 struct point cursor_pnt;
77 struct graphics *gra;
78 struct graphics_gc *bg;
79 struct transformation *trans;
80 int angle;
81 int speed;
82 int sequence;
83 GHashTable *log_to_cb;
84 };
85
86 static void vehicle_draw_do(struct vehicle *this_, int lazy);
87 static void vehicle_log_nmea(struct vehicle *this_, struct log *log);
88 static void vehicle_log_gpx(struct vehicle *this_, struct log *log);
89 static void vehicle_log_textfile(struct vehicle *this_, struct log *log);
90 static void vehicle_log_binfile(struct vehicle *this_, struct log *log);
91 static int vehicle_add_log(struct vehicle *this_, struct log *log);
92 void vehicle_remove_cursor(struct vehicle *this_);
93
94 /**
95 * Creates a new vehicle
96 */
97 struct vehicle *
98 vehicle_new(struct attr *parent, struct attr **attrs)
99 {
100 struct vehicle *this_;
101 struct attr *source;
102 struct vehicle_priv *(*vehicletype_new)(struct vehicle_methods * meth, struct callback_list * cbl, struct attr ** attrs);
103 char *type, *colon;
104 struct pcoord center;
105
106 //DBG dbg(0, "enter\n");
107 source = attr_search(attrs, NULL, attr_source);
108 if (!source)
109 {
110 //DBG dbg(0, "no source\n");
111 return NULL;
112 }
113
114 type = g_strdup(source->u.str);
115 colon = strchr(type, ':');
116 if (colon)
117 {
118 *colon = '\0';
119 }
120 ////DBG dbg(0, "source='%s' type='%s'\n", source->u.str, type);
121
122 vehicletype_new = plugin_get_vehicle_type(type);
123 if (!vehicletype_new)
124 {
125 //DBG dbg(0, "invalid type '%s'\n", type);
126 g_free(type);
127 return NULL;
128 }
129 g_free(type);
130 this_ = g_new0(struct vehicle, 1);
131 this_->cbl = callback_list_new();
132 this_->priv = vehicletype_new(&this_->meth, this_->cbl, attrs);
133 //DBG dbg(0, "veh new 2\n");
134 if (!this_->priv)
135 {
136 //DBG dbg(0, "vehicletype_new failed\n");
137 callback_list_destroy(this_->cbl);
138 g_free(this_);
139 return NULL;
140 }
141 //DBG dbg(0, "veh new 3\n");
142 this_->attrs = attr_list_dup(attrs);
143 //DBG dbg(0, "veh new 4\n");
144 this_->trans = transform_new();
145
146 // set bad 0/0 location ??? i dont know really
147 /*
148 struct coord_geo g;
149 struct coord co;
150 enum projection pro=projection_mg;
151 g.lat=53.13;
152 g.lng=11.70;
153 transform_from_geo(pro, &g, &co);
154 center.x=co.x;
155 center.y=co.y;
156 center.pro = pro;
157 */
158
159 center.pro = projection_screen;
160 center.x = 0;
161 center.y = 0;
162 //DBG dbg(0, "veh new 5\n");
163 transform_setup(this_->trans, &center, 16, 0);
164 //DBG dbg(0, "veh new 6\n");
165
166 this_->log_to_cb = g_hash_table_new(NULL, NULL);
167 //DBG dbg(0, "leave\n");
168 return this_;
169 }
170
171 /**
172 * Destroys a vehicle
173 *
174 * @param this_ The vehicle to destroy
175 */
176 void vehicle_destroy(struct vehicle *this_)
177 {
178 if (this_->animate_callback)
179 {
180 callback_destroy(this_->animate_callback);
181 event_remove_timeout(this_->animate_timer);
182 }
183 transform_destroy(this_->trans);
184 this_->meth.destroy(this_->priv);
185 callback_list_destroy(this_->cbl);
186 attr_list_free(this_->attrs);
187 if (this_->bg)
188 graphics_gc_destroy(this_->bg);
189 if (this_->gra)
190 graphics_free(this_->gra);
191 g_free(this_);
192 }
193
194 /**
195 * Creates an attribute iterator to be used with vehicles
196 */
197 struct attr_iter *
198 vehicle_attr_iter_new(void)
199 {
200 return (struct attr_iter *)g_new0(void *,1);
201 }
202
203 /**
204 * Destroys a vehicle attribute iterator
205 *
206 * @param iter a vehicle attr_iter
207 */
208 void vehicle_attr_iter_destroy(struct attr_iter *iter)
209 {
210 g_free(iter);
211 }
212
213 /**
214 * Generic get function
215 *
216 * @param this_ Pointer to a vehicle structure
217 * @param type The attribute type to look for
218 * @param attr Pointer to an attr structure to store the attribute
219 * @param iter A vehicle attr_iter
220 */
221 int vehicle_get_attr(struct vehicle *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
222 {
223 ////DBG dbg(0,"enter\n");
224 int ret;
225 if (this_->meth.position_attr_get)
226 {
227 ret = this_->meth.position_attr_get(this_->priv, type, attr);
228 if (ret)
229 return ret;
230 }
231 if (type == attr_log_gpx_desc)
232 {
233 attr->u.str = this_->gpx_desc;
234 return 1;
235 }
236 ////DBG dbg(0,"before return\n");
237 return attr_generic_get_attr(this_->attrs, NULL, type, attr, iter);
238 }
239
240 /**
241 * Generic set function
242 *
243 * @param this_ Pointer to a vehicle structure
244 * @param attr Pointer to an attr structure for the attribute to be set
245 * @return nonzero on success, zero on failure
246 */
247 int vehicle_set_attr(struct vehicle *this_, struct attr *attr)
248 {
249 int ret = 1;
250 if (this_->meth.set_attr)
251 ret = this_->meth.set_attr(this_->priv, attr);
252 if (ret == 1 && attr->type == attr_log_gpx_desc)
253 {
254 g_free(this_->gpx_desc);
255 this_->gpx_desc = attr->u.str;
256 }
257 if (ret == 1 && attr->type != attr_navit && attr->type != attr_pdl_gps_update)
258 this_->attrs = attr_generic_set_attr(this_->attrs, attr);
259 return ret != 0;
260 }
261
262 /**
263 * Generic add function
264 *
265 * @param this_ A vehicle
266 * @param attr A struct attr
267 */
268 int vehicle_add_attr(struct vehicle *this_, struct attr *attr)
269 {
270 int ret = 1;
271 switch (attr->type)
272 {
273 case attr_callback:
274 callback_list_add(this_->cbl, attr->u.callback);
275 break;
276 case attr_log:
277 ret = vehicle_add_log(this_, attr->u.log);
278 break;
279 // currently supporting oldstyle cursor config.
280 case attr_cursor:
281 this_->cursor_fixed = 1;
282 vehicle_set_cursor(this_, attr->u.cursor, 1);
283 break;
284 default:
285 break;
286 }
287 if (ret)
288 this_->attrs = attr_generic_add_attr(this_->attrs, attr);
289 return ret;
290 }
291
292 /**
293 * @brief Generic remove function.
294 *
295 * Used to remove a callback from the vehicle.
296 * @param this_ A vehicle
297 * @param attr
298 */
299 int vehicle_remove_attr(struct vehicle *this_, struct attr *attr)
300 {
301 struct callback *cb;
302 switch (attr->type)
303 {
304 case attr_callback:
305 callback_list_remove(this_->cbl, attr->u.callback);
306 break;
307 case attr_log:
308 cb = g_hash_table_lookup(this_->log_to_cb, attr->u.log);
309 if (!cb)
310 return 0;
311 g_hash_table_remove(this_->log_to_cb, attr->u.log);
312 callback_list_remove(this_->cbl, cb);
313 break;
314 case attr_cursor:
315 vehicle_remove_cursor(this_);
316 break;
317 default:
318 this_->attrs = attr_generic_remove_attr(this_->attrs, attr);
319 return 0;
320 }
321 return 1;
322 }
323
324 /**
325 * Sets the cursor of a vehicle.
326 *
327 * @param this_ A vehicle
328 * @param cursor A cursor
329 * @author Ralph Sennhauser (10/2009)
330 */
331 void vehicle_set_cursor(struct vehicle *this_, struct cursor *cursor, int overwrite)
332 {
333 struct point sc;
334 if (this_->cursor_fixed && !overwrite)
335 {
336 return;
337 }
338 if (this_->animate_callback)
339 {
340 event_remove_timeout(this_->animate_timer);
341 this_->animate_timer = NULL; // dangling pointer! prevent double freeing.
342 callback_destroy(this_->animate_callback);
343 this_->animate_callback = NULL; // dangling pointer! prevent double freeing.
344 }
345 if (cursor && cursor->interval)
346 {
347 this_->animate_callback = callback_new_2(callback_cast(vehicle_draw_do), this_, 0);
348 dbg(0, "event_add_timeout %d,%d,%p", cursor->interval, 1, this_->animate_callback);
349 this_->animate_timer = event_add_timeout(cursor->interval, 1, this_->animate_callback);
350 }
351
352 if (cursor && this_->gra && this_->cursor)
353 {
354 this_->cursor_pnt.x += (this_->cursor->w - cursor->w) / 2;
355 this_->cursor_pnt.y += (this_->cursor->h - cursor->h) / 2;
356 graphics_overlay_resize(this_->gra, &this_->cursor_pnt, cursor->w, cursor->h, 65535, 0);
357 }
358
359 if (cursor)
360 {
361 sc.x = cursor->w / 2;
362 sc.y = cursor->h / 2;
363 if (!this_->cursor && this_->gra)
364 graphics_overlay_disable(this_->gra, 0);
365 }
366 else
367 {
368 sc.x = sc.y = 0;
369 if (this_->cursor && this_->gra)
370 graphics_overlay_disable(this_->gra, 1);
371 }
372 transform_set_screen_center(this_->trans, &sc);
373
374 this_->cursor = cursor;
375 }
376
377 void vehicle_remove_cursor(struct vehicle *this_)
378 {
379 struct point sc;
380
381 if (this_->animate_callback)
382 {
383 event_remove_timeout(this_->animate_timer);
384 this_->animate_timer = NULL; // dangling pointer! prevent double freeing.
385 callback_destroy(this_->animate_callback);
386 this_->animate_callback = NULL; // dangling pointer! prevent double freeing.
387 }
388
389 if (this_->cursor && this_->gra)
390 {
391 }
392
393 if (this_->cursor && this_->gra)
394 {
395 graphics_overlay_disable(this_->gra, 1);
396 }
397
398 this_->cursor = NULL;
399 }
400
401 /**
402 * Draws a vehicle on top of a graphics.
403 *
404 * @param this_ The vehicle
405 * @param gra The graphics
406 * @param pnt Screen coordinates of the vehicle.
407 * @param lazy use lazy draw mode.
408 * @param angle The angle relative to the map.
409 * @param speed The speed of the vehicle.
410 */
411 void vehicle_draw(struct vehicle *this_, struct graphics *gra, struct point *pnt, int lazy, int angle, int speed)
412 {
413 if (angle < 0)
414 angle += 360;
415 //// dbg(1, "enter this=%p gra=%p pnt=%p lazy=%d dir=%d speed=%d\n", this_, gra,
416 // pnt, lazy, angle, speed);
417 //// dbg(1, "point %d,%d\n", pnt->x, pnt->y);
418 this_->cursor_pnt = *pnt;
419 this_->angle = angle;
420 this_->speed = speed;
421 if (!this_->cursor)
422 return;
423 this_->cursor_pnt.x -= this_->cursor->w / 2;
424 this_->cursor_pnt.y -= this_->cursor->h / 2;
425 if (!this_->gra)
426 {
427 struct color c;
428 this_->gra = graphics_overlay_new(gra, &this_->cursor_pnt, this_->cursor->w, this_->cursor->h, 65535, 0);
429 if (this_->gra)
430 {
431 this_->bg = graphics_gc_new(this_->gra);
432 c.r = 0;
433 c.g = 0;
434 c.b = 0;
435 c.a = 0;
436 graphics_gc_set_foreground(this_->bg, &c);
437 graphics_background_gc(this_->gra, this_->bg);
438 }
439 }
440 vehicle_draw_do(this_, lazy);
441 }
442
443 int vehicle_get_cursor_data(struct vehicle *this, struct point *pnt, int *angle, int *speed)
444 {
445 *pnt = this->cursor_pnt;
446 *angle = this->angle;
447 *speed = this->speed;
448 return 1;
449 }
450
451 static void vehicle_draw_do(struct vehicle *this_, int lazy)
452 {
453 struct point p;
454 struct cursor *cursor = this_->cursor;
455 int speed = this_->speed;
456 int angle = this_->angle;
457 int sequence = this_->sequence;
458 struct attr **attr;
459 char *label = NULL;
460 int match = 0;
461
462 if (!this_->cursor || !this_->cursor->attrs || !this_->gra)
463 return;
464
465 attr = this_->attrs;
466 while (attr && *attr)
467 {
468 if ((*attr)->type == attr_name)
469 label = (*attr)->u.str;
470 attr++;
471 }
472 transform_set_yaw(this_->trans, -this_->angle);
473 graphics_draw_mode(this_->gra, draw_mode_begin);
474 p.x = 0;
475 p.y = 0;
476 graphics_draw_rectangle(this_->gra, this_->bg, &p, cursor->w, cursor->h);
477 attr = cursor->attrs;
478 while (*attr)
479 {
480 if ((*attr)->type == attr_itemgra)
481 {
482 struct itemgra *itm = (*attr)->u.itemgra;
483 //// dbg(1, "speed %d-%d %d\n", itm->speed_range.min,
484 // itm->speed_range.max, speed);
485 if (speed >= itm->speed_range.min && speed <= itm->speed_range.max && angle >= itm->angle_range.min && angle <= itm->angle_range.max && sequence >= itm->sequence_range.min && sequence <= itm->sequence_range.max)
486 {
487 graphics_draw_itemgra(this_->gra, itm, this_->trans, label);
488 }
489 if (sequence < itm->sequence_range.max)
490 match = 1;
491 }
492 ++attr;
493 }
494 graphics_draw_drag(this_->gra, &this_->cursor_pnt);
495 graphics_draw_mode(this_->gra, lazy ? draw_mode_end_lazy : draw_mode_end);
496 if (this_->animate_callback)
497 {
498 ++this_->sequence;
499 if (cursor->sequence_range && cursor->sequence_range->max < this_->sequence)
500 this_->sequence = cursor->sequence_range->min;
501 if (!match && !cursor->sequence_range)
502 this_->sequence = 0;
503 }
504 }
505
506 /**
507 * Writes to an NMEA log.
508 *
509 * @param this_ Pointer to the vehicle structure of the data source
510 * @param log Pointer to a log structure for the log file
511 */
512 static void vehicle_log_nmea(struct vehicle *this_, struct log *log)
513 {
514 struct attr pos_attr;
515 if (!this_->meth.position_attr_get)
516 return;
517 if (!this_->meth.position_attr_get(this_->priv, attr_position_nmea, &pos_attr))
518 return;
519 log_write(log, pos_attr.u.str, strlen(pos_attr.u.str), 0);
520 }
521
522 void vehicle_log_gpx_add_tag(char *tag, char **logstr)
523 {
524 char *ext_start = "\t<extensions>\n";
525 char *ext_end = "\t</extensions>\n";
526 char *trkpt_end = "</trkpt>";
527 char *start = NULL, *end = NULL;
528 if (!*logstr)
529 {
530 start = g_strdup(ext_start);
531 end = g_strdup(ext_end);
532 }
533 else
534 {
535 char *str = strstr(*logstr, ext_start);
536 int len;
537 if (str)
538 {
539 len = str - *logstr + strlen(ext_start);
540 start = g_strdup(*logstr);
541 start[len] = '\0';
542 end = g_strdup(str + strlen(ext_start));
543 }
544 else
545 {
546 str = strstr(*logstr, trkpt_end);
547 len = str - *logstr;
548 end = g_strdup_printf("%s%s", ext_end, str);
549 str = g_strdup(*logstr);
550 str[len] = '\0';
551 start = g_strdup_printf("%s%s", str, ext_start);
552 g_free(str);
553 }
554 }
555 *logstr = g_strdup_printf("%s%s%s", start, tag, end);
556 g_free(start);
557 g_free(end);
558 }
559
560 /**
561 * Writes to a GPX log.
562 *
563 * @param this_ Pointer to the vehicle structure of the data source
564 * @param log Pointer to a log structure for the log file
565 */
566 static void vehicle_log_gpx(struct vehicle *this_, struct log *log)
567 {
568 struct attr attr, *attrp, fix_attr;
569 enum attr_type *attr_types;
570 char *logstr;
571 char *extensions = "\t<extensions>\n";
572
573 if (!this_->meth.position_attr_get)
574 return;
575 if (log_get_attr(log, attr_attr_types, &attr, NULL))
576 attr_types = attr.u.attr_types;
577 else
578 attr_types = NULL;
579 if (this_->meth.position_attr_get(this_->priv, attr_position_fix_type, &fix_attr))
580 {
581 if (fix_attr.u.num == 0)
582 return;
583 }
584 if (!this_->meth.position_attr_get(this_->priv, attr_position_coord_geo, &attr))
585 return;
586 logstr = g_strdup_printf("<trkpt lat=\"%f\" lon=\"%f\">\n", attr.u.coord_geo->lat, attr.u.coord_geo->lng);
587 if (attr_types && attr_types_contains_default(attr_types, attr_position_time_iso8601, 0))
588 {
589 if (this_->meth.position_attr_get(this_->priv, attr_position_time_iso8601, &attr))
590 {
591 logstr = g_strconcat_printf(logstr, "\t<time>%s</time>\n", attr.u.str);
592 }
593 else
594 {
595 char *timep = current_to_iso8601();
596 logstr = g_strconcat_printf(logstr, "\t<time>%s</time>\n", timep);
597 g_free(timep);
598 }
599 }
600 if (this_->gpx_desc)
601 {
602 logstr = g_strconcat_printf(logstr, "\t<desc>%s</desc>\n", this_->gpx_desc);
603 g_free(this_->gpx_desc);
604 this_->gpx_desc = NULL;
605 }
606 if (attr_types_contains_default(attr_types, attr_position_height, 0) && this_->meth.position_attr_get(this_->priv, attr_position_height, &attr))
607 logstr = g_strconcat_printf(logstr, "\t<ele>%.6f</ele>\n", *attr.u.numd);
608 // <magvar> magnetic variation in degrees; we might use position_magnetic_direction and position_direction to figure it out
609 // <geoidheight> Height (in meters) of geoid (mean sea level) above WGS84 earth ellipsoid. As defined in NMEA GGA message (field 11, which vehicle_wince.c ignores)
610 // <name> GPS name (arbitrary)
611 // <cmt> comment
612 // <src> Source of data
613 // <link> Link to additional information (URL)
614 // <sym> Text of GPS symbol name
615 // <type> Type (classification)
616 // <fix> Type of GPS fix {'none'|'2d'|'3d'|'dgps'|'pps'}, leave out if unknown. Similar to position_fix_type but more detailed.
617 if (attr_types_contains_default(attr_types, attr_position_sats_used, 0) && this_->meth.position_attr_get(this_->priv, attr_position_sats_used, &attr))
618 logstr = g_strconcat_printf(logstr, "\t<sat>%d</sat>\n", attr.u.num);
619 if (attr_types_contains_default(attr_types, attr_position_hdop, 0) && this_->meth.position_attr_get(this_->priv, attr_position_hdop, &attr))
620 logstr = g_strconcat_printf(logstr, "\t<hdop>%.6f</hdop>\n", *attr.u.numd);
621 // <vdop>, <pdop> Vertical and position dilution of precision, no corresponding attribute
622 if (attr_types_contains_default(attr_types, attr_position_direction, 0) && this_->meth.position_attr_get(this_->priv, attr_position_direction, &attr))
623 logstr = g_strconcat_printf(logstr, "\t<course>%.1f</course>\n", *attr.u.numd);
624 if (attr_types_contains_default(attr_types, attr_position_speed, 0) && this_->meth.position_attr_get(this_->priv, attr_position_speed, &attr))
625 logstr = g_strconcat_printf(logstr, "\t<speed>%.2f</speed>\n", (*attr.u.numd / 3.6));
626 if (attr_types_contains_default(attr_types, attr_profilename, 0) && (attrp = attr_search(this_->attrs, NULL, attr_profilename)))
627 {
628 logstr = g_strconcat_printf(logstr, "%s\t\t<navit:profilename>%s</navit:profilename>\n", extensions, attrp->u.str);
629 extensions = "";
630 }
631 if (attr_types_contains_default(attr_types, attr_position_radius, 0) && this_->meth.position_attr_get(this_->priv, attr_position_radius, &attr))
632 {
633 logstr = g_strconcat_printf(logstr, "%s\t\t<navit:radius>%.2f</navit:radius>\n", extensions, *attr.u.numd);
634 extensions = "";
635 }
636 if (!strcmp(extensions, ""))
637 {
638 logstr = g_strconcat_printf(logstr, "\t</extensions>\n");
639 }
640 logstr = g_strconcat_printf(logstr, "</trkpt>\n");
641 callback_list_call_attr_1(this_->cbl, attr_log_gpx, &logstr);
642 log_write(log, logstr, strlen(logstr), 0);
643 g_free(logstr);
644 }
645
646 /**
647 * Writes to a text log.
648 *
649 * @param this_ Pointer to the vehicle structure of the data source
650 * @param log Pointer to a log structure for the log file
651 */
652 static void vehicle_log_textfile(struct vehicle *this_, struct log *log)
653 {
654 struct attr pos_attr, fix_attr;
655 char *logstr;
656 if (!this_->meth.position_attr_get)
657 return;
658 if (this_->meth.position_attr_get(this_->priv, attr_position_fix_type, &fix_attr))
659 {
660 if (fix_attr.u.num == 0)
661 return;
662 }
663 if (!this_->meth.position_attr_get(this_->priv, attr_position_coord_geo, &pos_attr))
664 return;
665 logstr = g_strdup_printf("%f %f type=trackpoint\n", pos_attr.u.coord_geo->lng, pos_attr.u.coord_geo->lat);
666 callback_list_call_attr_1(this_->cbl, attr_log_textfile, &logstr);
667 log_write(log, logstr, strlen(logstr), 0);
668 }
669
670 /**
671 * Writes to a binary log.
672 *
673 * @param this_ Pointer to the vehicle structure of the data source
674 * @param log Pointer to a log structure for the log file
675 */
676 static void vehicle_log_binfile(struct vehicle *this_, struct log *log)
677 {
678 struct attr pos_attr, fix_attr;
679 int *buffer;
680 int *buffer_new;
681 int len, limit = 1024, done = 0, radius = 25;
682 struct coord c;
683 enum log_flags flags;
684
685 if (!this_->meth.position_attr_get)
686 return;
687 if (this_->meth.position_attr_get(this_->priv, attr_position_fix_type, &fix_attr))
688 {
689 if (fix_attr.u.num == 0)
690 return;
691 }
692 if (!this_->meth.position_attr_get(this_->priv, attr_position_coord_geo, &pos_attr))
693 return;
694 transform_from_geo(projection_mg, pos_attr.u.coord_geo, &c);
695 if (!c.x || !c.y)
696 return;
697 while (!done)
698 {
699 buffer = log_get_buffer(log, &len);
700 if (!buffer || !len)
701 {
702 buffer_new = g_malloc(5 * sizeof(int));
703 buffer_new[0] = 2;
704 buffer_new[1] = type_track;
705 buffer_new[2] = 0;
706 }
707 else
708 {
709 buffer_new = g_malloc((buffer[0] + 3) * sizeof(int));
710 memcpy(buffer_new, buffer, (buffer[0] + 1) * sizeof(int));
711 }
712 //// dbg(1, "c=0x%x,0x%x\n", c.x, c.y);
713 buffer_new[buffer_new[0] + 1] = c.x;
714 buffer_new[buffer_new[0] + 2] = c.y;
715 buffer_new[0] += 2;
716 buffer_new[2] += 2;
717 if (buffer_new[2] > limit)
718 {
719 int count = buffer_new[2] / 2;
720 struct coord *out = g_alloca(sizeof(struct coord) * (count));
721 struct coord *in = (struct coord *) (buffer_new + 3);
722 int count_out = transform_douglas_peucker(in, count, radius, out);
723 memcpy(in, out, count_out * 2 * sizeof(int));
724 buffer_new[0] += (count_out - count) * 2;
725 buffer_new[2] += (count_out - count) * 2;
726 flags = log_flag_replace_buffer | log_flag_force_flush | log_flag_truncate;
727 }
728 else
729 {
730 flags = log_flag_replace_buffer | log_flag_keep_pointer | log_flag_keep_buffer | log_flag_force_flush;
731 done = 1;
732 }
733 log_write(log, (char *) buffer_new, (buffer_new[0] + 1) * sizeof(int), flags);
734 }
735 }
736
737 /**
738 * Register a new log to receive data.
739 *
740 * @param this_ Pointer to the vehicle structure of the data source
741 * @param log Pointer to a log structure for the log file
742 */
743 static int vehicle_add_log(struct vehicle *this_, struct log *log)
744 {
745 struct callback *cb;
746 struct attr type_attr;
747 if (!log_get_attr(log, attr_type, &type_attr, NULL))
748 return 1;
749
750 if (!strcmp(type_attr.u.str, "nmea"))
751 {
752 cb = callback_new_attr_2(callback_cast(vehicle_log_nmea), attr_position_coord_geo, this_, log);
753 }
754 else if (!strcmp(type_attr.u.str, "gpx"))
755 {
756 char *header = "<?xml version='1.0' encoding='UTF-8'?>\n"
757 "<gpx version='1.1' creator='Navit http://navit.sourceforge.net'\n"
758 " xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'\n"
759 " xmlns:navit='http://www.navit-project.org/schema/navit'\n"
760 " xmlns='http://www.topografix.com/GPX/1/1'\n"
761 " xsi:schemaLocation='http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd'>\n"
762 "<trk>\n"
763 "<trkseg>\n";
764 char *trailer = "</trkseg>\n</trk>\n</gpx>\n";
765 log_set_header(log, header, strlen(header));
766 log_set_trailer(log, trailer, strlen(trailer));
767 cb = callback_new_attr_2(callback_cast(vehicle_log_gpx), attr_position_coord_geo, this_, log);
768 }
769 else if (!strcmp(type_attr.u.str, "textfile"))
770 {
771 char *header = "type=track\n";
772 log_set_header(log, header, strlen(header));
773 cb = callback_new_attr_2(callback_cast(vehicle_log_textfile), attr_position_coord_geo, this_, log);
774 }
775 else if (!strcmp(type_attr.u.str, "binfile"))
776 {
777 cb = callback_new_attr_2(callback_cast(vehicle_log_binfile), attr_position_coord_geo, this_, log);
778 }
779 else
780 return 1;
781 g_hash_table_insert(this_->log_to_cb, log, cb);
782 callback_list_add(this_->cbl, cb);
783 return 0;
784 }
785

   
Visit the ZANavi Wiki