2 * Navit, a modular navigation system.
3 * Copyright (C) 2005-2008 Navit Team
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.
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.
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.
21 * @brief Contains code related to finding a route from a position to a destination
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.
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
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.
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.
56 #include "projection.h"
64 #include "transform.h"
78 * @brief A point in the route graph
80 * This represents a point in the route graph. A point usually connects two or more segments,
81 * but there are also points which don't do that (e.g. at the end of a dead-end).
83 struct route_graph_point {
84 struct route_graph_point *next; /**< Linked-list pointer to a list of all route_graph_points */
85 struct route_graph_point *hash_next; /**< Pointer to a chained hashlist of all route_graph_points with this hash */
86 struct route_graph_segment *start; /**< Pointer to a list of segments of which this point is the start. The links
87 * of this linked-list are in route_graph_segment->start_next.*/
88 struct route_graph_segment *end; /**< Pointer to a list of segments of which this pointer is the end. The links
89 * of this linked-list are in route_graph_segment->end_next. */
90 struct route_graph_segment *seg; /**< Pointer to the segment one should use to reach the destination at
92 struct fibheap_el *el; /**< When this point is put on a Fibonacci heap, this is a pointer
93 * to this point's heap-element */
94 int value; /**< The cost at which one can reach the destination from this point on */
95 struct coord c; /**< Coordinates of this point */
99 * @brief A segment in the route graph
101 * This is a segment in the route graph. A segment represents a driveable way.
103 struct route_graph_segment {
104 struct route_graph_segment *next; /**< Linked-list pointer to a list of all route_graph_segments */
105 struct route_graph_segment *start_next; /**< Pointer to the next element in the list of segments that start at the
106 * same point. Start of this list is in route_graph_point->start. */
107 struct route_graph_segment *end_next; /**< Pointer to the next element in the list of segments that end at the
108 * same point. Start of this list is in route_graph_point->end. */
109 struct route_graph_point *start; /**< Pointer to the point this segment starts at. */
110 struct route_graph_point *end; /**< Pointer to the point this segment ends at. */
111 struct item item; /**< The item (e.g. street) that this segment represents. */
113 int len; /**< Length of this segment */
114 int maxspeed; /**< Maximum allowed speed on this segment in km/h. 0 if none, -1 if
116 int offset; /**< If the item represented by this segment is "segmented" (i.e.
117 * is represented by several segments instead of just one), this
118 * indicates the position of this segment in the item - for items
119 * that are not segmented this should always be 1 */
123 * @brief A segment in the route path
125 * This is a segment in the route path.
127 struct route_path_segment {
128 struct route_path_segment *next; /**< Pointer to the next segment in the path */
129 struct item item; /**< The item (e.g. street) this segment represents */
130 int length; /**< Length of the segment */
131 int offset; /**< Same as in route_graph_segment->offset */
132 int direction; /**< Order in which the coordinates are ordered. >0 means "First
133 * coordinate of the segment is the first coordinate of the item", <=0
135 int maxspeed; /**< Maximum allowed speed on this segment in km/h. 0 if none, -1 if unkown. */
136 unsigned ncoords; /**< How many coordinates does this segment have? */
137 struct coord c[0]; /**< Pointer to the ncoords coordinates of this segment */
138 /* WARNING: There will be coordinates following here, so do not create new fields after c! */
142 * @brief Usually represents a destination or position
144 * This struct usually represents a destination or position
147 struct coord c; /**< The actual destination / position */
148 struct coord lp; /**< The nearest point on a street to c */
149 int pos; /**< The position of lp within the coords of the street */
150 int lenpos; /**< Distance between lp and the end of the street */
151 int lenneg; /**< Distance between lp and the start of the street */
152 int lenextra; /**< Distance between lp and c */
154 struct street_data *street; /**< The street lp is on */
158 * @brief A complete route path
160 * This structure describes a whole routing path
163 int updated; /**< The path has only been updated */
164 struct route_path_segment *path; /**< The first segment in the path, i.e. the segment one should
166 struct route_path_segment *path_last; /**< The last segment in the path */
167 /* XXX: path_hash is not necessery now */
168 struct item_hash *path_hash; /**< A hashtable of all the items represented by this route's segements */
171 #define RF_FASTEST (1<<0)
172 #define RF_SHORTEST (1<<1)
173 #define RF_AVOIDHW (1<<2)
174 #define RF_AVOIDPAID (1<<3)
175 #define RF_LOCKONROAD (1<<4)
176 #define RF_SHOWGRAPH (1<<5)
179 * @brief A complete route
181 * This struct holds all information about a route.
184 struct mapset *ms; /**< The mapset this route is built upon */
186 struct route_info *pos; /**< Current position within this route */
187 struct route_info *dst; /**< Destination of the route */
189 struct route_graph *graph; /**< Pointer to the route graph */
190 struct route_path *path2; /**< Pointer to the route path */
192 struct map *graph_map;
193 struct callback * route_graph_done_cb ; /**< Callback when route graph is done */
194 struct callback * route_graph_flood_done_cb ; /**< Callback when route graph flooding is done */
195 struct callback_list *cbl; /**< Callback list to call when route changes */
196 int destination_distance; /**< Distance to the destination at which the destination is considered "reached" */
197 int speedlist[route_item_last-route_item_first+1]; /**< The speedlist for this route */
201 * @brief A complete route graph
203 * This structure describes a whole routing graph
206 int busy; /**< The graph is being built */
207 struct map_selection *sel; /**< The rectangle selection for the graph */
208 struct mapset_handle *h; /**< Handle to the mapset */
209 struct map *m; /**< Pointer to the currently active map */
210 struct map_rect *mr; /**< Pointer to the currently active map rectangle */
211 struct callback *idle_cb; /**< Idle callback to process the graph */
212 struct callback *done_cb; /**< Callback when graph is done */
213 struct event_idle *idle_ev; /**< The pointer to the idle event */
214 struct route_graph_point *route_points; /**< Pointer to the first route_graph_point in the linked list of all points */
215 struct route_graph_segment *route_segments; /**< Pointer to the first route_graph_segment in the linked list of all segments */
216 #define HASH_SIZE 8192
217 struct route_graph_point *hash[HASH_SIZE]; /**< A hashtable containing all route_graph_points in this graph */
220 #define HASHCOORD(c) ((((c)->x +(c)->y) * 2654435761UL) & (HASH_SIZE-1))
223 * @brief Iterator to iterate through all route graph segments in a route graph point
225 * This structure can be used to iterate through all route graph segments connected to a
226 * route graph point. Use this with the rp_iterator_* functions.
228 struct route_graph_point_iterator {
229 struct route_graph_point *p; /**< The route graph point whose segments should be iterated */
230 int end; /**< Indicates if we have finished iterating through the "start" segments */
231 struct route_graph_segment *next; /**< The next segment to be returned */
234 static struct route_info * route_find_nearest_street(struct mapset *ms, struct pcoord *c);
235 static struct route_graph_point *route_graph_get_point(struct route_graph *this, struct coord *c);
236 static void route_graph_update(struct route *this, struct callback *cb);
237 static void route_graph_build_done(struct route_graph *rg, int cancel);
238 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);
239 static void route_process_street_graph(struct route_graph *this, struct item *item);
240 static void route_graph_destroy(struct route_graph *this);
241 static void route_path_update(struct route *this, int cancel);
244 * @brief Returns the projection used for this route
246 * @param route The route to return the projection for
247 * @return The projection used for this route
249 static enum projection route_projection(struct route *route)
251 struct street_data *street;
252 if (!route->pos && !route->dst)
253 return projection_none;
254 street = route->pos ? route->pos->street : route->dst->street;
255 if (!street || !street->item.map)
256 return projection_none;
257 return map_projection(street->item.map);
261 * @brief Creates a new graph point iterator
263 * This function creates a new route graph point iterator, that can be used to
264 * iterate through all segments connected to the point.
266 * @param p The route graph point to create the iterator from
267 * @return A new iterator.
269 static struct route_graph_point_iterator
270 rp_iterator_new(struct route_graph_point *p)
272 struct route_graph_point_iterator it;
287 * @brief Gets the next segment connected to a route graph point from an iterator
289 * @param it The route graph point iterator to get the segment from
290 * @return The next segment or NULL if there are no more segments
292 static struct route_graph_segment
293 *rp_iterator_next(struct route_graph_point_iterator *it)
295 struct route_graph_segment *ret;
303 if (ret->start_next) {
304 it->next = ret->start_next;
306 it->next = it->p->end;
310 it->next = ret->end_next;
317 * @brief Checks if the last segment returned from a route_graph_point_iterator comes from the end
319 * @param it The route graph point iterator to be checked
320 * @return 1 if the last segment returned comes from the end of the route graph point, 0 otherwise
323 rp_iterator_end(struct route_graph_point_iterator *it) {
324 if (it->end && (it->next != it->p->end)) {
332 * @brief Destroys a route_path
334 * @param this The route_path to be destroyed
337 route_path_destroy(struct route_path *this)
339 struct route_path_segment *c,*n;
342 if (this->path_hash) {
343 item_hash_destroy(this->path_hash);
344 this->path_hash=NULL;
356 * @brief Creates a completely new route structure
358 * @param attrs Not used
359 * @return The newly created route
362 route_new(struct attr *parent, struct attr **attrs)
364 struct route *this=g_new0(struct route, 1);
365 struct attr dest_attr;
367 if (attr_generic_get_attr(attrs, NULL, attr_destination_distance, &dest_attr, NULL)) {
368 this->destination_distance = dest_attr.u.num;
370 this->destination_distance = 50; // Default value
372 this->cbl=callback_list_new();
378 * @brief Checks if a segment is part of a roundabout
380 * This function checks if a segment is part of a roundabout.
382 * @param seg The segment to be checked
383 * @param level How deep to scan the route graph
384 * @param direction Set this to 1 if we're entering the segment through its end, to 0 otherwise
385 * @param origin Used internally, set to NULL
386 * @return 1 If a roundabout was detected, 0 otherwise
389 route_check_roundabout(struct route_graph_segment *seg, int level, int direction, struct route_graph_segment *origin)
391 struct route_graph_point_iterator it,it2;
392 struct route_graph_segment *cur;
398 if (!direction && !(seg->flags & AF_ONEWAY)) {
401 if (direction && !(seg->flags & AF_ONEWAYREV)) {
410 it = rp_iterator_new(seg->end);
412 it = rp_iterator_new(seg->start);
416 while ((cur = rp_iterator_next(&it2)))
421 cur = rp_iterator_next(&it);
424 cur = rp_iterator_next(&it);
429 seg->flags |= AF_ROUNDABOUT;
433 if (route_check_roundabout(cur, (level-1), rp_iterator_end(&it), origin)) {
434 seg->flags |= AF_ROUNDABOUT;
438 cur = rp_iterator_next(&it);
445 * @brief Sets the mapset of the route passwd
447 * @param this The route to set the mapset for
448 * @param ms The mapset to set for this route
451 route_set_mapset(struct route *this, struct mapset *ms)
457 * @brief Returns the mapset of the route passed
459 * @param this The route to get the mapset of
460 * @return The mapset of the route passed
463 route_get_mapset(struct route *this)
469 * @brief Returns the current position within the route passed
471 * @param this The route to get the position for
472 * @return The position within the route passed
475 route_get_pos(struct route *this)
481 * @brief Returns the destination of the route passed
483 * @param this The route to get the destination for
484 * @return The destination of the route passed
487 route_get_dst(struct route *this)
493 * @brief Returns the speedlist of the route passed
495 * @param this The route to get the speedlist for
496 * @return The speedlist of the route passed
499 route_get_speedlist(struct route *this)
501 return this->speedlist;
505 * @brief Checks if the path is calculated for the route passed
507 * @param this The route to check
508 * @return True if the path is calculated, false if not
511 route_get_path_set(struct route *this)
513 return this->path2 != NULL;
517 * @brief Sets the driving speed for a certain itemtype
519 * @param this The route to set the speed for
520 * @param type The itemtype to set the speed for
521 * @param value The speed that should be set
522 * @return True on success, false if the itemtype does not exist
525 route_set_speed(struct route *this, enum item_type type, int value)
527 if (type < route_item_first || type > route_item_last) {
528 dbg(0,"street type %d out of range [%d,%d]", type, route_item_first, route_item_last);
531 this->speedlist[type-route_item_first]=value;
536 * @brief Checks if the route passed contains a certain item within the route path
538 * This function checks if a certain items exists in the path that navit will guide
539 * the user to his destination. It does *not* check if this item exists in the route
542 * @param this The route to check for this item
543 * @param item The item to search for
544 * @return True if the item was found, false if the item was not found or the route was not calculated
547 route_contains(struct route *this, struct item *item)
549 if (! this->path2 || !this->path2->path_hash)
551 return (int)item_hash_lookup(this->path2->path_hash, item);
555 * @brief Checks if the current position in a route is a certain item
557 * @param this The route to check for this item
558 * @param item The item to search for
559 * @return True if the current position is this item, false otherwise
562 route_pos_contains(struct route *this, struct item *item)
564 if (! this->pos || !this->pos->street)
566 return item_is_equal(this->pos->street->item, *item);
570 * @brief Checks if a route has reached its destination
572 * @param this The route to be checked
573 * @return True if the destination is "reached", false otherwise.
576 route_destination_reached(struct route *this)
578 struct street_data *sd = NULL;
584 sd = this->pos->street;
590 if (!item_is_equal(this->pos->street->item, this->dst->street->item)) {
594 if ((sd->flags & AF_ONEWAY) && (this->pos->lenneg >= this->dst->lenneg)) { // We would have to drive against the one-way road
597 if ((sd->flags & AF_ONEWAYREV) && (this->pos->lenpos >= this->dst->lenpos)) {
600 pro=route_projection(this);
601 if (pro == projection_none)
604 if (transform_distance(pro, &this->pos->c, &this->dst->lp) > this->destination_distance) {
612 route_path_update_done(struct route *this, int new_graph)
614 struct route_path *oldpath=this->path2;
617 this->path2=route_path_new(this->graph, oldpath, this->pos, this->dst, this->speedlist);
618 route_path_destroy(oldpath);
623 val=2+!this->path2->updated;
626 callback_list_call_attr_1(this->cbl, attr_route, (void *)val);
630 * @brief Updates the route graph and the route path if something changed with the route
632 * This will update the route graph and the route path of the route if some of the
633 * route's settings (destination, position) have changed.
635 * @attention For this to work the route graph has to be destroyed if the route's
636 * @attention destination is changed somewhere!
638 * @param this The route to update
641 route_path_update(struct route *this, int cancel)
643 dbg(1,"enter %d\n", cancel);
644 if (! this->pos || ! this->dst) {
646 route_path_destroy(this->path2);
651 route_graph_destroy(this->graph);
654 /* the graph is destroyed when setting the destination */
656 if (this->graph->busy) {
657 dbg(1,"busy building graph\n");
660 // we can try to update
661 dbg(1,"try update\n");
662 route_path_update_done(this, 0);
664 route_path_destroy(this->path2);
667 if (!this->graph || !this->path2) {
668 dbg(1,"rebuild graph\n");
669 if (! this->route_graph_flood_done_cb)
670 this->route_graph_flood_done_cb=callback_new_2(callback_cast(route_path_update_done), this, 1);
671 dbg(1,"route_graph_update\n");
672 route_graph_update(this, this->route_graph_flood_done_cb);
677 * @brief This will calculate all the distances stored in a route_info
679 * @param ri The route_info to calculate the distances for
680 * @param pro The projection used for this route
683 route_info_distances(struct route_info *ri, enum projection pro)
686 struct street_data *sd=ri->street;
687 /* 0 1 2 X 3 4 5 6 pos=2 npos=3 count=7 0,1,2 3,4,5,6*/
688 ri->lenextra=transform_distance(pro, &ri->lp, &ri->c);
689 ri->lenneg=transform_polyline_length(pro, sd->c, npos)+transform_distance(pro, &sd->c[ri->pos], &ri->lp);
690 ri->lenpos=transform_polyline_length(pro, sd->c+npos, sd->count-npos)+transform_distance(pro, &sd->c[npos], &ri->lp);
694 * @brief This sets the current position of the route passed
696 * This will set the current position of the route passed to the street that is nearest to the
697 * passed coordinates. It also automatically updates the route.
699 * @param this The route to set the position of
700 * @param pos Coordinates to set as position
703 route_set_position(struct route *this, struct pcoord *pos)
706 route_info_free(this->pos);
708 this->pos=route_find_nearest_street(this->ms, pos);
709 dbg(1,"this->pos=%p\n", this->pos);
712 route_info_distances(this->pos, pos->pro);
713 route_path_update(this, 0);
717 * @brief Sets a route's current position based on coordinates from tracking
719 * @param this The route to set the current position of
720 * @param tracking The tracking to get the coordinates from
723 route_set_position_from_tracking(struct route *this, struct tracking *tracking)
726 struct route_info *ret;
727 struct street_data *sd;
730 c=tracking_get_pos(tracking);
731 ret=g_new0(struct route_info, 1);
733 printf("%s:Out of memory\n", __FUNCTION__);
737 route_info_free(this->pos);
743 ret->pos=tracking_get_segment_pos(tracking);
744 sd=tracking_get_street_data(tracking);
746 ret->street=street_data_dup(sd);
747 route_info_distances(ret, c->pro);
749 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);
750 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);
753 route_path_update(this, 0);
757 /* Used for debuging of route_rect, what routing sees */
758 struct map_selection *route_selection;
761 * @brief Returns a single map selection
763 struct map_selection *
764 route_rect(int order, struct coord *c1, struct coord *c2, int rel, int abs)
766 int dx,dy,sx=1,sy=1,d,m;
767 struct map_selection *sel=g_new(struct map_selection, 1);
769 printf("%s:Out of memory\n", __FUNCTION__);
773 sel->range.min=route_item_first;
774 sel->range.max=route_item_last;
775 dbg(1,"%p %p\n", c1, c2);
780 sel->u.c_rect.lu.x=c1->x;
781 sel->u.c_rect.rl.x=c2->x;
783 sel->u.c_rect.lu.x=c2->x;
784 sel->u.c_rect.rl.x=c1->x;
788 sel->u.c_rect.lu.y=c2->y;
789 sel->u.c_rect.rl.y=c1->y;
791 sel->u.c_rect.lu.y=c1->y;
792 sel->u.c_rect.rl.y=c2->y;
799 sel->u.c_rect.lu.x-=m;
800 sel->u.c_rect.rl.x+=m;
801 sel->u.c_rect.lu.y+=m;
802 sel->u.c_rect.rl.y-=m;
808 * @brief Returns a list of map selections useable to create a route graph
810 * Returns a list of map selections useable to get a map rect from which items can be
811 * retrieved to build a route graph. The selections are a rectangle with
812 * c1 and c2 as two corners.
814 * @param c1 Corner 1 of the rectangle
815 * @param c2 Corder 2 of the rectangle
817 static struct map_selection *
818 route_calc_selection(struct coord *c1, struct coord *c2)
820 struct map_selection *ret,*sel;
821 sel=route_rect(4, c1, c2, 25, 0);
823 sel->next=route_rect(8, c1, c1, 0, 40000);
825 sel->next=route_rect(18, c1, c1, 0, 10000);
827 sel->next=route_rect(8, c2, c2, 0, 40000);
829 sel->next=route_rect(18, c2, c2, 0, 10000);
830 /* route_selection=ret; */
835 * @brief Destroys a list of map selections
837 * @param sel Start of the list to be destroyed
840 route_free_selection(struct map_selection *sel)
842 struct map_selection *next;
852 * @brief Sets the destination of a route
854 * This sets the destination of a route to the street nearest to the coordinates passed
855 * and updates the route.
857 * @param this The route to set the destination for
858 * @param dst Coordinates to set as destination
861 route_set_destination(struct route *this, struct pcoord *dst)
865 route_info_free(this->dst);
868 this->dst=route_find_nearest_street(this->ms, dst);
870 route_info_distances(this->dst, dst->pro);
872 callback_list_call_attr_1(this->cbl, attr_route, (void *)0);
873 profile(1,"find_nearest_street");
875 /* The graph has to be destroyed and set to NULL, otherwise route_path_update() doesn't work */
876 route_graph_destroy(this->graph);
878 route_path_update(this, 1);
883 * @brief Gets the route_graph_point with the specified coordinates
885 * @param this The route in which to search
886 * @param c Coordinates to search for
887 * @return The point at the specified coordinates or NULL if not found
889 static struct route_graph_point *
890 route_graph_get_point(struct route_graph *this, struct coord *c)
892 struct route_graph_point *p;
893 int hashval=HASHCOORD(c);
894 p=this->hash[hashval];
896 if (p->c.x == c->x && p->c.y == c->y)
904 * @brief Inserts a point into the route graph at the specified coordinates
906 * This will insert a point into the route graph at the coordinates passed in f.
907 * Note that the point is not yet linked to any segments.
909 * @param this The route to insert the point into
910 * @param f The coordinates at which the point should be inserted
911 * @return The point inserted or NULL on failure
913 static struct route_graph_point *
914 route_graph_add_point(struct route_graph *this, struct coord *f)
917 struct route_graph_point *p;
919 p=route_graph_get_point(this,f);
921 hashval=HASHCOORD(f);
923 printf("p (0x%x,0x%x)\n", f->x, f->y);
924 p=g_new(struct route_graph_point,1);
926 printf("%s:Out of memory\n", __FUNCTION__);
929 p->hash_next=this->hash[hashval];
930 this->hash[hashval]=p;
931 p->next=this->route_points;
938 this->route_points=p;
944 * @brief Frees all the memory used for points in the route graph passed
946 * @param this The route graph to delete all points from
949 route_graph_free_points(struct route_graph *this)
951 struct route_graph_point *curr,*next;
952 curr=this->route_points;
958 this->route_points=NULL;
959 memset(this->hash, 0, sizeof(this->hash));
963 * @brief Inserts a new segment into the route graph
965 * This function performs a check if a segment for the item specified already exists, and inserts
966 * a new segment representing this item if it does not.
968 * @param this The route graph to insert the segment into
969 * @param start The graph point which should be connected to the start of this segment
970 * @param end The graph point which should be connected to the end of this segment
971 * @param len The length of this segment
972 * @param item The item that is represented by this segment
973 * @param flags Flags for this segment
974 * @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
975 * @param maxspeed The maximum speed allowed on this segment in km/h. -1 if not known.
978 route_graph_add_segment(struct route_graph *this, struct route_graph_point *start,
979 struct route_graph_point *end, int len, struct item *item,
980 int flags, int offset, int maxspeed)
982 struct route_graph_segment *s;
986 if (item_is_equal(*item, s->item) && (s->offset == offset))
991 s = g_new0(struct route_graph_segment, 1);
993 printf("%s:Out of memory\n", __FUNCTION__);
997 s->start_next=start->start;
1000 s->end_next=end->end;
1002 dbg_assert(len >= 0);
1007 s->maxspeed = maxspeed;
1009 s->next=this->route_segments;
1010 this->route_segments=s;
1012 printf("l (0x%x,0x%x)-(0x%x,0x%x)\n", start->c.x, start->c.y, end->c.x, end->c.y);
1016 * @brief Gets all the coordinates of an item
1018 * This will get all the coordinates of the item i and return them in c,
1019 * up to max coordinates. Additionally it is possible to limit the coordinates
1020 * returned to all the coordinates of the item between the two coordinates
1023 * @important Make shure that whatever c points to has enough memory allocated
1024 * @important to hold max coordinates!
1026 * @param i The item to get the coordinates of
1027 * @param c Pointer to memory allocated for holding the coordinates
1028 * @param max Maximum number of coordinates to return
1029 * @param start First coordinate to get
1030 * @param end Last coordinate to get
1031 * @return The number of coordinates returned
1033 static int get_item_seg_coords(struct item *i, struct coord *c, int max,
1034 struct coord *start, struct coord *end)
1036 struct map_rect *mr;
1040 mr=map_rect_new(i->map, NULL);
1043 item = map_rect_get_item_byid(mr, i->id_hi, i->id_lo);
1045 rc = item_coord_get(item, &c1, 1);
1046 while (rc && (c1.x != start->x || c1.y != start->y)) {
1047 rc = item_coord_get(item, &c1, 1);
1049 while (rc && p < max) {
1051 if (c1.x == end->x && c1.y == end->y)
1053 rc = item_coord_get(item, &c1, 1);
1056 map_rect_destroy(mr);
1061 * @brief Returns and removes one segment from a path
1063 * @param path The path to take the segment from
1064 * @param item The item whose segment to remove
1065 * @param offset Offset of the segment within the item to remove. If the item is not segmented this should be 1.
1066 * @return The segment removed
1068 static struct route_path_segment *
1069 route_extract_segment_from_path(struct route_path *path, struct item *item,
1072 struct route_path_segment *sp = NULL, *s;
1075 if (s->offset == offset && item_is_equal(s->item,*item)) {
1080 path->path = s->next;
1088 item_hash_remove(path->path_hash, item);
1093 * @brief Adds a segment and the end of a path
1095 * @param this The path to add the segment to
1096 * @param segment The segment to add
1099 route_path_add_segment(struct route_path *this, struct route_path_segment *segment)
1103 if (this->path_last)
1104 this->path_last->next=segment;
1105 this->path_last=segment;
1109 * @brief Adds a new item to a path
1111 * This adds a new item to a path, creating a new segment for it. Please note that this function does not check
1112 * if the item passed is segmented - it will create exactly one segment.
1114 * @param this The path to add the item to
1115 * @param item The item to add
1116 * @param len The length of the item
1117 * @param first (Optional) coordinate to add to the start of the item. If none should be added, make this NULL.
1118 * @param c Pointer to count coordinates of the item.
1119 * @param cound Number of coordinates in c
1120 * @param last (Optional) coordinate to add to the end of the item. If none should be added, make this NULL.
1121 * @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"
1122 * @param maxspeed The maximum allowed speed on this item in km/h. -1 if not known.
1125 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, int maxspeed)
1127 int i,idx=0,ccount=count + (first ? 1:0) + (last ? 1:0);
1128 struct route_path_segment *segment;
1130 segment=g_malloc0(sizeof(*segment) + sizeof(struct coord) * ccount);
1131 segment->ncoords=ccount;
1132 segment->direction=dir;
1134 segment->c[idx++]=*first;
1136 for (i = 0 ; i < count ; i++)
1137 segment->c[idx++]=c[i];
1139 for (i = 0 ; i < count ; i++)
1140 segment->c[idx++]=c[count-i-1];
1143 segment->maxspeed=maxspeed;
1146 segment->c[idx++]=*last;
1147 segment->length=len;
1149 segment->item=*item;
1150 route_path_add_segment(this, segment);
1154 * @brief Inserts a new item into the path
1156 * This function does almost the same as "route_apth_add_item()", but identifies
1157 * the item to add by a segment from the route graph. Another difference is that it "copies" the
1158 * segment from the route graph, i.e. if the item is segmented, only the segment passed in rgs will
1159 * be added to the route path, not all segments of the item.
1161 * The function can be sped up by passing an old path already containing this segment in oldpath -
1162 * the segment will then be extracted from this old path. Please note that in this case the direction
1163 * parameter has no effect.
1165 * @param this The path to add the item to
1166 * @param oldpath Old path containing the segment to be added. Speeds up the function, but can be NULL.
1167 * @param rgs Segment of the route graph that should be "copied" to the route path
1168 * @param len Length of the item to be added
1169 * @param offset Offset of rgs within the item it represents
1170 * @param dir Order in which to add the coordinates. See route_path_add_item()
1171 * @param straight Indicates if this segment is being entered "straight". See route_check_straight().
1174 route_path_add_item_from_graph(struct route_path *this, struct route_path *oldpath,
1175 struct route_graph_segment *rgs, int len, int offset, int dir, int straight)
1177 struct route_path_segment *segment;
1178 int i,ccnt = 0, ret=1;
1179 struct coord ca[2048];
1182 ccnt = (int)item_hash_lookup(oldpath->path_hash, &rgs->item);
1184 segment = route_extract_segment_from_path(oldpath,
1185 &rgs->item, offset);
1192 ccnt = get_item_seg_coords(&rgs->item, ca, 2047, &rgs->start->c, &rgs->end->c);
1193 segment= g_malloc0(sizeof(*segment) + sizeof(struct coord) * ccnt);
1194 segment->direction=dir;
1196 for (i = 0 ; i < ccnt ; i++)
1197 segment->c[i]=ca[i];
1199 for (i = 0 ; i < ccnt ; i++)
1200 segment->c[i]=ca[ccnt-i-1];
1202 segment->ncoords = ccnt;
1204 /* We check if the route graph segment is part of a roundabout here, because this
1205 * only matters for route graph segments which form parts of the route path */
1206 if (!(rgs->flags & AF_ROUNDABOUT)) { // We identified this roundabout earlier
1207 route_check_roundabout(rgs, 13, (dir < 1), NULL);
1211 segment->item=rgs->item;
1212 segment->maxspeed = rgs->maxspeed;
1213 segment->offset = offset;
1215 segment->length=len;
1217 item_hash_insert(this->path_hash, &rgs->item, (void *)ccnt);
1219 route_path_add_segment(this, segment);
1225 * @brief Destroys all segments of a route graph
1227 * @param this The graph to destroy all segments from
1230 route_graph_free_segments(struct route_graph *this)
1232 struct route_graph_segment *curr,*next;
1233 curr=this->route_segments;
1239 this->route_segments=NULL;
1243 * @brief Destroys a route graph
1245 * @param this The route graph to be destroyed
1248 route_graph_destroy(struct route_graph *this)
1251 route_graph_build_done(this, 1);
1252 route_graph_free_points(this);
1253 route_graph_free_segments(this);
1259 * @brief Returns the time needed to drive len on item
1261 * This function returns the time needed to drive len meters on
1262 * the item passed in item in tenth of seconds.
1264 * @param speedlist The speedlist that should be used
1265 * @param item The item to be driven on
1266 * @param len The length to drive
1267 * @param maxspeed The maximum allowed speed on this item, -1 if not known
1268 * @return The time needed to drive len on item in thenth of senconds
1271 route_time(int *speedlist, struct item *item, int len, int maxspeed)
1273 if (item->type < route_item_first || item->type > route_item_last) {
1274 dbg(0,"street type %d out of range [%d,%d]\n", item->type, route_item_first, route_item_last);
1277 if (!speedlist[item->type-route_item_first] && maxspeed <= 0) {
1278 dbg(0,"street type %d speed is zero\n", item->type);
1282 if (maxspeed <= 0) {
1283 return len*36/speedlist[item->type-route_item_first];
1285 return len*36/maxspeed;
1290 * @brief Returns the "costs" of driving len on item
1292 * @param speedlist The speedlist that should be used
1293 * @param item The item to be driven on
1294 * @param len The length to drive
1295 * @param maxspeed The maximum allowed speed on this item, -1 if not known
1296 * @return The "costs" needed to drive len on item
1299 route_value(int *speedlist, struct item *item, int len, int maxspeed)
1303 printf("len=%d\n", len);
1305 dbg_assert(len >= 0);
1306 ret=route_time(speedlist, item, len, maxspeed);
1307 dbg(1, "route_value(0x%x, %d)=%d\n", item->type, len, ret);
1312 * @brief Adds an item to the route graph
1314 * This adds an item (e.g. a street) to the route graph, creating as many segments as needed for a
1317 * @param this The route graph to add to
1318 * @param item The item to add
1321 route_process_street_graph(struct route_graph *this, struct item *item)
1328 struct route_graph_point *s_pnt,*e_pnt;
1330 struct attr flags_attr, maxspeed_attr;
1336 if (item_coord_get(item, &l, 1)) {
1337 if (item_attr_get(item, attr_flags, &flags_attr)) {
1338 flags = flags_attr.u.num;
1339 if (flags & AF_SEGMENTED)
1343 if (flags & AF_SPEED_LIMIT) {
1344 if (item_attr_get(item, attr_maxspeed, &maxspeed_attr)) {
1345 maxspeed = maxspeed_attr.u.num;
1349 s_pnt=route_graph_add_point(this,&l);
1351 while (item_coord_get(item, &c, 1)) {
1352 len+=transform_distance(map_projection(item->map), &l, &c);
1355 e_pnt=route_graph_add_point(this,&l);
1356 dbg_assert(len >= 0);
1357 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset, maxspeed);
1362 isseg = item_coord_is_node(item);
1363 rc = item_coord_get(item, &c, 1);
1365 len+=transform_distance(map_projection(item->map), &l, &c);
1368 e_pnt=route_graph_add_point(this,&l);
1369 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset, maxspeed);
1371 s_pnt=route_graph_add_point(this,&l);
1376 e_pnt=route_graph_add_point(this,&l);
1377 dbg_assert(len >= 0);
1379 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset, maxspeed);
1385 * @brief Compares the costs of reaching the destination from two points on
1387 * @important Do not pass anything other than route_graph_points in v1 and v2!
1391 * @return The additional costs of v1 compared to v2 (may be negative)
1394 compare(void *v1, void *v2)
1396 struct route_graph_point *p1=v1;
1397 struct route_graph_point *p2=v2;
1400 printf("compare %d (%p) vs %d (%p)\n", p1->value,p1,p2->value,p2);
1402 return p1->value-p2->value;
1406 * @brief Calculates the routing costs for each point
1408 * This function is the heart of routing. It assigns each point in the route graph a
1409 * cost at which one can reach the destination from this point on. Additionally it assigns
1410 * each point a segment one should follow from this point on to reach the destination at the
1413 * This function uses Dijkstra's algorithm to do the routing. To understand it you should have a look
1414 * at this algorithm.
1417 route_graph_flood(struct route_graph *this, struct route_info *dst, int *speedlist, struct callback *cb)
1419 struct route_graph_point *p_min,*end=NULL;
1420 struct route_graph_segment *s;
1421 int min,new,old,val;
1422 struct fibheap *heap; /* This heap will hold all points with "temporarily" calculated costs */
1423 struct street_data *sd=dst->street;
1425 heap = fh_makeheap();
1426 fh_setcmp(heap, compare);
1428 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 */
1429 end=route_graph_get_point(this, &sd->c[0]);
1430 dbg_assert(end != 0);
1431 end->value=route_value(speedlist, &sd->item, dst->lenneg, sd->maxspeed);
1432 end->el=fh_insert(heap, end);
1435 if (! (sd->flags & AF_ONEWAY)) { /* If we may drive against the direction of the coordinates, the last coordinate is another starting point */
1436 end=route_graph_get_point(this, &sd->c[sd->count-1]);
1437 dbg_assert(end != 0);
1438 end->value=route_value(speedlist, &sd->item, dst->lenpos, sd->maxspeed);
1439 end->el=fh_insert(heap, end);
1442 dbg(1,"0x%x,0x%x\n", end->c.x, end->c.y);
1444 p_min=fh_extractmin(heap); /* Starting Dijkstra by selecting the point with the minimum costs on the heap */
1445 if (! p_min) /* There are no more points with temporarily calculated costs, Dijkstra has finished */
1449 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);
1450 p_min->el=NULL; /* This point is permanently calculated now, we've taken it out of the heap */
1452 while (s) { /* Iterating all the segments leading away from our point to update the points at their ends */
1453 val=route_value(speedlist, &s->item, s->len, s->maxspeed);
1455 val+=val*2*street_route_contained(s->str->segid);
1459 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);
1460 if (new < s->end->value && !(s->flags & AF_ONEWAY)) { /* We've found a less costly way to reach the end of s, update it */
1465 printf("insert_end p=%p el=%p val=%d ", s->end, s->end->el, s->end->value);
1466 s->end->el=fh_insert(heap, s->end);
1468 printf("el new=%p\n", s->end->el);
1472 printf("replace_end p=%p el=%p val=%d\n", s->end, s->end->el, s->end->value);
1473 fh_replacedata(heap, s->end->el, s->end);
1481 while (s) { /* Doing the same as above with the segments leading towards our point */
1482 val=route_value(speedlist, &s->item, s->len, s->maxspeed);
1485 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);
1486 if (new < s->start->value && !(s->flags & AF_ONEWAYREV)) {
1487 old=s->start->value;
1488 s->start->value=new;
1490 if (! s->start->el) {
1492 printf("insert_start p=%p el=%p val=%d ", s->start, s->start->el, s->start->value);
1493 s->start->el=fh_insert(heap, s->start);
1495 printf("el new=%p\n", s->start->el);
1499 printf("replace_start p=%p el=%p val=%d\n", s->start, s->start->el, s->start->value);
1500 fh_replacedata(heap, s->start->el, s->start);
1508 fh_deleteheap(heap);
1509 callback_call_0(cb);
1513 * @brief Starts an "offroad" path
1515 * This starts a path that is not located on a street. It creates a new route path
1516 * adding only one segment, that leads from pos to dest, and which is not associated with an item.
1518 * @param this Not used
1519 * @param pos The starting position for the new path
1520 * @param dst The destination of the new path
1521 * @param dir Not used
1522 * @return The new path
1524 static struct route_path *
1525 route_path_new_offroad(struct route_graph *this, struct route_info *pos, struct route_info *dst, int dir)
1527 struct route_path *ret;
1529 ret=g_new0(struct route_path, 1);
1530 ret->path_hash=item_hash_new();
1531 route_path_add_item(ret, NULL, pos->lenextra+dst->lenextra, &pos->c, NULL, 0, &dst->c, 1, -1);
1538 * @brief Creates a new "trivial" route
1540 * This function creates a new "trivial" route. A trivial route is a route that starts and ends on the same street,
1541 * so there is no routing needed. Depending on pos and dst it can optionally add some "offroad" part to the route.
1543 * @param this The route graph to place the route on
1544 * @param pos The starting position for the new path
1545 * @param dst The destination of the new path
1546 * @param dir Direction of the coordinates to be added
1547 * @return The new path
1549 static struct route_path *
1550 route_path_new_trivial(struct route_graph *this, struct route_info *pos, struct route_info *dst, int dir)
1552 struct street_data *sd=pos->street;
1553 struct route_path *ret;
1556 if (pos->lenextra + dst->lenextra + pos->lenneg-dst->lenneg > transform_distance(map_projection(sd->item.map), &pos->c, &dst->c))
1557 return route_path_new_offroad(this, pos, dst, dir);
1559 if (pos->lenextra + dst->lenextra + pos->lenpos-dst->lenpos > transform_distance(map_projection(sd->item.map), &pos->c, &dst->c))
1560 return route_path_new_offroad(this, pos, dst, dir);
1562 ret=g_new0(struct route_path, 1);
1563 ret->path_hash=item_hash_new();
1565 route_path_add_item(ret, NULL, pos->lenextra, &pos->c, NULL, 0, &pos->lp, 1, -1);
1567 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, sd->maxspeed);
1569 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, sd->maxspeed);
1571 route_path_add_item(ret, NULL, dst->lenextra, &dst->lp, NULL, 0, &dst->c, 1, -1);
1577 * @brief Returns a coordinate at a given distance
1579 * This function returns the coordinate, where the user will be if he
1580 * follows the current route for a certain distance.
1582 * @param this_ The route we're driving upon
1583 * @param dist The distance in meters
1584 * @return The coordinate where the user will be in that distance
1587 route_get_coord_dist(struct route *this_, int dist)
1592 struct route_path_segment *cur;
1594 enum projection pro=route_projection(this_);
1598 if (!this_->path2 || pro == projection_none) {
1599 return this_->pos->c;
1602 ret = this_->pos->c;
1603 cur = this_->path2->path;
1605 if (cur->length < d) {
1608 for (i=0; i < (cur->ncoords-1); i++) {
1610 len = (int)transform_polyline_length(pro, (cur->c + i), 2);
1613 // We interpolate a bit here...
1614 frac = (double)l / len;
1616 dx = (cur->c + i + 1)->x - (cur->c + i)->x;
1617 dy = (cur->c + i + 1)->y - (cur->c + i)->y;
1619 ret.x = (cur->c + i)->x + (frac * dx);
1620 ret.y = (cur->c + i)->y + (frac * dy);
1624 return cur->c[(cur->ncoords-1)];
1629 return this_->dst->c;
1633 * @brief Creates a new route path
1635 * This creates a new non-trivial route. It therefore needs the routing information created by route_graph_flood, so
1636 * make shure to run route_graph_flood() after changing the destination before using this function.
1638 * @param this The route graph to create the route from
1639 * @param oldpath (Optional) old path which may contain parts of the new part - this speeds things up a bit. May be NULL.
1640 * @param pos The starting position of the route
1641 * @param dst The destination of the route
1642 * @param speedlist The speedlist to use
1643 * @return The new route path
1645 static struct route_path *
1646 route_path_new(struct route_graph *this, struct route_path *oldpath, struct route_info *pos, struct route_info *dst, int *speedlist)
1648 struct route_graph_point *start1=NULL,*start2=NULL,*start;
1649 struct route_graph_segment *s=NULL;
1650 struct route_graph_segment *lastseg = NULL;
1655 int time=0,hr,min,sec
1657 unsigned int val1=0xffffffff,val2=0xffffffff;
1658 struct street_data *sd=pos->street;
1659 struct route_path *ret;
1661 if (! pos->street || ! dst->street)
1663 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 */
1664 if (!(sd->flags & AF_ONEWAY) && pos->lenneg >= dst->lenneg) {
1665 return route_path_new_trivial(this, pos, dst, -1);
1667 if (!(sd->flags & AF_ONEWAYREV) && pos->lenpos >= dst->lenpos) {
1668 return route_path_new_trivial(this, pos, dst, 1);
1671 if (! (sd->flags & AF_ONEWAY)) { /* Using the start of the current segment as one starting point */
1672 start1=route_graph_get_point(this, &sd->c[0]);
1675 val1=start1->value+route_value(speedlist, &sd->item, pos->lenneg, sd->maxspeed);
1676 dbg(1,"start1: %d(route)+%d=%d\n", start1->value, val1-start1->value, val1);
1678 if (! (sd->flags & AF_ONEWAYREV)) { /* Using the start of the current segment as an alternative starting point */
1679 start2=route_graph_get_point(this, &sd->c[sd->count-1]);
1682 val2=start2->value+route_value(speedlist, &sd->item, pos->lenpos, sd->maxspeed);
1683 dbg(1,"start2: %d(route)+%d=%d\n", start2->value, val2-start2->value, val2);
1685 dbg(1,"val1=%d val2=%d\n", val1, val2);
1687 val1=start1->start->start->value;
1688 val2=start2->end->end->value;
1690 ret=g_new0(struct route_path, 1);
1693 route_path_add_item(ret, NULL, pos->lenextra, &pos->c, NULL, 0, &pos->lp, 1, -1);
1694 if (start1 && (val1 < val2)) {
1696 route_path_add_item(ret, &sd->item, pos->lenneg, &pos->lp, sd->c, pos->pos+1, NULL, -1, sd->maxspeed);
1700 route_path_add_item(ret, &sd->item, pos->lenpos, &pos->lp, sd->c+pos->pos+1, sd->count-pos->pos-1, NULL, 1, sd->maxspeed);
1702 printf("no route found, pos blocked\n");
1706 ret->path_hash=item_hash_new();
1707 while ((s=start->seg)) { /* following start->seg, which indicates the least costly way to reach our destination */
1710 printf("start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
1715 if (s->start == start) {
1716 if (!route_path_add_item_from_graph(ret, oldpath, s, seg_len, s->offset, 1, is_straight))
1720 if (!route_path_add_item_from_graph(ret, oldpath, s, seg_len, s->offset, -1, is_straight))
1728 dbg(1,"start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
1729 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);
1730 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 */
1731 route_path_add_item(ret, &sd->item, dst->lenneg, NULL, sd->c, dst->pos+1, &dst->lp, 1, sd->maxspeed);
1732 } else if (start->c.x == sd->c[sd->count-1].x && start->c.y == sd->c[sd->count-1].y) {
1733 route_path_add_item(ret, &sd->item, dst->lenpos, NULL, sd->c+dst->pos+1, sd->count-dst->pos-1, &dst->lp, -1, sd->maxspeed);
1735 printf("no route found\n");
1736 route_path_destroy(ret);
1740 route_path_add_item(ret, NULL, dst->lenextra, &dst->lp, NULL, 0, &dst->c, 1, -1);
1741 dbg(1, "%d segments\n", segs);
1746 route_graph_build_next_map(struct route_graph *rg)
1749 rg->m=mapset_next(rg->h, 1);
1752 map_rect_destroy(rg->mr);
1753 rg->mr=map_rect_new(rg->m, rg->sel);
1760 route_graph_build_done(struct route_graph *rg, int cancel)
1762 dbg(1,"cancel=%d\n",cancel);
1763 event_remove_idle(rg->idle_ev);
1764 callback_destroy(rg->idle_cb);
1765 map_rect_destroy(rg->mr);
1766 mapset_close(rg->h);
1767 route_free_selection(rg->sel);
1774 callback_call_0(rg->done_cb);
1779 route_graph_build_idle(struct route_graph *rg)
1786 item=map_rect_get_item(rg->mr);
1789 if (!route_graph_build_next_map(rg)) {
1790 route_graph_build_done(rg, 0);
1794 if (item->type >= type_street_0 && item->type <= type_ferry)
1795 route_process_street_graph(rg, item);
1801 * @brief Builds a new route graph from a mapset
1803 * This function builds a new route graph from a map. Please note that this function does not
1804 * add any routing information to the route graph - this has to be done via the route_graph_flood()
1807 * The function does not create a graph covering the whole map, but only covering the rectangle
1808 * between c1 and c2.
1810 * @param ms The mapset to build the route graph from
1811 * @param c1 Corner 1 of the rectangle to use from the map
1812 * @param c2 Corner 2 of the rectangle to use from the map
1813 * @param done_cb The callback which will be called when graph is complete
1814 * @return The new route graph.
1816 static struct route_graph *
1817 route_graph_build(struct mapset *ms, struct coord *c1, struct coord *c2, struct callback *done_cb)
1819 struct route_graph *ret=g_new0(struct route_graph, 1);
1823 ret->sel=route_calc_selection(c1, c2);
1824 ret->h=mapset_open(ms);
1825 ret->done_cb=done_cb;
1827 if (route_graph_build_next_map(ret)) {
1828 ret->idle_cb=callback_new_1(callback_cast(route_graph_build_idle), ret);
1829 ret->idle_ev=event_add_idle(50, ret->idle_cb);
1831 route_graph_build_done(ret, 0);
1837 route_graph_update_done(struct route *this, struct callback *cb)
1839 route_graph_flood(this->graph, this->dst, this->speedlist, cb);
1843 * @brief Updates the route graph
1845 * This updates the route graph after settings in the route have changed. It also
1846 * adds routing information afterwards by calling route_graph_flood().
1848 * @param this The route to update the graph for
1851 route_graph_update(struct route *this, struct callback *cb)
1853 route_graph_destroy(this->graph);
1854 callback_destroy(this->route_graph_done_cb);
1855 this->route_graph_done_cb=callback_new_2(callback_cast(route_graph_update_done), this, cb);
1856 callback_list_call_attr_1(this->cbl, attr_route, (void *)0);
1857 this->graph=route_graph_build(this->ms, &this->pos->c, &this->dst->c, this->route_graph_done_cb);
1861 * @brief Gets street data for an item
1863 * @param item The item to get the data for
1864 * @return Street data for the item
1866 struct street_data *
1867 street_get_data (struct item *item)
1870 struct street_data *ret = NULL, *ret1;
1871 struct attr flags_attr, maxspeed_attr;
1872 const int step = 128;
1876 ret1=g_realloc(ret, sizeof(struct street_data)+(count+step)*sizeof(struct coord));
1883 c = item_coord_get(item, &ret->c[count], step);
1885 } while (c && c == step);
1887 ret1=g_realloc(ret, sizeof(struct street_data)+count*sizeof(struct coord));
1892 if (item_attr_get(item, attr_flags, &flags_attr))
1893 ret->flags=flags_attr.u.num;
1898 if (ret->flags & AF_SPEED_LIMIT) {
1899 if (item_attr_get(item, attr_maxspeed, &maxspeed_attr)) {
1900 ret->maxspeed = maxspeed_attr.u.num;
1908 * @brief Copies street data
1910 * @param orig The street data to copy
1911 * @return The copied street data
1913 struct street_data *
1914 street_data_dup(struct street_data *orig)
1916 struct street_data *ret;
1917 int size=sizeof(struct street_data)+orig->count*sizeof(struct coord);
1920 memcpy(ret, orig, size);
1926 * @brief Frees street data
1928 * @param sd Street data to be freed
1931 street_data_free(struct street_data *sd)
1937 * @brief Finds the nearest street to a given coordinate
1939 * @param ms The mapset to search in for the street
1940 * @param pc The coordinate to find a street nearby
1941 * @return The nearest street
1943 static struct route_info *
1944 route_find_nearest_street(struct mapset *ms, struct pcoord *pc)
1946 struct route_info *ret=NULL;
1948 struct map_selection *sel;
1949 int dist,mindist=0,pos;
1950 struct mapset_handle *h;
1952 struct map_rect *mr;
1955 struct street_data *sd;
1959 ret=g_new0(struct route_info, 1);
1961 dbg(0,"Out of memory\n");
1967 while ((m=mapset_next(h,1))) {
1970 if (map_projection(m) != pc->pro) {
1971 transform_to_geo(pc->pro, &c, &g);
1972 transform_from_geo(map_projection(m), &g, &c);
1974 sel = route_rect(18, &c, &c, 0, max_dist);
1977 mr=map_rect_new(m, sel);
1979 map_selection_destroy(sel);
1982 while ((item=map_rect_get_item(mr))) {
1983 if (item->type >= type_street_0 && item->type <= type_ferry) {
1984 sd=street_get_data(item);
1987 dist=transform_distance_polyline_sq(sd->c, sd->count, &c, &lp, &pos);
1988 if (dist < mindist) {
1991 street_data_free(ret->street);
1997 dbg(1,"dist=%d id 0x%x 0x%x pos=%d\n", dist, item->id_hi, item->id_lo, pos);
1999 street_data_free(sd);
2003 map_selection_destroy(sel);
2004 map_rect_destroy(mr);
2008 if (!ret->street || mindist > max_dist*max_dist) {
2010 street_data_free(ret->street);
2011 dbg(1,"Much too far %d > %d\n", mindist, max_dist);
2021 * @brief Destroys a route_info
2023 * @param info The route info to be destroyed
2026 route_info_free(struct route_info *inf)
2029 street_data_free(inf->street);
2037 * @brief Returns street data for a route info
2039 * @param rinf The route info to return the street data for
2040 * @return Street data for the route info
2042 struct street_data *
2043 route_info_street(struct route_info *rinf)
2045 return rinf->street;
2049 struct route_crossings *
2050 route_crossings_get(struct route *this, struct coord *c)
2052 struct route_point *pnt;
2053 struct route_segment *seg;
2055 struct route_crossings *ret;
2057 pnt=route_graph_get_point(this, c);
2060 printf("start: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
2062 seg=seg->start_next;
2066 printf("end: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
2070 ret=g_malloc(sizeof(struct route_crossings)+crossings*sizeof(struct route_crossing));
2071 ret->count=crossings;
2077 struct map_rect_priv {
2078 struct route_info_handle *ri;
2079 enum attr_type attr_next;
2081 struct map_priv *mpriv;
2084 unsigned int last_coord;
2085 struct route_path_segment *seg,*seg_next;
2086 struct route_graph_point *point;
2087 struct route_graph_segment *rseg;
2089 struct coord *coord_sel; /**< Set this to a coordinate if you want to filter for just a single route graph point */
2090 struct route_graph_point_iterator it;
2094 rm_coord_rewind(void *priv_data)
2096 struct map_rect_priv *mr = priv_data;
2101 rm_attr_rewind(void *priv_data)
2103 struct map_rect_priv *mr = priv_data;
2104 mr->attr_next = attr_street_item;
2108 rm_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
2110 struct map_rect_priv *mr = priv_data;
2111 struct route_path_segment *seg=mr->seg;
2112 struct route *route=mr->mpriv->route;
2113 if (mr->item.type != type_street_route)
2115 attr->type=attr_type;
2116 switch (attr_type) {
2118 while (mr->attr_next != attr_none) {
2119 if (rm_attr_get(priv_data, mr->attr_next, attr))
2124 mr->attr_next = attr_street_item;
2126 attr->u.num = seg->maxspeed;
2131 case attr_street_item:
2132 mr->attr_next=attr_direction;
2133 if (seg && seg->item.map)
2134 attr->u.item=&seg->item;
2138 case attr_direction:
2139 mr->attr_next=attr_route;
2141 attr->u.num=seg->direction;
2146 mr->attr_next=attr_length;
2147 attr->u.route = mr->mpriv->route;
2151 attr->u.num=seg->length;
2153 attr->u.num=mr->length;
2154 mr->attr_next=attr_time;
2157 mr->attr_next=attr_none;
2159 attr->u.num=route_time(route->speedlist, &seg->item, seg->length, seg->maxspeed);
2164 mr->attr_next=attr_none;
2167 mr->attr_next=attr_none;
2168 attr->type=attr_none;
2175 rm_coord_get(void *priv_data, struct coord *c, int count)
2177 struct map_rect_priv *mr = priv_data;
2178 struct route_path_segment *seg = mr->seg;
2180 struct route *r = mr->mpriv->route;
2181 enum projection pro = route_projection(r);
2183 if (pro == projection_none)
2185 if (mr->item.type == type_route_start || mr->item.type == type_route_end) {
2186 if (! count || mr->last_coord)
2189 if (mr->item.type == type_route_start)
2197 for (i=0; i < count; i++) {
2198 if (mr->last_coord >= seg->ncoords)
2200 if (i >= seg->ncoords)
2202 if (pro != projection_mg)
2203 transform_from_to(&seg->c[mr->last_coord++], pro,
2204 &c[i],projection_mg);
2206 c[i] = seg->c[mr->last_coord++];
2209 dbg(1,"return %d\n",rc);
2213 static struct item_methods methods_route_item = {
2221 rp_attr_rewind(void *priv_data)
2223 struct map_rect_priv *mr = priv_data;
2224 mr->attr_next = attr_label;
2228 rp_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
2230 struct map_rect_priv *mr = priv_data;
2231 struct route_graph_point *p = mr->point;
2232 struct route_graph_segment *seg = mr->rseg;
2233 switch (attr_type) {
2234 case attr_any: // works only with rg_points for now
2235 if (mr->item.type != type_rg_point)
2237 while (mr->attr_next != attr_none) {
2238 if (rp_attr_get(priv_data, mr->attr_next, attr))
2243 mr->attr_next = attr_label;
2244 if (mr->item.type != type_rg_segment)
2247 attr->u.num = seg->maxspeed;
2253 if (mr->item.type != type_rg_point)
2255 attr->type = attr_label;
2258 if (p->value != INT_MAX)
2259 mr->str=g_strdup_printf("%d", p->value);
2261 mr->str=g_strdup("-");
2262 attr->u.str = mr->str;
2263 mr->attr_next=attr_none;
2265 case attr_street_item:
2266 if (mr->item.type != type_rg_segment)
2268 mr->attr_next=attr_none;
2269 if (seg && seg->item.map)
2270 attr->u.item=&seg->item;
2275 if (mr->item.type != type_rg_segment)
2277 mr->attr_next = attr_none;
2279 attr->u.num = seg->flags;
2284 case attr_direction:
2285 // This only works if the map has been opened at a single point, and in that case indicates if the
2286 // segment returned last is connected to this point via its start (1) or its end (-1)
2287 if (!mr->coord_sel || (mr->item.type != type_rg_segment))
2289 if (seg->start == mr->point) {
2291 } else if (seg->end == mr->point) {
2298 if (mr->item.type != type_rg_point)
2300 attr->type = attr_debug;
2303 mr->str=g_strdup_printf("x=%d y=%d", p->c.x, p->c.y);
2304 attr->u.str = mr->str;
2305 mr->attr_next=attr_none;
2308 mr->attr_next=attr_none;
2309 attr->type=attr_none;
2315 * @brief Returns the coordinates of a route graph item
2317 * @param priv_data The route graph item's private data
2318 * @param c Pointer where to store the coordinates
2319 * @param count How many coordinates to get at a max?
2320 * @return The number of coordinates retrieved
2323 rp_coord_get(void *priv_data, struct coord *c, int count)
2325 struct map_rect_priv *mr = priv_data;
2326 struct route_graph_point *p = mr->point;
2327 struct route_graph_segment *seg = mr->rseg;
2329 struct route *r = mr->mpriv->route;
2330 enum projection pro = route_projection(r);
2332 if (pro == projection_none)
2334 for (i=0; i < count; i++) {
2335 if (mr->item.type == type_rg_point) {
2336 if (mr->last_coord >= 1)
2338 if (pro != projection_mg)
2339 transform_from_to(&p->c, pro,
2340 &c[i],projection_mg);
2344 if (mr->last_coord >= 2)
2347 if (seg->end->seg == seg)
2352 if (pro != projection_mg)
2353 transform_from_to(&seg->end->c, pro,
2354 &c[i],projection_mg);
2358 if (pro != projection_mg)
2359 transform_from_to(&seg->start->c, pro,
2360 &c[i],projection_mg);
2362 c[i] = seg->start->c;
2371 static struct item_methods methods_point_item = {
2379 rp_destroy(struct map_priv *priv)
2385 rm_destroy(struct map_priv *priv)
2390 static struct map_rect_priv *
2391 rm_rect_new(struct map_priv *priv, struct map_selection *sel)
2393 struct map_rect_priv * mr;
2395 if (! route_get_pos(priv->route))
2397 if (! route_get_dst(priv->route))
2400 if (! priv->route->path2)
2403 mr=g_new0(struct map_rect_priv, 1);
2405 mr->item.priv_data = mr;
2406 mr->item.type = type_none;
2407 mr->item.meth = &methods_route_item;
2408 if (priv->route->path2)
2409 mr->seg_next=priv->route->path2->path;
2416 * @brief Opens a new map rectangle on the route graph's map
2418 * This function opens a new map rectangle on the route graph's map.
2419 * The "sel" parameter enables you to only search for a single route graph
2420 * point on this map (or exactly: open a map rectangle that only contains
2421 * this one point). To do this, pass here a single map selection, whose
2422 * c_rect has both coordinates set to the same point. Otherwise this parameter
2425 * @param priv The route graph map's private data
2426 * @param sel Here it's possible to specify a point for which to search. Please read the function's description.
2427 * @return A new map rect's private data
2429 static struct map_rect_priv *
2430 rp_rect_new(struct map_priv *priv, struct map_selection *sel)
2432 struct map_rect_priv * mr;
2435 if (! priv->route->graph || ! priv->route->graph->route_points)
2437 mr=g_new0(struct map_rect_priv, 1);
2439 mr->item.priv_data = mr;
2440 mr->item.type = type_rg_point;
2441 mr->item.meth = &methods_point_item;
2443 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)) {
2444 mr->coord_sel = g_malloc(sizeof(struct coord));
2445 *(mr->coord_sel) = sel->u.c_rect.lu;
2452 rm_rect_destroy(struct map_rect_priv *mr)
2456 if (mr->coord_sel) {
2457 g_free(mr->coord_sel);
2463 static struct item *
2464 rp_get_item(struct map_rect_priv *mr)
2466 struct route *r = mr->mpriv->route;
2467 struct route_graph_point *p = mr->point;
2468 struct route_graph_segment *seg = mr->rseg;
2470 if (mr->item.type == type_rg_point) {
2471 if (mr->coord_sel) {
2472 // We are supposed to return only the point at one specified coordinate...
2474 p = r->graph->hash[HASHCOORD(mr->coord_sel)];
2475 while ((p) && ((p->c.x != mr->coord_sel->x) || (p->c.y != mr->coord_sel->y))) {
2478 if ((!p) || !((p->c.x == mr->coord_sel->x) && (p->c.y == mr->coord_sel->y))) {
2479 mr->point = NULL; // This indicates that no point has been found
2481 mr->it = rp_iterator_new(p);
2488 p = r->graph->route_points;
2495 rm_coord_rewind(mr);
2499 mr->item.type = type_rg_segment;
2502 if (mr->coord_sel) {
2503 if (!mr->point) { // This means that no point has been found
2506 seg = rp_iterator_next(&(mr->it));
2509 seg=r->graph->route_segments;
2517 rm_coord_rewind(mr);
2525 static struct item *
2526 rp_get_item_byid(struct map_rect_priv *mr, int id_hi, int id_lo)
2528 struct item *ret=NULL;
2530 ret=rp_get_item(mr);
2535 static struct item *
2536 rm_get_item(struct map_rect_priv *mr)
2538 dbg(1,"enter\n", mr->pos);
2540 switch (mr->item.type) {
2542 mr->item.type=type_route_start;
2543 if (mr->mpriv->route->pos)
2546 mr->item.type=type_street_route;
2547 mr->seg=mr->seg_next;
2549 mr->seg_next=mr->seg->next;
2552 mr->item.type=type_route_end;
2553 if (mr->mpriv->route->dst)
2555 case type_route_end:
2564 static struct item *
2565 rm_get_item_byid(struct map_rect_priv *mr, int id_hi, int id_lo)
2567 struct item *ret=NULL;
2569 ret=rm_get_item(mr);
2573 static struct map_methods route_meth = {
2586 static struct map_methods route_graph_meth = {
2600 route_toggle_routegraph_display(struct route *route)
2602 if (route->flags & RF_SHOWGRAPH) {
2603 route->flags &= ~RF_SHOWGRAPH;
2605 route->flags |= RF_SHOWGRAPH;
2609 static struct map_priv *
2610 route_map_new_helper(struct map_methods *meth, struct attr **attrs, int graph)
2612 struct map_priv *ret;
2613 struct attr *route_attr;
2615 route_attr=attr_search(attrs, NULL, attr_route);
2618 ret=g_new0(struct map_priv, 1);
2620 *meth=route_graph_meth;
2623 ret->route=route_attr->u.route;
2628 static struct map_priv *
2629 route_map_new(struct map_methods *meth, struct attr **attrs)
2631 return route_map_new_helper(meth, attrs, 0);
2634 static struct map_priv *
2635 route_graph_map_new(struct map_methods *meth, struct attr **attrs)
2637 return route_map_new_helper(meth, attrs, 1);
2641 route_get_map_helper(struct route *this_, struct map **map, char *type, char *description)
2644 *map=map_new(NULL, (struct attr*[]){
2645 &(struct attr){attr_type,{type}},
2646 &(struct attr){attr_route,.u.route=this_},
2647 &(struct attr){attr_data,{""}},
2648 &(struct attr){attr_description,{description}},
2655 * @brief Returns a new map containing the route path
2657 * This function returns a new map containing the route path.
2659 * @important Do not map_destroy() this!
2661 * @param this_ The route to get the map of
2662 * @return A new map containing the route path
2665 route_get_map(struct route *this_)
2667 return route_get_map_helper(this_, &this_->map, "route","Route");
2672 * @brief Returns a new map containing the route graph
2674 * This function returns a new map containing the route graph.
2676 * @important Do not map_destroy() this!
2678 * @param this_ The route to get the map of
2679 * @return A new map containing the route graph
2682 route_get_graph_map(struct route *this_)
2684 return route_get_map_helper(this_, &this_->graph_map, "route_graph","Route Graph");
2688 route_set_projection(struct route *this_, enum projection pro)
2693 route_add_callback(struct route *this_, struct callback *cb)
2695 callback_list_add(this_->cbl, cb);
2699 route_remove_callback(struct route *this_, struct callback *cb)
2701 callback_list_remove(this_->cbl, cb);
2708 plugin_register_map_type("route", route_map_new);
2709 plugin_register_map_type("route_graph", route_graph_map_new);