Fix:Core:Fixed routing crashes
[profile/ivi/navit.git] / navit / navit / route.c
1 /**
2  * Navit, a modular navigation system.
3  * Copyright (C) 2005-2008 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 /** @file
21  * @brief Contains code related to finding a route from a position to a destination
22  *
23  * Routing uses segments, points and items. Items are items from the map: Streets, highways, etc.
24  * Segments represent such items, or parts of it. Generally, a segment is a driveable path. An item
25  * can be represented by more than one segment - in that case it is "segmented". Each segment has an
26  * "offset" associated, that indicates at which position in a segmented item this segment is - a 
27  * segment representing a not-segmented item always has the offset 1.
28  * A point is located at the end of segments, often connecting several segments.
29  * 
30  * The code in this file will make navit find a route between a position and a destination.
31  * It accomplishes this by first building a "route graph". This graph contains segments and
32  * points.
33  *
34  * After building this graph in route_graph_build(), the function route_graph_flood() assigns every 
35  * point and segment a "value" which represents the "costs" of traveling from this point to the
36  * destination. This is done by Dijkstra's algorithm.
37  *
38  * When the graph is built a "route path" is created, which is a path in this graph from a given
39  * position to the destination determined at time of building the graph.
40  */
41
42 #include <stdio.h>
43 #include <stdlib.h>
44 #include <string.h>
45 #if 0
46 #include <math.h>
47 #include <assert.h>
48 #include <unistd.h>
49 #include <sys/time.h>
50 #endif
51 #include <glib.h>
52 #include "config.h"
53 #include "debug.h"
54 #include "profile.h"
55 #include "coord.h"
56 #include "projection.h"
57 #include "item.h"
58 #include "map.h"
59 #include "mapset.h"
60 #include "route.h"
61 #include "track.h"
62 #include "point.h"
63 #include "graphics.h"
64 #include "transform.h"
65 #include "plugin.h"
66 #include "fib.h"
67 #include "event.h"
68 #include "callback.h"
69
70
71 struct map_priv {
72         struct route *route;
73 };
74
75 int debug_route=0;
76
77 /**
78  * @brief A point in the route graph
79  *
80  * This represents a point in the route graph. A point usually connects two or more segments,
81  * but there are also points which don't do that (e.g. at the end of a dead-end).
82  */
83 struct route_graph_point {
84         struct route_graph_point *next;          /**< Linked-list pointer to a list of all route_graph_points */
85         struct route_graph_point *hash_next; /**< Pointer to a chained hashlist of all route_graph_points with this hash */
86         struct route_graph_segment *start;       /**< Pointer to a list of segments of which this point is the start. The links 
87                                                                                   *  of this linked-list are in route_graph_segment->start_next.*/
88         struct route_graph_segment *end;         /**< Pointer to a list of segments of which this pointer is the end. The links
89                                                                                   *  of this linked-list are in route_graph_segment->end_next. */
90         struct route_graph_segment *seg;         /**< Pointer to the segment one should use to reach the destination at
91                                                                                   *  least costs */
92         struct fibheap_el *el;                           /**< When this point is put on a Fibonacci heap, this is a pointer
93                                                                                   *  to this point's heap-element */
94         int value;                                                       /**< The cost at which one can reach the destination from this point on */
95         struct coord c;                                          /**< Coordinates of this point */
96 };
97
98 /**
99  * @brief A segment in the route graph
100  *
101  * This is a segment in the route graph. A segment represents a driveable way.
102  */
103 struct route_graph_segment {
104         struct route_graph_segment *next;                       /**< Linked-list pointer to a list of all route_graph_segments */
105         struct route_graph_segment *start_next;         /**< Pointer to the next element in the list of segments that start at the 
106                                                                                                  *  same point. Start of this list is in route_graph_point->start. */
107         struct route_graph_segment *end_next;           /**< Pointer to the next element in the list of segments that end at the
108                                                                                                  *  same point. Start of this list is in route_graph_point->end. */
109         struct route_graph_point *start;                        /**< Pointer to the point this segment starts at. */
110         struct route_graph_point *end;                          /**< Pointer to the point this segment ends at. */
111         struct item item;                                                       /**< The item (e.g. street) that this segment represents. */
112         int flags;
113         int len;                                                                        /**< Length of this segment */
114         int offset;                                                                     /**< If the item represented by this segment is "segmented" (i.e. 
115                                                                                                  *  is represented by several segments instead of just one), this 
116                                                                                                  *  indicates the position of this segment in the item - for items
117                                                                                                  *  that are not segmented this should always be 1 */
118 };
119
120 /**
121  * @brief A segment in the route path
122  *
123  * This is a segment in the route path.
124  */
125 struct route_path_segment {
126         struct route_path_segment *next;        /**< Pointer to the next segment in the path */
127         struct item item;                                       /**< The item (e.g. street) this segment represents */
128         int length;                                                     /**< Length of the segment */
129         int offset;                                                     /**< Same as in route_graph_segment->offset */
130         int direction;                                          /**< Order in which the coordinates are ordered. >0 means "First
131                                                                                  *  coordinate of the segment is the first coordinate of the item", <=0 
132                                                                                  *  means reverse. */
133         unsigned ncoords;                                       /**< How many coordinates does this segment have? */
134         struct coord c[0];                                      /**< Pointer to the ncoords coordinates of this segment */
135         /* WARNING: There will be coordinates following here, so do not create new fields after c! */
136 };
137
138 /**
139  * @brief Usually represents a destination or position
140  *
141  * This struct usually represents a destination or position
142  */
143 struct route_info {
144         struct coord c;                  /**< The actual destination / position */
145         struct coord lp;                 /**< The nearest point on a street to c */
146         int pos;                                 /**< The position of lp within the coords of the street */
147         int lenpos;                      /**< Distance between lp and the end of the street */
148         int lenneg;                      /**< Distance between lp and the start of the street */
149         int lenextra;                    /**< Distance between lp and c */
150
151         struct street_data *street; /**< The street lp is on */
152 };
153
154 /**
155  * @brief A complete route path
156  *
157  * This structure describes a whole routing path
158  */
159 struct route_path {
160         int updated;                                            /**< The path has only been updated */
161         struct route_path_segment *path;                        /**< The first segment in the path, i.e. the segment one should 
162                                                                                                  *  drive in next */
163         struct route_path_segment *path_last;           /**< The last segment in the path */
164         /* XXX: path_hash is not necessery now */
165         struct item_hash *path_hash;                            /**< A hashtable of all the items represented by this route's segements */
166 };
167
168 #define RF_FASTEST      (1<<0)
169 #define RF_SHORTEST     (1<<1)
170 #define RF_AVOIDHW      (1<<2)
171 #define RF_AVOIDPAID    (1<<3)
172 #define RF_LOCKONROAD   (1<<4)
173 #define RF_SHOWGRAPH    (1<<5)
174
175 /**
176  * @brief A complete route
177  * 
178  * This struct holds all information about a route.
179  */
180 struct route {
181         struct mapset *ms;                      /**< The mapset this route is built upon */
182         unsigned flags;
183         struct route_info *pos;         /**< Current position within this route */
184         struct route_info *dst;         /**< Destination of the route */
185
186         struct route_graph *graph;      /**< Pointer to the route graph */
187         struct route_path *path2;       /**< Pointer to the route path */
188         struct map *map;
189         struct map *graph_map;
190         struct callback * route_graph_done_cb ; /**< Callback when route graph is done */
191         struct callback * route_graph_flood_done_cb ; /**< Callback when route graph flooding is done */
192         struct callback_list *cbl;      /**< Callback list to call when route changes */
193         int destination_distance;       /**< Distance to the destination at which the destination is considered "reached" */
194         int speedlist[route_item_last-route_item_first+1];      /**< The speedlist for this route */
195 };
196
197 /**
198  * @brief A complete route graph
199  *
200  * This structure describes a whole routing graph
201  */
202 struct route_graph {
203         int busy;                                       /**< The graph is being built */
204         struct map_selection *sel;                      /**< The rectangle selection for the graph */
205         struct mapset_handle *h;                        /**< Handle to the mapset */    
206         struct map *m;                                  /**< Pointer to the currently active map */     
207         struct map_rect *mr;                            /**< Pointer to the currently active map rectangle */   
208         struct callback *idle_cb;                       /**< Idle callback to process the graph */
209         struct callback *done_cb;                       /**< Callback when graph is done */
210         struct event_idle *idle_ev;                     /**< The pointer to the idle event */
211         struct route_graph_point *route_points;         /**< Pointer to the first route_graph_point in the linked list of  all points */
212         struct route_graph_segment *route_segments; /**< Pointer to the first route_graph_segment in the linked list of all segments */
213 #define HASH_SIZE 8192
214         struct route_graph_point *hash[HASH_SIZE];      /**< A hashtable containing all route_graph_points in this graph */
215 };
216
217 #define HASHCOORD(c) ((((c)->x +(c)->y) * 2654435761UL) & (HASH_SIZE-1))
218
219 /**
220  * @brief Iterator to iterate through all route graph segments in a route graph point
221  *
222  * This structure can be used to iterate through all route graph segments connected to a
223  * route graph point. Use this with the rp_iterator_* functions.
224  */
225 struct route_graph_point_iterator {
226         struct route_graph_point *p;            /**< The route graph point whose segments should be iterated */
227         int end;                                                        /**< Indicates if we have finished iterating through the "start" segments */
228         struct route_graph_segment *next;       /**< The next segment to be returned */
229 };
230
231 static struct route_info * route_find_nearest_street(struct mapset *ms, struct pcoord *c);
232 static struct route_graph_point *route_graph_get_point(struct route_graph *this, struct coord *c);
233 static void route_graph_update(struct route *this, struct callback *cb);
234 static void route_graph_build_done(struct route_graph *rg, int cancel);
235 static struct route_path *route_path_new(struct route_graph *this, struct route_path *oldpath, struct route_info *pos, struct route_info *dst, int *speedlist);
236 static void route_process_street_graph(struct route_graph *this, struct item *item);
237 static void route_graph_destroy(struct route_graph *this);
238 static void route_path_update(struct route *this, int cancel);
239
240 /**
241  * @brief Returns the projection used for this route
242  *
243  * @param route The route to return the projection for
244  * @return The projection used for this route
245  */
246 static enum projection route_projection(struct route *route)
247 {
248         struct street_data *street;
249         if (!route->pos && !route->dst)
250                 return projection_none;
251         street = route->pos ? route->pos->street : route->dst->street;
252         return map_projection(street->item.map);
253 }
254
255 /**
256  * @brief Creates a new graph point iterator 
257  *
258  * This function creates a new route graph point iterator, that can be used to
259  * iterate through all segments connected to the point.
260  *
261  * @param p The route graph point to create the iterator from
262  * @return A new iterator.
263  */
264 static struct route_graph_point_iterator
265 rp_iterator_new(struct route_graph_point *p)
266 {
267         struct route_graph_point_iterator it;
268
269         it.p = p;
270         if (p->start) {
271                 it.next = p->start;
272                 it.end = 0;
273         } else {
274                 it.next = p->end;
275                 it.end = 1;
276         }
277
278         return it;
279 }
280
281 /**
282  * @brief Gets the next segment connected to a route graph point from an iterator
283  *
284  * @param it The route graph point iterator to get the segment from
285  * @return The next segment or NULL if there are no more segments
286  */
287 static struct route_graph_segment
288 *rp_iterator_next(struct route_graph_point_iterator *it) 
289 {
290         struct route_graph_segment *ret;
291
292         ret = it->next;
293         if (!ret) {
294                 return NULL;
295         }
296
297         if (!it->end) {
298                 if (ret->start_next) {
299                         it->next = ret->start_next;
300                 } else {
301                         it->next = it->p->end;
302                         it->end = 1;
303                 }
304         } else {
305                 it->next = ret->end_next;
306         }
307
308         return ret;
309 }
310
311 /**
312  * @brief Checks if the last segment returned from a route_graph_point_iterator comes from the end
313  *
314  * @param it The route graph point iterator to be checked
315  * @return 1 if the last segment returned comes from the end of the route graph point, 0 otherwise
316  */
317 static int
318 rp_iterator_end(struct route_graph_point_iterator *it) {
319         if (it->end && (it->next != it->p->end)) {
320                 return 1;
321         } else {
322                 return 0;
323         }
324 }
325
326 /**
327  * @brief Destroys a route_path
328  *
329  * @param this The route_path to be destroyed
330  */
331 static void
332 route_path_destroy(struct route_path *this)
333 {
334         struct route_path_segment *c,*n;
335         if (! this)
336                 return;
337         if (this->path_hash) {
338                 item_hash_destroy(this->path_hash);
339                 this->path_hash=NULL;
340         }
341         c=this->path;
342         while (c) {
343                 n=c->next;
344                 g_free(c);
345                 c=n;
346         }
347         g_free(this);
348 }
349
350 /**
351  * @brief Creates a completely new route structure
352  *
353  * @param attrs Not used
354  * @return The newly created route
355  */
356 struct route *
357 route_new(struct attr *parent, struct attr **attrs)
358 {
359         struct route *this=g_new0(struct route, 1);
360         struct attr dest_attr;
361
362         if (attr_generic_get_attr(attrs, NULL, attr_destination_distance, &dest_attr, NULL)) {
363                 this->destination_distance = dest_attr.u.num;
364         } else {
365                 this->destination_distance = 50; // Default value
366         }
367         this->cbl=callback_list_new();
368
369         return this;
370 }
371
372 /**
373  * @brief Checks if a segment is part of a roundabout
374  *
375  * This function checks if a segment is part of a roundabout.
376  *
377  * @param seg The segment to be checked
378  * @param level How deep to scan the route graph
379  * @param direction Set this to 1 if we're entering the segment through its end, to 0 otherwise
380  * @param origin Used internally, set to NULL
381  * @return 1 If a roundabout was detected, 0 otherwise
382  */
383 static int
384 route_check_roundabout(struct route_graph_segment *seg, int level, int direction, struct route_graph_segment *origin)
385 {
386         struct route_graph_point_iterator it,it2;
387         struct route_graph_segment *cur;
388         int count=0;
389
390         if (!level) {
391                 return 0;
392         }
393         if (!direction && !(seg->flags & AF_ONEWAY)) {
394                 return 0;
395         }
396         if (direction && !(seg->flags & AF_ONEWAYREV)) {
397                 return 0;
398         }
399         
400         if (!origin) {
401                 origin = seg;
402         }
403
404         if (!direction) {
405                 it = rp_iterator_new(seg->end);
406         } else {
407                 it = rp_iterator_new(seg->start);
408         }
409         it2=it;
410         
411         while ((cur = rp_iterator_next(&it2)))
412                 count++;
413
414         if (count > 3)
415                 return 0;
416         cur = rp_iterator_next(&it);
417         while (cur) {
418                 if (cur == seg) {
419                         cur = rp_iterator_next(&it);
420                         continue;
421                 }
422
423                 if (cur == origin) {
424                         seg->flags |= AF_ROUNDABOUT;
425                         return 1;
426                 }
427
428                 if (route_check_roundabout(cur, (level-1), rp_iterator_end(&it), origin)) {
429                         seg->flags |= AF_ROUNDABOUT;
430                         return 1;
431                 }
432
433                 cur = rp_iterator_next(&it);
434         }
435
436         return 0;
437 }
438
439 /**
440  * @brief Sets the mapset of the route passwd
441  *
442  * @param this The route to set the mapset for
443  * @param ms The mapset to set for this route
444  */
445 void
446 route_set_mapset(struct route *this, struct mapset *ms)
447 {
448         this->ms=ms;
449 }
450
451 /**
452  * @brief Returns the mapset of the route passed
453  *
454  * @param this The route to get the mapset of
455  * @return The mapset of the route passed
456  */
457 struct mapset *
458 route_get_mapset(struct route *this)
459 {
460         return this->ms;
461 }
462
463 /**
464  * @brief Returns the current position within the route passed
465  *
466  * @param this The route to get the position for
467  * @return The position within the route passed
468  */
469 struct route_info *
470 route_get_pos(struct route *this)
471 {
472         return this->pos;
473 }
474
475 /**
476  * @brief Returns the destination of the route passed
477  *
478  * @param this The route to get the destination for
479  * @return The destination of the route passed
480  */
481 struct route_info *
482 route_get_dst(struct route *this)
483 {
484         return this->dst;
485 }
486
487 /**
488  * @brief Returns the speedlist of the route passed
489  *
490  * @param this The route to get the speedlist for
491  * @return The speedlist of the route passed
492  */
493 int *
494 route_get_speedlist(struct route *this)
495 {
496         return this->speedlist;
497 }
498
499 /**
500  * @brief Checks if the path is calculated for the route passed
501  *
502  * @param this The route to check
503  * @return True if the path is calculated, false if not
504  */
505 int
506 route_get_path_set(struct route *this)
507 {
508         return this->path2 != NULL;
509 }
510
511 /**
512  * @brief Sets the driving speed for a certain itemtype
513  *
514  * @param this The route to set the speed for
515  * @param type The itemtype to set the speed for
516  * @param value The speed that should be set
517  * @return True on success, false if the itemtype does not exist
518  */
519 int
520 route_set_speed(struct route *this, enum item_type type, int value)
521 {
522         if (type < route_item_first || type > route_item_last) {
523                 dbg(0,"street type %d out of range [%d,%d]", type, route_item_first, route_item_last);
524                 return 0;
525         }
526         this->speedlist[type-route_item_first]=value;
527         return 1;
528 }
529
530 /**
531  * @brief Checks if the route passed contains a certain item within the route path
532  *
533  * This function checks if a certain items exists in the path that navit will guide
534  * the user to his destination. It does *not* check if this item exists in the route 
535  * graph!
536  *
537  * @param this The route to check for this item
538  * @param item The item to search for
539  * @return True if the item was found, false if the item was not found or the route was not calculated
540  */
541 int
542 route_contains(struct route *this, struct item *item)
543 {
544         if (! this->path2 || !this->path2->path_hash)
545                 return 0;
546         return  (int)item_hash_lookup(this->path2->path_hash, item);
547 }
548
549 /**
550  * @brief Checks if the current position in a route is a certain item
551  *
552  * @param this The route to check for this item
553  * @param item The item to search for
554  * @return True if the current position is this item, false otherwise
555  */
556 int
557 route_pos_contains(struct route *this, struct item *item)
558 {
559         if (! this->pos || !this->pos->street)
560                 return 0;
561         return item_is_equal(this->pos->street->item, *item);
562 }
563
564 /**
565  * @brief Checks if a route has reached its destination
566  *
567  * @param this The route to be checked
568  * @return True if the destination is "reached", false otherwise.
569  */
570 int
571 route_destination_reached(struct route *this)
572 {
573         struct street_data *sd = NULL;
574         enum projection pro;
575
576         if (!this->pos)
577                 return 0;
578
579         sd = this->pos->street;
580
581         if (!this->path2) {
582                 return 0;
583         }
584
585         if (!item_is_equal(this->pos->street->item, this->dst->street->item)) { 
586                 return 0;
587         }
588
589         if ((sd->flags & AF_ONEWAY) && (this->pos->lenneg >= this->dst->lenneg)) { // We would have to drive against the one-way road
590                 return 0;
591         }
592         if ((sd->flags & AF_ONEWAYREV) && (this->pos->lenpos >= this->dst->lenpos)) {
593                 return 0;
594         }
595         pro=route_projection(this);
596         if (pro == projection_none)
597                 return 0;
598          
599         if (transform_distance(pro, &this->pos->c, &this->dst->lp) > this->destination_distance) {
600                 return 0;
601         }
602         
603         return 1;
604 }
605
606 static void
607 route_path_update_done(struct route *this, int new_graph)
608 {
609         struct route_path *oldpath=this->path2;
610         int val;
611
612         this->path2=route_path_new(this->graph, oldpath, this->pos, this->dst, this->speedlist);
613         route_path_destroy(oldpath);
614         if (this->path2) {
615                 if (new_graph)
616                         val=4;
617                 else
618                         val=2+!this->path2->updated;
619         } else
620                 val=1;
621         callback_list_call_attr_1(this->cbl, attr_route, (void *)val);
622 }
623
624 /**
625  * @brief Updates the route graph and the route path if something changed with the route
626  *
627  * This will update the route graph and the route path of the route if some of the
628  * route's settings (destination, position) have changed. 
629  * 
630  * @attention For this to work the route graph has to be destroyed if the route's 
631  * @attention destination is changed somewhere!
632  *
633  * @param this The route to update
634  */
635 static void
636 route_path_update(struct route *this, int cancel)
637 {
638         dbg(1,"enter %d\n", cancel);
639         if (! this->pos || ! this->dst) {
640                 dbg(1,"destroy\n");
641                 route_path_destroy(this->path2);
642                 this->path2 = NULL;
643                 return;
644         }
645         if (cancel) {
646                 route_graph_destroy(this->graph);
647                 this->graph=NULL;
648         }
649         /* the graph is destroyed when setting the destination */
650         if (this->graph) {
651                 if (this->graph->busy) {
652                         dbg(1,"busy building graph\n");
653                         return;
654                 }
655                 // we can try to update
656                 dbg(1,"try update\n");
657                 route_path_update_done(this, 0);
658         } else {
659                 route_path_destroy(this->path2);
660                 this->path2 = NULL;
661         }
662         if (!this->graph || !this->path2) {
663                 dbg(1,"rebuild graph\n");
664                 if (! this->route_graph_flood_done_cb)
665                         this->route_graph_flood_done_cb=callback_new_2(callback_cast(route_path_update_done), this, 1);
666                 dbg(1,"route_graph_update\n");
667                 route_graph_update(this, this->route_graph_flood_done_cb);
668         }
669 }
670
671 /** 
672  * @brief This will calculate all the distances stored in a route_info
673  *
674  * @param ri The route_info to calculate the distances for
675  * @param pro The projection used for this route
676  */
677 static void
678 route_info_distances(struct route_info *ri, enum projection pro)
679 {
680         int npos=ri->pos+1;
681         struct street_data *sd=ri->street;
682         /* 0 1 2 X 3 4 5 6 pos=2 npos=3 count=7 0,1,2 3,4,5,6*/
683         ri->lenextra=transform_distance(pro, &ri->lp, &ri->c);
684         ri->lenneg=transform_polyline_length(pro, sd->c, npos)+transform_distance(pro, &sd->c[ri->pos], &ri->lp);
685         ri->lenpos=transform_polyline_length(pro, sd->c+npos, sd->count-npos)+transform_distance(pro, &sd->c[npos], &ri->lp);
686 }
687
688 /**
689  * @brief This sets the current position of the route passed
690  *
691  * This will set the current position of the route passed to the street that is nearest to the
692  * passed coordinates. It also automatically updates the route.
693  *
694  * @param this The route to set the position of
695  * @param pos Coordinates to set as position
696  */
697 void
698 route_set_position(struct route *this, struct pcoord *pos)
699 {
700         if (this->pos)
701                 route_info_free(this->pos);
702         this->pos=NULL;
703         this->pos=route_find_nearest_street(this->ms, pos);
704         dbg(1,"this->pos=%p\n", this->pos);
705         if (! this->pos)
706                 return;
707         route_info_distances(this->pos, pos->pro);
708         route_path_update(this, 0);
709 }
710
711 /**
712  * @brief Sets a route's current position based on coordinates from tracking
713  *
714  * @param this The route to set the current position of
715  * @param tracking The tracking to get the coordinates from
716  */
717 void
718 route_set_position_from_tracking(struct route *this, struct tracking *tracking)
719 {
720         struct pcoord *c;
721         struct route_info *ret;
722         struct street_data *sd;
723
724         dbg(2,"enter\n");
725         c=tracking_get_pos(tracking);
726         ret=g_new0(struct route_info, 1);
727         if (!ret) {
728                 printf("%s:Out of memory\n", __FUNCTION__);
729                 return;
730         }
731         if (this->pos)
732                 route_info_free(this->pos);
733         this->pos=NULL;
734         ret->c.x = c->x;
735         ret->c.y = c->y;
736         ret->lp.x=c->x;
737         ret->lp.y=c->y;
738         ret->pos=tracking_get_segment_pos(tracking);
739         sd=tracking_get_street_data(tracking);
740         if (sd) {
741                 ret->street=street_data_dup(sd);
742                 route_info_distances(ret, c->pro);
743         }
744         dbg(3,"c->x=0x%x, c->y=0x%x pos=%d item=(0x%x,0x%x)\n", c->x, c->y, ret->pos, ret->street->item.id_hi, ret->street->item.id_lo);
745         dbg(3,"street 0=(0x%x,0x%x) %d=(0x%x,0x%x)\n", ret->street->c[0].x, ret->street->c[0].y, ret->street->count-1, ret->street->c[ret->street->count-1].x, ret->street->c[ret->street->count-1].y);
746         this->pos=ret;
747         if (this->dst) 
748                 route_path_update(this, 0);
749         dbg(2,"ret\n");
750 }
751
752 /* Used for debuging of route_rect, what routing sees */
753 struct map_selection *route_selection;
754
755 /**
756  * @brief Returns a single map selection
757  */
758 struct map_selection *
759 route_rect(int order, struct coord *c1, struct coord *c2, int rel, int abs)
760 {
761         int dx,dy,sx=1,sy=1,d,m;
762         struct map_selection *sel=g_new(struct map_selection, 1);
763         if (!sel) {
764                 printf("%s:Out of memory\n", __FUNCTION__);
765                 return sel;
766         }
767         sel->order=order;
768         sel->range.min=route_item_first;
769         sel->range.max=route_item_last;
770         dbg(1,"%p %p\n", c1, c2);
771         dx=c1->x-c2->x;
772         dy=c1->y-c2->y;
773         if (dx < 0) {
774                 sx=-1;
775                 sel->u.c_rect.lu.x=c1->x;
776                 sel->u.c_rect.rl.x=c2->x;
777         } else {
778                 sel->u.c_rect.lu.x=c2->x;
779                 sel->u.c_rect.rl.x=c1->x;
780         }
781         if (dy < 0) {
782                 sy=-1;
783                 sel->u.c_rect.lu.y=c2->y;
784                 sel->u.c_rect.rl.y=c1->y;
785         } else {
786                 sel->u.c_rect.lu.y=c1->y;
787                 sel->u.c_rect.rl.y=c2->y;
788         }
789         if (dx*sx > dy*sy) 
790                 d=dx*sx;
791         else
792                 d=dy*sy;
793         m=d*rel/100+abs;
794         sel->u.c_rect.lu.x-=m;
795         sel->u.c_rect.rl.x+=m;
796         sel->u.c_rect.lu.y+=m;
797         sel->u.c_rect.rl.y-=m;
798         sel->next=NULL;
799         return sel;
800 }
801
802 /**
803  * @brief Returns a list of map selections useable to create a route graph
804  *
805  * Returns a list of  map selections useable to get a  map rect from which items can be
806  * retrieved to build a route graph. The selections are a rectangle with
807  * c1 and c2 as two corners.
808  *
809  * @param c1 Corner 1 of the rectangle
810  * @param c2 Corder 2 of the rectangle
811  */
812 static struct map_selection *
813 route_calc_selection(struct coord *c1, struct coord *c2)
814 {
815         struct map_selection *ret,*sel;
816         sel=route_rect(4, c1, c2, 25, 0);
817         ret=sel;
818         sel->next=route_rect(8, c1, c1, 0, 40000);
819         sel=sel->next;
820         sel->next=route_rect(18, c1, c1, 0, 10000);
821         sel=sel->next;
822         sel->next=route_rect(8, c2, c2, 0, 40000);
823         sel=sel->next;
824         sel->next=route_rect(18, c2, c2, 0, 10000);
825         /* route_selection=ret; */
826         return ret;
827 }
828
829 /**
830  * @brief Destroys a list of map selections
831  *
832  * @param sel Start of the list to be destroyed
833  */
834 static void
835 route_free_selection(struct map_selection *sel)
836 {
837         struct map_selection *next;
838         while (sel) {
839                 next=sel->next;
840                 g_free(sel);
841                 sel=next;
842         }
843 }
844
845
846 /**
847  * @brief Sets the destination of a route
848  *
849  * This sets the destination of a route to the street nearest to the coordinates passed
850  * and updates the route.
851  *
852  * @param this The route to set the destination for
853  * @param dst Coordinates to set as destination
854  */
855 void
856 route_set_destination(struct route *this, struct pcoord *dst)
857 {
858         profile(0,NULL);
859         if (this->dst)
860                 route_info_free(this->dst);
861         this->dst=NULL;
862         if (dst) {
863                 this->dst=route_find_nearest_street(this->ms, dst);
864                 if(this->dst)
865                         route_info_distances(this->dst, dst->pro);
866         } else 
867                 callback_list_call_attr_1(this->cbl, attr_route, (void *)0);
868         profile(1,"find_nearest_street");
869
870         /* The graph has to be destroyed and set to NULL, otherwise route_path_update() doesn't work */
871         route_graph_destroy(this->graph);
872         this->graph=NULL;
873         route_path_update(this, 1);
874         profile(0,"end");
875 }
876
877 /**
878  * @brief Gets the route_graph_point with the specified coordinates
879  *
880  * @param this The route in which to search
881  * @param c Coordinates to search for
882  * @return The point at the specified coordinates or NULL if not found
883  */
884 static struct route_graph_point *
885 route_graph_get_point(struct route_graph *this, struct coord *c)
886 {
887         struct route_graph_point *p;
888         int hashval=HASHCOORD(c);
889         p=this->hash[hashval];
890         while (p) {
891                 if (p->c.x == c->x && p->c.y == c->y) 
892                         return p;
893                 p=p->hash_next;
894         }
895         return NULL;
896 }
897
898 /**
899  * @brief Inserts a point into the route graph at the specified coordinates
900  *
901  * This will insert a point into the route graph at the coordinates passed in f.
902  * Note that the point is not yet linked to any segments.
903  *
904  * @param this The route to insert the point into
905  * @param f The coordinates at which the point should be inserted
906  * @return The point inserted or NULL on failure
907  */
908 static struct route_graph_point *
909 route_graph_add_point(struct route_graph *this, struct coord *f)
910 {
911         int hashval;
912         struct route_graph_point *p;
913
914         p=route_graph_get_point(this,f);
915         if (!p) {
916                 hashval=HASHCOORD(f);
917                 if (debug_route)
918                         printf("p (0x%x,0x%x)\n", f->x, f->y);
919                 p=g_new(struct route_graph_point,1);
920                 if (!p) {
921                         printf("%s:Out of memory\n", __FUNCTION__);
922                         return p;
923                 }
924                 p->hash_next=this->hash[hashval];
925                 this->hash[hashval]=p;
926                 p->next=this->route_points;
927                 p->el=NULL;
928                 p->start=NULL;
929                 p->end=NULL;
930                 p->seg=NULL;
931                 p->value=INT_MAX;
932                 p->c=*f;
933                 this->route_points=p;
934         }
935         return p;
936 }
937
938 /**
939  * @brief Frees all the memory used for points in the route graph passed
940  *
941  * @param this The route graph to delete all points from
942  */
943 static void
944 route_graph_free_points(struct route_graph *this)
945 {
946         struct route_graph_point *curr,*next;
947         curr=this->route_points;
948         while (curr) {
949                 next=curr->next;
950                 g_free(curr);
951                 curr=next;
952         }
953         this->route_points=NULL;
954         memset(this->hash, 0, sizeof(this->hash));
955 }
956
957 /**
958  * @brief Inserts a new segment into the route graph
959  *
960  * This function performs a check if a segment for the item specified already exists, and inserts
961  * a new segment representing this item if it does not.
962  *
963  * @param this The route graph to insert the segment into
964  * @param start The graph point which should be connected to the start of this segment
965  * @param end The graph point which should be connected to the end of this segment
966  * @param len The length of this segment
967  * @param item The item that is represented by this segment
968  * @param flags Flags for this segment
969  * @param offset If the item passed in "item" is segmented (i.e. divided into several segments), this indicates the position of this segment within the item
970  */
971 static void
972 route_graph_add_segment(struct route_graph *this, struct route_graph_point *start,
973                         struct route_graph_point *end, int len, struct item *item,
974                         int flags, int offset)
975 {
976         struct route_graph_segment *s;
977
978         s=start->start;
979         while (s) {
980                 if (item_is_equal(*item, s->item) && (s->offset == offset)) 
981                         return;
982                 s=s->start_next;
983         } 
984
985         s = g_new0(struct route_graph_segment, 1);
986         if (!s) {
987                 printf("%s:Out of memory\n", __FUNCTION__);
988                 return;
989         }
990         s->start=start;
991         s->start_next=start->start;
992         start->start=s;
993         s->end=end;
994         s->end_next=end->end;
995         end->end=s;
996         dbg_assert(len >= 0);
997         s->len=len;
998         s->item=*item;
999         s->flags=flags;
1000         s->offset = offset;
1001         s->next=this->route_segments;
1002         this->route_segments=s;
1003         if (debug_route)
1004                 printf("l (0x%x,0x%x)-(0x%x,0x%x)\n", start->c.x, start->c.y, end->c.x, end->c.y);
1005 }
1006
1007 /**
1008  * @brief Gets all the coordinates of an item
1009  *
1010  * This will get all the coordinates of the item i and return them in c,
1011  * up to max coordinates. Additionally it is possible to limit the coordinates
1012  * returned to all the coordinates of the item between the two coordinates
1013  * start end end.
1014  *
1015  * @important Make shure that whatever c points to has enough memory allocated
1016  * @important to hold max coordinates!
1017  *
1018  * @param i The item to get the coordinates of
1019  * @param c Pointer to memory allocated for holding the coordinates
1020  * @param max Maximum number of coordinates to return
1021  * @param start First coordinate to get
1022  * @param end Last coordinate to get
1023  * @return The number of coordinates returned
1024  */
1025 static int get_item_seg_coords(struct item *i, struct coord *c, int max,
1026                 struct coord *start, struct coord *end)
1027 {
1028         struct map_rect *mr;
1029         struct item *item;
1030         int rc = 0, p = 0;
1031         struct coord c1;
1032         mr=map_rect_new(i->map, NULL);
1033         if (!mr)
1034                 return 0;
1035         item = map_rect_get_item_byid(mr, i->id_hi, i->id_lo);
1036         if (item) {
1037                 rc = item_coord_get(item, &c1, 1);
1038                 while (rc && (c1.x != start->x || c1.y != start->y)) {
1039                         rc = item_coord_get(item, &c1, 1);
1040                 }
1041                 while (rc && p < max) {
1042                         c[p++] = c1;
1043                         if (c1.x == end->x && c1.y == end->y)
1044                                 break;
1045                         rc = item_coord_get(item, &c1, 1);
1046                 }
1047         }
1048         map_rect_destroy(mr);
1049         return p;
1050 }
1051
1052 /**
1053  * @brief Returns and removes one segment from a path
1054  *
1055  * @param path The path to take the segment from
1056  * @param item The item whose segment to remove
1057  * @param offset Offset of the segment within the item to remove. If the item is not segmented this should be 1.
1058  * @return The segment removed
1059  */
1060 static struct route_path_segment *
1061 route_extract_segment_from_path(struct route_path *path, struct item *item,
1062                                                  int offset)
1063 {
1064         struct route_path_segment *sp = NULL, *s;
1065         s = path->path;
1066         while (s) {
1067                 if (s->offset == offset && item_is_equal(s->item,*item)) {
1068                         if (sp) {
1069                                 sp->next = s->next;
1070                                 break;
1071                         } else {
1072                                 path->path = s->next;
1073                                 break;
1074                         }
1075                 }
1076                 sp = s;
1077                 s = s->next;
1078         }
1079         if (s)
1080                 item_hash_remove(path->path_hash, item);
1081         return s;
1082 }
1083
1084 /**
1085  * @brief Adds a segment and the end of a path
1086  *
1087  * @param this The path to add the segment to
1088  * @param segment The segment to add
1089  */
1090 static void
1091 route_path_add_segment(struct route_path *this, struct route_path_segment *segment)
1092 {
1093         if (!this->path)
1094                 this->path=segment;
1095         if (this->path_last)
1096                 this->path_last->next=segment;
1097         this->path_last=segment;
1098 }
1099
1100 /**
1101  * @brief Adds a new item to a path
1102  *
1103  * This adds a new item to a path, creating a new segment for it. Please note that this function does not check
1104  * if the item passed is segmented - it will create exactly one segment.
1105  *
1106  * @param this The path to add the item to
1107  * @param item The item to add
1108  * @param len The length of the item
1109  * @param first (Optional) coordinate to add to the start of the item. If none should be added, make this NULL.
1110  * @param c Pointer to count coordinates of the item.
1111  * @param cound Number of coordinates in c
1112  * @param last (Optional) coordinate to add to the end of the item. If none should be added, make this NULL.
1113  * @param dir Direction to add the coordinates in. Greater than zero means "start with the first coordinate in c", all other values mean "start with the last coordinate in c"
1114  */
1115 static void
1116 route_path_add_item(struct route_path *this, struct item *item, int len, struct coord *first, struct coord *c, int count, struct coord *last, int dir)
1117 {
1118         int i,idx=0,ccount=count + (first ? 1:0) + (last ? 1:0);
1119         struct route_path_segment *segment;
1120         
1121         segment=g_malloc0(sizeof(*segment) + sizeof(struct coord) * ccount);
1122         segment->ncoords=ccount;
1123         segment->direction=dir;
1124         if (first)
1125                 segment->c[idx++]=*first;
1126         if (dir > 0) {
1127                 for (i = 0 ; i < count ; i++)
1128                         segment->c[idx++]=c[i];
1129         } else {
1130                 for (i = 0 ; i < count ; i++)
1131                         segment->c[idx++]=c[count-i-1];
1132         }
1133         if (last)
1134                 segment->c[idx++]=*last;
1135         segment->length=len;
1136         if (item)
1137                 segment->item=*item;
1138         route_path_add_segment(this, segment);
1139 }
1140
1141 /**
1142  * @brief Inserts a new item into the path
1143  * 
1144  * This function does almost the same as "route_apth_add_item()", but identifies
1145  * the item to add by a segment from the route graph. Another difference is that it "copies" the
1146  * segment from the route graph, i.e. if the item is segmented, only the segment passed in rgs will
1147  * be added to the route path, not all segments of the item. 
1148  *
1149  * The function can be sped up by passing an old path already containing this segment in oldpath - 
1150  * the segment will then be extracted from this old path. Please note that in this case the direction
1151  * parameter has no effect.
1152  *
1153  * @param this The path to add the item to
1154  * @param oldpath Old path containing the segment to be added. Speeds up the function, but can be NULL.
1155  * @param rgs Segment of the route graph that should be "copied" to the route path
1156  * @param len Length of the item to be added
1157  * @param offset Offset of rgs within the item it represents
1158  * @param dir Order in which to add the coordinates. See route_path_add_item()
1159  * @param straight Indicates if this segment is being entered "straight". See route_check_straight().
1160  */
1161 static int
1162 route_path_add_item_from_graph(struct route_path *this, struct route_path *oldpath,
1163                                    struct route_graph_segment *rgs, int len, int offset, int dir, int straight)
1164 {
1165         struct route_path_segment *segment;
1166         int i,ccnt = 0, ret=1;
1167         struct coord ca[2048];
1168
1169         if (oldpath) {
1170                 ccnt = (int)item_hash_lookup(oldpath->path_hash, &rgs->item);
1171                 if (ccnt) {
1172                         segment = route_extract_segment_from_path(oldpath,
1173                                                          &rgs->item, offset);
1174                         
1175                         if (segment) 
1176                                 goto linkold;
1177                 }
1178         }
1179
1180         ccnt = get_item_seg_coords(&rgs->item, ca, 2047, &rgs->start->c, &rgs->end->c);
1181         segment= g_malloc0(sizeof(*segment) + sizeof(struct coord) * ccnt);
1182         segment->direction=dir;
1183         if (dir > 0) {
1184                 for (i = 0 ; i < ccnt ; i++)
1185                         segment->c[i]=ca[i];
1186         } else {
1187                 for (i = 0 ; i < ccnt ; i++)
1188                         segment->c[i]=ca[ccnt-i-1];
1189         }
1190         segment->ncoords = ccnt;
1191
1192         /* We check if the route graph segment is part of a roundabout here, because this
1193          * only matters for route graph segments which form parts of the route path */
1194         if (!(rgs->flags & AF_ROUNDABOUT)) { // We identified this roundabout earlier
1195                 route_check_roundabout(rgs, 13, (dir < 1), NULL);
1196         }
1197
1198         ret=0;
1199         segment->item=rgs->item;
1200         segment->offset = offset;
1201 linkold:
1202         segment->length=len;
1203         segment->next=NULL;
1204         item_hash_insert(this->path_hash,  &rgs->item, (void *)ccnt);
1205
1206         route_path_add_segment(this, segment);
1207
1208         return ret;
1209 }
1210
1211 /**
1212  * @brief Destroys all segments of a route graph
1213  *
1214  * @param this The graph to destroy all segments from
1215  */
1216 static void
1217 route_graph_free_segments(struct route_graph *this)
1218 {
1219         struct route_graph_segment *curr,*next;
1220         curr=this->route_segments;
1221         while (curr) {
1222                 next=curr->next;
1223                 g_free(curr);
1224                 curr=next;
1225         }
1226         this->route_segments=NULL;
1227 }
1228
1229 /**
1230  * @brief Destroys a route graph
1231  * 
1232  * @param this The route graph to be destroyed
1233  */
1234 static void
1235 route_graph_destroy(struct route_graph *this)
1236 {
1237         if (this) {
1238                 route_graph_build_done(this, 1);
1239                 route_graph_free_points(this);
1240                 route_graph_free_segments(this);
1241                 g_free(this);
1242         }
1243 }
1244
1245 /**
1246  * @brief Returns the time needed to drive len on item
1247  *
1248  * This function returns the time needed to drive len meters on 
1249  * the item passed in item in tenth of seconds.
1250  *
1251  * @param speedlist The speedlist that should be used
1252  * @param item The item to be driven on
1253  * @param len The length to drive
1254  * @return The time needed to drive len on item in thenth of senconds
1255  */
1256 int
1257 route_time(int *speedlist, struct item *item, int len)
1258 {
1259         if (item->type < route_item_first || item->type > route_item_last) {
1260                 dbg(0,"street type %d out of range [%d,%d]\n", item->type, route_item_first, route_item_last);
1261                 return len*36;
1262         }
1263         if (!speedlist[item->type-route_item_first]) {
1264                 dbg(0,"street type %d speed is zero\n", item->type);
1265                 return len*36;
1266         }
1267
1268         return len*36/speedlist[item->type-route_item_first];
1269 }
1270
1271 /**
1272  * @brief Returns the "costs" of driving len on item
1273  *
1274  * @param speedlist The speedlist that should be used
1275  * @param item The item to be driven on
1276  * @param len The length to drive
1277  * @return The "costs" needed to drive len on item
1278  */  
1279 static int
1280 route_value(int *speedlist, struct item *item, int len)
1281 {
1282         int ret;
1283         if (len < 0) {
1284                 printf("len=%d\n", len);
1285         }
1286         dbg_assert(len >= 0);
1287         ret=route_time(speedlist, item, len);
1288         dbg(1, "route_value(0x%x, %d)=%d\n", item->type, len, ret);
1289         return ret;
1290 }
1291
1292 /**
1293  * @brief Adds an item to the route graph
1294  *
1295  * This adds an item (e.g. a street) to the route graph, creating as many segments as needed for a
1296  * segmented item.
1297  *
1298  * @param this The route graph to add to
1299  * @param item The item to add
1300  */
1301 static void
1302 route_process_street_graph(struct route_graph *this, struct item *item)
1303 {
1304 #ifdef AVOID_FLOAT
1305         int len=0;
1306 #else
1307         double len=0;
1308 #endif
1309         struct route_graph_point *s_pnt,*e_pnt;
1310         struct coord c,l;
1311         struct attr attr;
1312         int flags = 0;
1313         int segmented = 0;
1314         int offset = 1;
1315
1316         if (item_coord_get(item, &l, 1)) {
1317                 if (item_attr_get(item, attr_flags, &attr)) {
1318                         flags = attr.u.num;
1319                         if (flags & AF_SEGMENTED)
1320                                 segmented = 1;
1321                 }
1322                 s_pnt=route_graph_add_point(this,&l);
1323                 if (!segmented) {
1324                         while (item_coord_get(item, &c, 1)) {
1325                                 len+=transform_distance(map_projection(item->map), &l, &c);
1326                                 l=c;
1327                         }
1328                         e_pnt=route_graph_add_point(this,&l);
1329                         dbg_assert(len >= 0);
1330                         route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset);
1331                 } else {
1332                         int isseg,rc;
1333                         int sc = 0;
1334                         do {
1335                                 isseg = item_coord_is_node(item);
1336                                 rc = item_coord_get(item, &c, 1);
1337                                 if (rc) {
1338                                         len+=transform_distance(map_projection(item->map), &l, &c);
1339                                         l=c;
1340                                         if (isseg) {
1341                                                 e_pnt=route_graph_add_point(this,&l);
1342                                                 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset);
1343                                                 offset++;
1344                                                 s_pnt=route_graph_add_point(this,&l);
1345                                                 len = 0;
1346                                         }
1347                                 }
1348                         } while(rc);
1349                         e_pnt=route_graph_add_point(this,&l);
1350                         dbg_assert(len >= 0);
1351                         sc++;
1352                         route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset);
1353                 }
1354         }
1355 }
1356
1357 /**
1358  * @brief Compares the costs of reaching the destination from two points on
1359  * 
1360  * @important Do not pass anything other than route_graph_points in v1 and v2!
1361  *
1362  * @param v1 Point1 
1363  * @param v2 Point2
1364  * @return The additional costs of v1 compared to v2 (may be negative)
1365  */
1366 static int
1367 compare(void *v1, void *v2)
1368 {
1369         struct route_graph_point *p1=v1;
1370         struct route_graph_point *p2=v2;
1371 #if 0
1372         if (debug_route)
1373                 printf("compare %d (%p) vs %d (%p)\n", p1->value,p1,p2->value,p2);
1374 #endif
1375         return p1->value-p2->value;
1376 }
1377
1378 /**
1379  * @brief Calculates the routing costs for each point
1380  *
1381  * This function is the heart of routing. It assigns each point in the route graph a
1382  * cost at which one can reach the destination from this point on. Additionally it assigns
1383  * each point a segment one should follow from this point on to reach the destination at the
1384  * stated costs.
1385  * 
1386  * This function uses Dijkstra's algorithm to do the routing. To understand it you should have a look
1387  * at this algorithm.
1388  */
1389 static void
1390 route_graph_flood(struct route_graph *this, struct route_info *dst, int *speedlist, struct callback *cb)
1391 {
1392         struct route_graph_point *p_min,*end=NULL;
1393         struct route_graph_segment *s;
1394         int min,new,old,val;
1395         struct fibheap *heap; /* This heap will hold all points with "temporarily" calculated costs */
1396         struct street_data *sd=dst->street;
1397
1398         heap = fh_makeheap();   
1399         fh_setcmp(heap, compare);
1400
1401         if (! (sd->flags & AF_ONEWAYREV)) { /* If we may drive in the direction of the coordinates of the item, the first coordinate is one starting point */
1402                 end=route_graph_get_point(this, &sd->c[0]);
1403                 dbg_assert(end != 0);
1404                 end->value=route_value(speedlist, &sd->item, dst->lenneg);
1405                 end->el=fh_insert(heap, end);
1406         }
1407
1408         if (! (sd->flags & AF_ONEWAY)) { /* If we may drive against the direction of the coordinates, the last coordinate is another starting point */
1409                 end=route_graph_get_point(this, &sd->c[sd->count-1]);
1410                 dbg_assert(end != 0);
1411                 end->value=route_value(speedlist, &sd->item, dst->lenpos);
1412                 end->el=fh_insert(heap, end);
1413         }
1414
1415         dbg(1,"0x%x,0x%x\n", end->c.x, end->c.y);
1416         for (;;) {
1417                 p_min=fh_extractmin(heap); /* Starting Dijkstra by selecting the point with the minimum costs on the heap */
1418                 if (! p_min) /* There are no more points with temporarily calculated costs, Dijkstra has finished */
1419                         break;
1420                 min=p_min->value;
1421                 if (debug_route)
1422                         printf("extract p=%p free el=%p min=%d, 0x%x, 0x%x\n", p_min, p_min->el, min, p_min->c.x, p_min->c.y);
1423                 p_min->el=NULL; /* This point is permanently calculated now, we've taken it out of the heap */
1424                 s=p_min->start;
1425                 while (s) { /* Iterating all the segments leading away from our point to update the points at their ends */
1426                         val=route_value(speedlist, &s->item, s->len);
1427 #if 0
1428                         val+=val*2*street_route_contained(s->str->segid);
1429 #endif
1430                         new=min+val;
1431                         if (debug_route)
1432                                 printf("begin %d len %d vs %d (0x%x,0x%x)\n",new,val,s->end->value, s->end->c.x, s->end->c.y);
1433                         if (new < s->end->value && !(s->flags & AF_ONEWAY)) { /* We've found a less costly way to reach the end of s, update it */
1434                                 s->end->value=new;
1435                                 s->end->seg=s;
1436                                 if (! s->end->el) {
1437                                         if (debug_route)
1438                                                 printf("insert_end p=%p el=%p val=%d ", s->end, s->end->el, s->end->value);
1439                                         s->end->el=fh_insert(heap, s->end);
1440                                         if (debug_route)
1441                                                 printf("el new=%p\n", s->end->el);
1442                                 }
1443                                 else {
1444                                         if (debug_route)
1445                                                 printf("replace_end p=%p el=%p val=%d\n", s->end, s->end->el, s->end->value);
1446                                         fh_replacedata(heap, s->end->el, s->end);
1447                                 }
1448                         }
1449                         if (debug_route)
1450                                 printf("\n");
1451                         s=s->start_next;
1452                 }
1453                 s=p_min->end;
1454                 while (s) { /* Doing the same as above with the segments leading towards our point */
1455                         val=route_value(speedlist, &s->item, s->len);
1456                         new=min+val;
1457                         if (debug_route)
1458                                 printf("end %d len %d vs %d (0x%x,0x%x)\n",new,val,s->start->value,s->start->c.x, s->start->c.y);
1459                         if (new < s->start->value && !(s->flags & AF_ONEWAYREV)) {
1460                                 old=s->start->value;
1461                                 s->start->value=new;
1462                                 s->start->seg=s;
1463                                 if (! s->start->el) {
1464                                         if (debug_route)
1465                                                 printf("insert_start p=%p el=%p val=%d ", s->start, s->start->el, s->start->value);
1466                                         s->start->el=fh_insert(heap, s->start);
1467                                         if (debug_route)
1468                                                 printf("el new=%p\n", s->start->el);
1469                                 }
1470                                 else {
1471                                         if (debug_route)
1472                                                 printf("replace_start p=%p el=%p val=%d\n", s->start, s->start->el, s->start->value);
1473                                         fh_replacedata(heap, s->start->el, s->start);
1474                                 }
1475                         }
1476                         if (debug_route)
1477                                 printf("\n");
1478                         s=s->end_next;
1479                 }
1480         }
1481         fh_deleteheap(heap);
1482         callback_call_0(cb);
1483 }
1484
1485 /**
1486  * @brief Starts an "offroad" path
1487  *
1488  * This starts a path that is not located on a street. It creates a new route path
1489  * adding only one segment, that leads from pos to dest, and which is not associated with an item.
1490  *
1491  * @param this Not used
1492  * @param pos The starting position for the new path
1493  * @param dst The destination of the new path
1494  * @param dir Not used
1495  * @return The new path
1496  */
1497 static struct route_path *
1498 route_path_new_offroad(struct route_graph *this, struct route_info *pos, struct route_info *dst, int dir)
1499 {
1500         struct route_path *ret;
1501
1502         ret=g_new0(struct route_path, 1);
1503         ret->path_hash=item_hash_new();
1504         route_path_add_item(ret, NULL, pos->lenextra+dst->lenextra, &pos->c, NULL, 0, &dst->c, 1);
1505         ret->updated=1;
1506
1507         return ret;
1508 }
1509
1510 /**
1511  * @brief Creates a new "trivial" route
1512  * 
1513  * This function creates a new "trivial" route. A trivial route is a route that starts and ends on the same street,
1514  * so there is no routing needed. Depending on pos and dst it can optionally add some "offroad" part to the route.
1515  *
1516  * @param this The route graph to place the route on
1517  * @param pos The starting position for the new path
1518  * @param dst The destination of the new path
1519  * @param dir Direction of the coordinates to be added
1520  * @return The new path
1521  */
1522 static struct route_path *
1523 route_path_new_trivial(struct route_graph *this, struct route_info *pos, struct route_info *dst, int dir)
1524 {
1525         struct street_data *sd=pos->street;
1526         struct route_path *ret;
1527
1528         if (dir > 0) {
1529                 if (pos->lenextra + dst->lenextra + pos->lenneg-dst->lenneg > transform_distance(map_projection(sd->item.map), &pos->c, &dst->c))
1530                         return route_path_new_offroad(this, pos, dst, dir);
1531         } else {
1532                 if (pos->lenextra + dst->lenextra + pos->lenpos-dst->lenpos > transform_distance(map_projection(sd->item.map), &pos->c, &dst->c))
1533                         return route_path_new_offroad(this, pos, dst, dir);
1534         }
1535         ret=g_new0(struct route_path, 1);
1536         ret->path_hash=item_hash_new();
1537         if (pos->lenextra) 
1538                 route_path_add_item(ret, NULL, pos->lenextra, &pos->c, NULL, 0, &pos->lp, 1);
1539         if (dir > 0)
1540                 route_path_add_item(ret, &sd->item, pos->lenpos-dst->lenpos, &pos->lp, sd->c+pos->pos+1, dst->pos+pos->pos, &dst->lp, 1);
1541         else
1542                 route_path_add_item(ret, &sd->item, pos->lenneg-dst->lenneg, &pos->lp, sd->c+dst->pos+1, pos->pos-dst->pos, &dst->lp, -1);
1543         if (dst->lenextra) 
1544                 route_path_add_item(ret, NULL, dst->lenextra, &dst->lp, NULL, 0, &dst->c, 1);
1545         ret->updated=1;
1546         return ret;
1547 }
1548
1549 /**
1550  * @brief Returns a coordinate at a given distance
1551  *
1552  * This function returns the coordinate, where the user will be if he
1553  * follows the current route for a certain distance.
1554  *
1555  * @param this_ The route we're driving upon
1556  * @param dist The distance in meters
1557  * @return The coordinate where the user will be in that distance
1558  */
1559 struct coord 
1560 route_get_coord_dist(struct route *this_, int dist)
1561 {
1562         int d,l,i,len;
1563         int dx,dy;
1564         double frac;
1565         struct route_path_segment *cur;
1566         struct coord ret;
1567         enum projection pro=route_projection(this_);
1568
1569         d = dist;
1570
1571         if (!this_->path2 || pro == projection_none) {
1572                 return this_->pos->c;
1573         }
1574         
1575         ret = this_->pos->c;
1576         cur = this_->path2->path;
1577         while (cur) {
1578                 if (cur->length < d) {
1579                         d -= cur->length;
1580                 } else {
1581                         for (i=0; i < (cur->ncoords-1); i++) {
1582                                 l = d;
1583                                 len = (int)transform_polyline_length(pro, (cur->c + i), 2);
1584                                 d -= len;
1585                                 if (d <= 0) { 
1586                                         // We interpolate a bit here...
1587                                         frac = (double)l / len;
1588                                         
1589                                         dx = (cur->c + i + 1)->x - (cur->c + i)->x;
1590                                         dy = (cur->c + i + 1)->y - (cur->c + i)->y;
1591                                         
1592                                         ret.x = (cur->c + i)->x + (frac * dx);
1593                                         ret.y = (cur->c + i)->y + (frac * dy);
1594                                         return ret;
1595                                 }
1596                         }
1597                         return cur->c[(cur->ncoords-1)];
1598                 }
1599                 cur = cur->next;
1600         }
1601
1602         return this_->dst->c;
1603 }
1604
1605 /**
1606  * @brief Creates a new route path
1607  * 
1608  * This creates a new non-trivial route. It therefore needs the routing information created by route_graph_flood, so
1609  * make shure to run route_graph_flood() after changing the destination before using this function.
1610  *
1611  * @param this The route graph to create the route from
1612  * @param oldpath (Optional) old path which may contain parts of the new part - this speeds things up a bit. May be NULL.
1613  * @param pos The starting position of the route
1614  * @param dst The destination of the route
1615  * @param speedlist The speedlist to use
1616  * @return The new route path
1617  */
1618 static struct route_path *
1619 route_path_new(struct route_graph *this, struct route_path *oldpath, struct route_info *pos, struct route_info *dst, int *speedlist)
1620 {
1621         struct route_graph_point *start1=NULL,*start2=NULL,*start;
1622         struct route_graph_segment *s=NULL;
1623         struct route_graph_segment *lastseg = NULL;
1624         int is_straight=0;
1625         int len=0,segs=0;
1626         int seg_len;
1627 #if 0
1628         int time=0,hr,min,sec
1629 #endif
1630         unsigned int val1=0xffffffff,val2=0xffffffff;
1631         struct street_data *sd=pos->street;
1632         struct route_path *ret;
1633
1634         if (! pos->street || ! dst->street)
1635                 return NULL;
1636         if (item_is_equal(pos->street->item, dst->street->item)) { /* We probably don't have to leave this street and can use a trivial route */
1637                 if (!(sd->flags & AF_ONEWAY) && pos->lenneg >= dst->lenneg) {
1638                         return route_path_new_trivial(this, pos, dst, -1);
1639                 }
1640                 if (!(sd->flags & AF_ONEWAYREV) && pos->lenpos >= dst->lenpos) {
1641                         return route_path_new_trivial(this, pos, dst, 1);
1642                 }
1643         } 
1644         if (! (sd->flags & AF_ONEWAY)) { /* Using the start of the current segment as one starting point */
1645                 start1=route_graph_get_point(this, &sd->c[0]);
1646                 if (! start1)
1647                         return NULL;
1648                 val1=start1->value+route_value(speedlist, &sd->item, pos->lenneg);
1649                 dbg(1,"start1: %d(route)+%d=%d\n", start1->value, val1-start1->value, val1);
1650         }
1651         if (! (sd->flags & AF_ONEWAYREV)) { /* Using the start of the current segment as an alternative starting point */
1652                 start2=route_graph_get_point(this, &sd->c[sd->count-1]);
1653                 if (! start2)
1654                         return NULL;
1655                 val2=start2->value+route_value(speedlist, &sd->item, pos->lenpos);
1656                 dbg(1,"start2: %d(route)+%d=%d\n", start2->value, val2-start2->value, val2);
1657         }
1658         dbg(1,"val1=%d val2=%d\n", val1, val2);
1659         if (val1 == val2) {
1660                 val1=start1->start->start->value;
1661                 val2=start2->end->end->value;
1662         }
1663         ret=g_new0(struct route_path, 1);
1664         ret->updated=1;
1665         if (pos->lenextra) 
1666                 route_path_add_item(ret, NULL, pos->lenextra, &pos->c, NULL, 0, &pos->lp, 1);
1667         if (start1 && (val1 < val2)) {
1668                 start=start1;
1669                 route_path_add_item(ret, &sd->item, pos->lenneg, &pos->lp, sd->c, pos->pos+1, NULL, -1);
1670         } else {
1671                 if (start2) {
1672                         start=start2;
1673                         route_path_add_item(ret, &sd->item, pos->lenpos, &pos->lp, sd->c+pos->pos+1, sd->count-pos->pos-1, NULL, 1);
1674                 } else {
1675                         printf("no route found, pos blocked\n");
1676                         return NULL;
1677                 }
1678         }
1679         ret->path_hash=item_hash_new();
1680         while ((s=start->seg)) { /* following start->seg, which indicates the least costly way to reach our destination */
1681                 segs++;
1682 #if 0
1683                 printf("start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
1684 #endif
1685                 seg_len=s->len;
1686                 len+=seg_len;
1687         
1688                 if (s->start == start) {                
1689                         if (!route_path_add_item_from_graph(ret, oldpath, s, seg_len, s->offset, 1, is_straight))
1690                                 ret->updated=0;
1691                         start=s->end;
1692                 } else {
1693                         if (!route_path_add_item_from_graph(ret, oldpath, s, seg_len, s->offset, -1, is_straight))
1694                                 ret->updated=0;
1695                         start=s->start;
1696                 }
1697
1698                 lastseg = s;
1699         }
1700         sd=dst->street;
1701         dbg(1,"start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
1702         dbg(1,"dst sd->flags=%d sd->c[0]=0x%x,0x%x sd->c[sd->count-1]=0x%x,0x%x\n", sd->flags, sd->c[0].x,sd->c[0].y, sd->c[sd->count-1].x, sd->c[sd->count-1].y);
1703         if (start->c.x == sd->c[0].x && start->c.y == sd->c[0].y) { /* Adding a final segment to reach the destination within the destination street */
1704                 route_path_add_item(ret, &sd->item, dst->lenneg, NULL, sd->c, dst->pos+1, &dst->lp, 1);
1705         } else if (start->c.x == sd->c[sd->count-1].x && start->c.y == sd->c[sd->count-1].y) {
1706                 route_path_add_item(ret, &sd->item, dst->lenpos, NULL, sd->c+dst->pos+1, sd->count-dst->pos-1, &dst->lp, -1);
1707         } else {
1708                 printf("no route found\n");
1709                 route_path_destroy(ret);
1710                 return NULL;
1711         }
1712         if (dst->lenextra) 
1713                 route_path_add_item(ret, NULL, dst->lenextra, &dst->lp, NULL, 0, &dst->c, 1);
1714         dbg(1, "%d segments\n", segs);
1715         return ret;
1716 }
1717
1718 static int
1719 route_graph_build_next_map(struct route_graph *rg)
1720 {
1721         do {
1722                 rg->m=mapset_next(rg->h, 1);
1723                 if (! rg->m)
1724                         return 0;
1725                 map_rect_destroy(rg->mr);
1726                 rg->mr=map_rect_new(rg->m, rg->sel);
1727         } while (!rg->mr);
1728                 
1729         return 1;
1730 }
1731
1732 static void
1733 route_graph_build_done(struct route_graph *rg, int cancel)
1734 {
1735         dbg(1,"cancel=%d\n",cancel);
1736         event_remove_idle(rg->idle_ev);
1737         callback_destroy(rg->idle_cb);
1738         map_rect_destroy(rg->mr);
1739         mapset_close(rg->h);
1740         route_free_selection(rg->sel);
1741         rg->idle_ev=NULL;
1742         rg->idle_cb=NULL;
1743         rg->mr=NULL;
1744         rg->h=NULL;
1745         rg->sel=NULL;
1746         if (! cancel)
1747                 callback_call_0(rg->done_cb);
1748         rg->busy=0;
1749 }
1750
1751 static void
1752 route_graph_build_idle(struct route_graph *rg)
1753 {
1754         int count=1000;
1755         struct item *item;
1756
1757         while (count > 0) {
1758                 for (;;) {      
1759                         item=map_rect_get_item(rg->mr);
1760                         if (item)
1761                                 break;
1762                         if (!route_graph_build_next_map(rg)) {
1763                                 route_graph_build_done(rg, 0);
1764                                 return;
1765                         }
1766                 }
1767                 if (item->type >= type_street_0 && item->type <= type_ferry) 
1768                         route_process_street_graph(rg, item);
1769                 count--;
1770         }
1771 }
1772
1773 /**
1774  * @brief Builds a new route graph from a mapset
1775  *
1776  * This function builds a new route graph from a map. Please note that this function does not
1777  * add any routing information to the route graph - this has to be done via the route_graph_flood()
1778  * function.
1779  *
1780  * The function does not create a graph covering the whole map, but only covering the rectangle
1781  * between c1 and c2.
1782  *
1783  * @param ms The mapset to build the route graph from
1784  * @param c1 Corner 1 of the rectangle to use from the map
1785  * @param c2 Corner 2 of the rectangle to use from the map
1786  * @param done_cb The callback which will be called when graph is complete
1787  * @return The new route graph.
1788  */
1789 static struct route_graph *
1790 route_graph_build(struct mapset *ms, struct coord *c1, struct coord *c2, struct callback *done_cb)
1791 {
1792         struct route_graph *ret=g_new0(struct route_graph, 1);
1793
1794         dbg(1,"enter\n");
1795
1796         ret->sel=route_calc_selection(c1, c2);
1797         ret->h=mapset_open(ms);
1798         ret->done_cb=done_cb;
1799         ret->busy=1;
1800         if (route_graph_build_next_map(ret)) {
1801                 ret->idle_cb=callback_new_1(callback_cast(route_graph_build_idle), ret);
1802                 ret->idle_ev=event_add_idle(50, ret->idle_cb);
1803         } else
1804                 route_graph_build_done(ret, 0);
1805
1806         return ret;
1807 }
1808
1809 static void
1810 route_graph_update_done(struct route *this, struct callback *cb)
1811 {
1812         route_graph_flood(this->graph, this->dst, this->speedlist, cb);
1813 }
1814
1815 /**
1816  * @brief Updates the route graph
1817  *
1818  * This updates the route graph after settings in the route have changed. It also
1819  * adds routing information afterwards by calling route_graph_flood().
1820  * 
1821  * @param this The route to update the graph for
1822  */
1823 static void
1824 route_graph_update(struct route *this, struct callback *cb)
1825 {
1826         route_graph_destroy(this->graph);
1827         callback_destroy(this->route_graph_done_cb);
1828         this->route_graph_done_cb=callback_new_2(callback_cast(route_graph_update_done), this, cb);
1829         callback_list_call_attr_1(this->cbl, attr_route, (void *)0);
1830         this->graph=route_graph_build(this->ms, &this->pos->c, &this->dst->c, this->route_graph_done_cb);
1831 }
1832
1833 /**
1834  * @brief Gets street data for an item
1835  *
1836  * @param item The item to get the data for
1837  * @return Street data for the item
1838  */
1839 struct street_data *
1840 street_get_data (struct item *item)
1841 {
1842         int count=0;
1843         struct street_data *ret = NULL, *ret1;
1844         struct attr attr;
1845         const int step = 128;
1846         int c;
1847
1848         do {
1849                 ret1=g_realloc(ret, sizeof(struct street_data)+(count+step)*sizeof(struct coord));
1850                 if (!ret1) {
1851                         if (ret)
1852                                 g_free(ret);
1853                         return NULL;
1854                 }
1855                 ret = ret1;
1856                 c = item_coord_get(item, &ret->c[count], step);
1857                 count += c;
1858         } while (c && c == step);
1859
1860         ret1=g_realloc(ret, sizeof(struct street_data)+count*sizeof(struct coord));
1861         if (ret1)
1862                 ret = ret1;
1863         ret->item=*item;
1864         ret->count=count;
1865         if (item_attr_get(item, attr_flags, &attr)) 
1866                 ret->flags=attr.u.num;
1867         else
1868                 ret->flags=0;
1869
1870         return ret;
1871 }
1872
1873 /**
1874  * @brief Copies street data
1875  * 
1876  * @param orig The street data to copy
1877  * @return The copied street data
1878  */ 
1879 struct street_data *
1880 street_data_dup(struct street_data *orig)
1881 {
1882         struct street_data *ret;
1883         int size=sizeof(struct street_data)+orig->count*sizeof(struct coord);
1884
1885         ret=g_malloc(size);
1886         memcpy(ret, orig, size);
1887
1888         return ret;
1889 }
1890
1891 /**
1892  * @brief Frees street data
1893  *
1894  * @param sd Street data to be freed
1895  */
1896 void
1897 street_data_free(struct street_data *sd)
1898 {
1899         g_free(sd);
1900 }
1901
1902 /**
1903  * @brief Finds the nearest street to a given coordinate
1904  *
1905  * @param ms The mapset to search in for the street
1906  * @param pc The coordinate to find a street nearby
1907  * @return The nearest street
1908  */
1909 static struct route_info *
1910 route_find_nearest_street(struct mapset *ms, struct pcoord *pc)
1911 {
1912         struct route_info *ret=NULL;
1913         int max_dist=1000;
1914         struct map_selection *sel;
1915         int dist,mindist=0,pos;
1916         struct mapset_handle *h;
1917         struct map *m;
1918         struct map_rect *mr;
1919         struct item *item;
1920         struct coord lp;
1921         struct street_data *sd;
1922         struct coord c;
1923         struct coord_geo g;
1924
1925         ret=g_new0(struct route_info, 1);
1926         if (!ret) {
1927                 dbg(0,"Out of memory\n");
1928                 return ret;
1929         }
1930         mindist = INT_MAX;
1931
1932         h=mapset_open(ms);
1933         while ((m=mapset_next(h,1))) {
1934                 c.x = pc->x;
1935                 c.y = pc->y;
1936                 if (map_projection(m) != pc->pro) {
1937                         transform_to_geo(pc->pro, &c, &g);
1938                         transform_from_geo(map_projection(m), &g, &c);
1939                 }
1940                 sel = route_rect(18, &c, &c, 0, max_dist);
1941                 if (!sel)
1942                         continue;
1943                 mr=map_rect_new(m, sel);
1944                 if (!mr) {
1945                         map_selection_destroy(sel);
1946                         continue;
1947                 }
1948                 while ((item=map_rect_get_item(mr))) {
1949                         if (item->type >= type_street_0 && item->type <= type_ferry) {
1950                                 sd=street_get_data(item);
1951                                 if (!sd)
1952                                         continue;
1953                                 dist=transform_distance_polyline_sq(sd->c, sd->count, &c, &lp, &pos);
1954                                 if (dist < mindist) {
1955                                         mindist = dist;
1956                                         if (ret->street) {
1957                                                 street_data_free(ret->street);
1958                                         }
1959                                         ret->c=c;
1960                                         ret->lp=lp;
1961                                         ret->pos=pos;
1962                                         ret->street=sd;
1963                                         dbg(1,"dist=%d id 0x%x 0x%x pos=%d\n", dist, item->id_hi, item->id_lo, pos);
1964                                 } else {
1965                                         street_data_free(sd);
1966                                 }
1967                         }
1968                 }
1969                 map_selection_destroy(sel);
1970                 map_rect_destroy(mr);
1971         }
1972         mapset_close(h);
1973
1974         if (!ret->street || mindist > max_dist*max_dist) {
1975                 if (ret->street) {
1976                         street_data_free(ret->street);
1977                         dbg(1,"Much too far %d > %d\n", mindist, max_dist);
1978                 }
1979                 g_free(ret);
1980                 ret = NULL;
1981         }
1982
1983         return ret;
1984 }
1985
1986 /**
1987  * @brief Destroys a route_info
1988  *
1989  * @param info The route info to be destroyed
1990  */
1991 void
1992 route_info_free(struct route_info *inf)
1993 {
1994         if (inf->street)
1995                 street_data_free(inf->street);
1996         g_free(inf);
1997 }
1998
1999
2000 #include "point.h"
2001
2002 /**
2003  * @brief Returns street data for a route info 
2004  *
2005  * @param rinf The route info to return the street data for
2006  * @return Street data for the route info
2007  */
2008 struct street_data *
2009 route_info_street(struct route_info *rinf)
2010 {
2011         return rinf->street;
2012 }
2013
2014 #if 0
2015 struct route_crossings *
2016 route_crossings_get(struct route *this, struct coord *c)
2017 {
2018       struct route_point *pnt;
2019       struct route_segment *seg;
2020       int crossings=0;
2021       struct route_crossings *ret;
2022
2023        pnt=route_graph_get_point(this, c);
2024        seg=pnt->start;
2025        while (seg) {
2026                 printf("start: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
2027                crossings++;
2028                seg=seg->start_next;
2029        }
2030        seg=pnt->end;
2031        while (seg) {
2032                 printf("end: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
2033                crossings++;
2034                seg=seg->end_next;
2035        }
2036        ret=g_malloc(sizeof(struct route_crossings)+crossings*sizeof(struct route_crossing));
2037        ret->count=crossings;
2038        return ret;
2039 }
2040 #endif
2041
2042
2043 struct map_rect_priv {
2044         struct route_info_handle *ri;
2045         enum attr_type attr_next;
2046         int pos;
2047         struct map_priv *mpriv;
2048         struct item item;
2049         int length;
2050         unsigned int last_coord;
2051         struct route_path_segment *seg,*seg_next;
2052         struct route_graph_point *point;
2053         struct route_graph_segment *rseg;
2054         char *str;
2055         struct coord *coord_sel;        /**< Set this to a coordinate if you want to filter for just a single route graph point */
2056         struct route_graph_point_iterator it;
2057 };
2058
2059 static void
2060 rm_coord_rewind(void *priv_data)
2061 {
2062         struct map_rect_priv *mr = priv_data;
2063         mr->last_coord = 0;
2064 }
2065
2066 static void
2067 rm_attr_rewind(void *priv_data)
2068 {
2069         struct map_rect_priv *mr = priv_data;
2070         mr->attr_next = attr_street_item;
2071 }
2072
2073 static int
2074 rm_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
2075 {
2076         struct map_rect_priv *mr = priv_data;
2077         struct route_path_segment *seg=mr->seg;
2078         struct route *route=mr->mpriv->route;
2079         if (mr->item.type != type_street_route)
2080                 return 0;
2081         attr->type=attr_type;
2082         switch (attr_type) {
2083                 case attr_any:
2084                         while (mr->attr_next != attr_none) {
2085                                 if (rm_attr_get(priv_data, mr->attr_next, attr))
2086                                         return 1;
2087                         }
2088                         return 0;
2089                 case attr_street_item:
2090                         mr->attr_next=attr_direction;
2091                         if (seg && seg->item.map)
2092                                 attr->u.item=&seg->item;
2093                         else
2094                                 return 0;
2095                         return 1;
2096                 case attr_direction:
2097                         mr->attr_next=attr_route;
2098                         if (seg) 
2099                                 attr->u.num=seg->direction;
2100                         else
2101                                 return 0;
2102                         return 1;
2103                 case attr_route:
2104                         mr->attr_next=attr_length;
2105                         attr->u.route = mr->mpriv->route;
2106                         return 1;
2107                 case attr_length:
2108                         if (seg)
2109                                 attr->u.num=seg->length;
2110                         else
2111                                 attr->u.num=mr->length;
2112                         mr->attr_next=attr_time;
2113                         return 1;
2114                 case attr_time:
2115                         mr->attr_next=attr_none;
2116                         if (seg)
2117                                 attr->u.num=route_time(route->speedlist, &seg->item, seg->length);
2118                         else
2119                                 return 0;
2120                         return 1;
2121                 case attr_label:
2122                         mr->attr_next=attr_none;
2123                         return 0;
2124                 default:
2125                         mr->attr_next=attr_none;
2126                         attr->type=attr_none;
2127                         return 0;
2128         }
2129         return 0;
2130 }
2131
2132 static int
2133 rm_coord_get(void *priv_data, struct coord *c, int count)
2134 {
2135         struct map_rect_priv *mr = priv_data;
2136         struct route_path_segment *seg = mr->seg;
2137         int i,rc=0;
2138         struct route *r = mr->mpriv->route;
2139         enum projection pro = route_projection(r);
2140
2141         if (pro == projection_none)
2142                 return 0;
2143         if (mr->item.type == type_route_start || mr->item.type == type_route_end) {
2144                 if (! count || mr->last_coord)
2145                         return 0;
2146                 mr->last_coord=1;
2147                 if (mr->item.type == type_route_start)
2148                         c[0]=r->pos->c;
2149                 else
2150                         c[0]=r->dst->c;
2151                 return 1;
2152         }
2153         if (! seg)
2154                 return 0;
2155         for (i=0; i < count; i++) {
2156                 if (mr->last_coord >= seg->ncoords)
2157                         break;
2158                 if (i >= seg->ncoords)
2159                         break;
2160                 if (pro != projection_mg)
2161                         transform_from_to(&seg->c[mr->last_coord++], pro,
2162                                 &c[i],projection_mg);
2163                 else
2164                         c[i] = seg->c[mr->last_coord++];
2165                 rc++;
2166         }
2167         dbg(1,"return %d\n",rc);
2168         return rc;
2169 }
2170
2171 static struct item_methods methods_route_item = {
2172         rm_coord_rewind,
2173         rm_coord_get,
2174         rm_attr_rewind,
2175         rm_attr_get,
2176 };
2177
2178 static void
2179 rp_attr_rewind(void *priv_data)
2180 {
2181         struct map_rect_priv *mr = priv_data;
2182         mr->attr_next = attr_label;
2183 }
2184
2185 static int
2186 rp_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
2187 {
2188         struct map_rect_priv *mr = priv_data;
2189         struct route_graph_point *p = mr->point;
2190         struct route_graph_segment *seg = mr->rseg;
2191         switch (attr_type) {
2192         case attr_any: // works only with rg_points for now
2193                 if (mr->item.type != type_rg_point) 
2194                         return 0;               
2195                 while (mr->attr_next != attr_none) {
2196                         if (rp_attr_get(priv_data, mr->attr_next, attr))
2197                                 return 1;
2198                 }
2199                 return 0;
2200         case attr_label:
2201                 if (mr->item.type != type_rg_point) 
2202                         return 0;
2203                 attr->type = attr_label;
2204                 if (mr->str)
2205                         g_free(mr->str);
2206                 if (p->value != INT_MAX)
2207                         mr->str=g_strdup_printf("%d", p->value);
2208                 else
2209                         mr->str=g_strdup("-");
2210                 attr->u.str = mr->str;
2211                 mr->attr_next=attr_none;
2212                 return 1;
2213         case attr_street_item:
2214                 if (mr->item.type != type_rg_segment) 
2215                         return 0;
2216                 mr->attr_next=attr_none;
2217                 if (seg && seg->item.map)
2218                         attr->u.item=&seg->item;
2219                 else
2220                         return 0;
2221                 return 1;
2222         case attr_flags:
2223                 if (mr->item.type != type_rg_segment)
2224                         return 0;
2225                 mr->attr_next = attr_none;
2226                 if (seg) {
2227                         attr->u.num = seg->flags;
2228                 } else {
2229                         return 0;
2230                 }
2231                 return 1;
2232         case attr_direction:
2233                 // This only works if the map has been opened at a single point, and in that case indicates if the
2234                 // segment returned last is connected to this point via its start (1) or its end (-1)
2235                 if (!mr->coord_sel || (mr->item.type != type_rg_segment))
2236                         return 0;
2237                 if (seg->start == mr->point) {
2238                         attr->u.num=1;
2239                 } else if (seg->end == mr->point) {
2240                         attr->u.num=-1;
2241                 } else {
2242                         return 0;
2243                 }
2244                 return 1;
2245         case attr_debug:
2246                 if (mr->item.type != type_rg_point) 
2247                         return 0;
2248                 attr->type = attr_debug;
2249                 if (mr->str)
2250                         g_free(mr->str);
2251                 mr->str=g_strdup_printf("x=%d y=%d", p->c.x, p->c.y);
2252                 attr->u.str = mr->str;
2253                 mr->attr_next=attr_none;
2254                 return 1;
2255         default:
2256                 mr->attr_next=attr_none;
2257                 attr->type=attr_none;
2258                 return 0;
2259         }
2260 }
2261
2262 /**
2263  * @brief Returns the coordinates of a route graph item
2264  *
2265  * @param priv_data The route graph item's private data
2266  * @param c Pointer where to store the coordinates
2267  * @param count How many coordinates to get at a max?
2268  * @return The number of coordinates retrieved
2269  */
2270 static int
2271 rp_coord_get(void *priv_data, struct coord *c, int count)
2272 {
2273         struct map_rect_priv *mr = priv_data;
2274         struct route_graph_point *p = mr->point;
2275         struct route_graph_segment *seg = mr->rseg;
2276         int rc = 0,i,dir;
2277         struct route *r = mr->mpriv->route;
2278         enum projection pro = route_projection(r);
2279
2280         if (pro == projection_none)
2281                 return 0;
2282         for (i=0; i < count; i++) {
2283                 if (mr->item.type == type_rg_point) {
2284                         if (mr->last_coord >= 1)
2285                                 break;
2286                         if (pro != projection_mg)
2287                                 transform_from_to(&p->c, pro,
2288                                         &c[i],projection_mg);
2289                         else
2290                                 c[i] = p->c;
2291                 } else {
2292                         if (mr->last_coord >= 2)
2293                                 break;
2294                         dir=0;
2295                         if (seg->end->seg == seg)
2296                                 dir=1;
2297                         if (mr->last_coord)
2298                                 dir=1-dir;
2299                         if (dir) {
2300                                 if (pro != projection_mg)
2301                                         transform_from_to(&seg->end->c, pro,
2302                                                 &c[i],projection_mg);
2303                                 else
2304                                         c[i] = seg->end->c;
2305                         } else {
2306                                 if (pro != projection_mg)
2307                                         transform_from_to(&seg->start->c, pro,
2308                                                 &c[i],projection_mg);
2309                                 else
2310                                         c[i] = seg->start->c;
2311                         }
2312                 }
2313                 mr->last_coord++;
2314                 rc++;
2315         }
2316         return rc;
2317 }
2318
2319 static struct item_methods methods_point_item = {
2320         rm_coord_rewind,
2321         rp_coord_get,
2322         rp_attr_rewind,
2323         rp_attr_get,
2324 };
2325
2326 static void
2327 rp_destroy(struct map_priv *priv)
2328 {
2329         g_free(priv);
2330 }
2331
2332 static void
2333 rm_destroy(struct map_priv *priv)
2334 {
2335         g_free(priv);
2336 }
2337
2338 static struct map_rect_priv * 
2339 rm_rect_new(struct map_priv *priv, struct map_selection *sel)
2340 {
2341         struct map_rect_priv * mr;
2342         dbg(1,"enter\n");
2343         if (! route_get_pos(priv->route))
2344                 return NULL;
2345         if (! route_get_dst(priv->route))
2346                 return NULL;
2347 #if 0
2348         if (! priv->route->path2)
2349                 return NULL;
2350 #endif
2351         mr=g_new0(struct map_rect_priv, 1);
2352         mr->mpriv = priv;
2353         mr->item.priv_data = mr;
2354         mr->item.type = type_none;
2355         mr->item.meth = &methods_route_item;
2356         if (priv->route->path2)
2357                 mr->seg_next=priv->route->path2->path;
2358         else
2359                 mr->seg_next=NULL;
2360         return mr;
2361 }
2362
2363 /**
2364  * @brief Opens a new map rectangle on the route graph's map
2365  *
2366  * This function opens a new map rectangle on the route graph's map.
2367  * The "sel" parameter enables you to only search for a single route graph
2368  * point on this map (or exactly: open a map rectangle that only contains
2369  * this one point). To do this, pass here a single map selection, whose 
2370  * c_rect has both coordinates set to the same point. Otherwise this parameter
2371  * has no effect.
2372  *
2373  * @param priv The route graph map's private data
2374  * @param sel Here it's possible to specify a point for which to search. Please read the function's description.
2375  * @return A new map rect's private data
2376  */
2377 static struct map_rect_priv * 
2378 rp_rect_new(struct map_priv *priv, struct map_selection *sel)
2379 {
2380         struct map_rect_priv * mr;
2381
2382         dbg(1,"enter\n");
2383         if (! priv->route->graph || ! priv->route->graph->route_points)
2384                 return NULL;
2385         mr=g_new0(struct map_rect_priv, 1);
2386         mr->mpriv = priv;
2387         mr->item.priv_data = mr;
2388         mr->item.type = type_rg_point;
2389         mr->item.meth = &methods_point_item;
2390         if (sel) {
2391                 if ((sel->u.c_rect.lu.x == sel->u.c_rect.rl.x) && (sel->u.c_rect.lu.y == sel->u.c_rect.rl.y)) {
2392                         mr->coord_sel = g_malloc(sizeof(struct coord));
2393                         *(mr->coord_sel) = sel->u.c_rect.lu;
2394                 }
2395         }
2396         return mr;
2397 }
2398
2399 static void
2400 rm_rect_destroy(struct map_rect_priv *mr)
2401 {
2402         if (mr->str)
2403                 g_free(mr->str);
2404         if (mr->coord_sel) {
2405                 g_free(mr->coord_sel);
2406         }
2407
2408         g_free(mr);
2409 }
2410
2411 static struct item *
2412 rp_get_item(struct map_rect_priv *mr)
2413 {
2414         struct route *r = mr->mpriv->route;
2415         struct route_graph_point *p = mr->point;
2416         struct route_graph_segment *seg = mr->rseg;
2417
2418         if (mr->item.type == type_rg_point) {
2419                 if (mr->coord_sel) {
2420                         // We are supposed to return only the point at one specified coordinate...
2421                         if (!p) {
2422                                 p = r->graph->hash[HASHCOORD(mr->coord_sel)];
2423                                 while ((p) && ((p->c.x != mr->coord_sel->x) || (p->c.y != mr->coord_sel->y))) {
2424                                         p = p->hash_next;
2425                                 }
2426                                 if ((!p) || !((p->c.x == mr->coord_sel->x) && (p->c.y == mr->coord_sel->y))) {
2427                                         mr->point = NULL; // This indicates that no point has been found
2428                                 } else {
2429                                         mr->it = rp_iterator_new(p);
2430                                 }
2431                         } else {
2432                                 p = NULL;
2433                         }
2434                 } else {
2435                         if (!p)
2436                                 p = r->graph->route_points;
2437                         else
2438                                 p = p->next;
2439                 }
2440                 if (p) {
2441                         mr->point = p;
2442                         mr->item.id_lo++;
2443                         rm_coord_rewind(mr);
2444                         rp_attr_rewind(mr);
2445                         return &mr->item;
2446                 } else
2447                         mr->item.type = type_rg_segment;
2448         }
2449         
2450         if (mr->coord_sel) {
2451                 if (!mr->point) { // This means that no point has been found
2452                         return NULL;
2453                 }
2454                 seg = rp_iterator_next(&(mr->it));
2455         } else {
2456                 if (!seg)
2457                         seg=r->graph->route_segments;
2458                 else
2459                         seg=seg->next;
2460         }
2461         
2462         if (seg) {
2463                 mr->rseg = seg;
2464                 mr->item.id_lo++;
2465                 rm_coord_rewind(mr);
2466                 rp_attr_rewind(mr);
2467                 return &mr->item;
2468         }
2469         return NULL;
2470         
2471 }
2472
2473 static struct item *
2474 rp_get_item_byid(struct map_rect_priv *mr, int id_hi, int id_lo)
2475 {
2476         struct item *ret=NULL;
2477         while (id_lo-- > 0) 
2478                 ret=rp_get_item(mr);
2479         return ret;
2480 }
2481
2482
2483 static struct item *
2484 rm_get_item(struct map_rect_priv *mr)
2485 {
2486         dbg(1,"enter\n", mr->pos);
2487
2488         switch (mr->item.type) {
2489         case type_none:
2490                 mr->item.type=type_route_start;
2491                 if (mr->mpriv->route->pos) 
2492                         break;
2493         default:
2494                 mr->item.type=type_street_route;
2495                 mr->seg=mr->seg_next;
2496                 if (mr->seg) {
2497                         mr->seg_next=mr->seg->next;
2498                         break;
2499                 }
2500                 mr->item.type=type_route_end;
2501                 if (mr->mpriv->route->dst)
2502                         break;
2503         case type_route_end:
2504                 return NULL;
2505         }
2506         mr->last_coord = 0;
2507         mr->item.id_lo++;
2508         rm_attr_rewind(mr);
2509         return &mr->item;
2510 }
2511
2512 static struct item *
2513 rm_get_item_byid(struct map_rect_priv *mr, int id_hi, int id_lo)
2514 {
2515         struct item *ret=NULL;
2516         while (id_lo-- > 0) 
2517                 ret=rm_get_item(mr);
2518         return ret;
2519 }
2520
2521 static struct map_methods route_meth = {
2522         projection_mg,
2523         "utf-8",
2524         rm_destroy,
2525         rm_rect_new,
2526         rm_rect_destroy,
2527         rm_get_item,
2528         rm_get_item_byid,
2529         NULL,
2530         NULL,
2531         NULL,
2532 };
2533
2534 static struct map_methods route_graph_meth = {
2535         projection_mg,
2536         "utf-8",
2537         rp_destroy,
2538         rp_rect_new,
2539         rm_rect_destroy,
2540         rp_get_item,
2541         rp_get_item_byid,
2542         NULL,
2543         NULL,
2544         NULL,
2545 };
2546
2547 void 
2548 route_toggle_routegraph_display(struct route *route)
2549 {
2550         if (route->flags & RF_SHOWGRAPH) {
2551                 route->flags &= ~RF_SHOWGRAPH;
2552         } else {
2553                 route->flags |= RF_SHOWGRAPH;
2554         }
2555 }
2556
2557 static struct map_priv *
2558 route_map_new_helper(struct map_methods *meth, struct attr **attrs, int graph)
2559 {
2560         struct map_priv *ret;
2561         struct attr *route_attr;
2562
2563         route_attr=attr_search(attrs, NULL, attr_route);
2564         if (! route_attr)
2565                 return NULL;
2566         ret=g_new0(struct map_priv, 1);
2567         if (graph)
2568                 *meth=route_graph_meth;
2569         else
2570                 *meth=route_meth;
2571         ret->route=route_attr->u.route;
2572
2573         return ret;
2574 }
2575
2576 static struct map_priv *
2577 route_map_new(struct map_methods *meth, struct attr **attrs)
2578 {
2579         return route_map_new_helper(meth, attrs, 0);
2580 }
2581
2582 static struct map_priv *
2583 route_graph_map_new(struct map_methods *meth, struct attr **attrs)
2584 {
2585         return route_map_new_helper(meth, attrs, 1);
2586 }
2587
2588 static struct map *
2589 route_get_map_helper(struct route *this_, struct map **map, char *type, char *description)
2590 {
2591         if (! *map) 
2592                 *map=map_new(NULL, (struct attr*[]){
2593                                 &(struct attr){attr_type,{type}},
2594                                 &(struct attr){attr_route,.u.route=this_},
2595                                 &(struct attr){attr_data,{""}},
2596                                 &(struct attr){attr_description,{description}},
2597                                 NULL});
2598  
2599         return *map;
2600 }
2601
2602 /**
2603  * @brief Returns a new map containing the route path
2604  *
2605  * This function returns a new map containing the route path.
2606  *
2607  * @important Do not map_destroy() this!
2608  *
2609  * @param this_ The route to get the map of
2610  * @return A new map containing the route path
2611  */
2612 struct map *
2613 route_get_map(struct route *this_)
2614 {
2615         return route_get_map_helper(this_, &this_->map, "route","Route");
2616 }
2617
2618
2619 /**
2620  * @brief Returns a new map containing the route graph
2621  *
2622  * This function returns a new map containing the route graph.
2623  *
2624  * @important Do not map_destroy()  this!
2625  *
2626  * @param this_ The route to get the map of
2627  * @return A new map containing the route graph
2628  */
2629 struct map *
2630 route_get_graph_map(struct route *this_)
2631 {
2632         return route_get_map_helper(this_, &this_->graph_map, "route_graph","Route Graph");
2633 }
2634
2635 void
2636 route_set_projection(struct route *this_, enum projection pro)
2637 {
2638 }
2639
2640 void
2641 route_add_callback(struct route *this_, struct callback *cb)
2642 {
2643         callback_list_add(this_->cbl, cb);
2644 }
2645
2646 void
2647 route_remove_callback(struct route *this_, struct callback *cb)
2648 {
2649         callback_list_remove(this_->cbl, cb);
2650 }
2651
2652
2653 void
2654 route_init(void)
2655 {
2656         plugin_register_map_type("route", route_map_new);
2657         plugin_register_map_type("route_graph", route_graph_map_new);
2658 }