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