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

Contents of /navit/navit/vehicle.c

Parent Directory Parent Directory | Revision Log Revision Log


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

   
Visit the ZANavi Wiki