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 */
100 * @brief A segment in the route graph or path
102 * This is a segment in the route graph or path. A segment represents a driveable way.
105 struct route_segment_data {
106 struct item item; /**< The item (e.g. street) that this segment represents. */
108 int len; /**< Length of this segment */
109 /*NOTE: After a segment, various fields may follow, depending on what flags are set. Order of fields:
110 1.) maxspeed Maximum allowed speed on this segment. Present if AF_SPEED_LIMIT is set.
111 2.) offset If the item is segmented (i.e. represented by more than one segment), this
112 indicates the position of this segment in the item. Present if AF_SEGMENTED is set.
116 #define RSD_OFFSET(x) *((int *)route_segment_data_field_pos((x), attr_offset))
117 #define RSD_MAXSPEED(x) *((int *)route_segment_data_field_pos((x), attr_maxspeed))
122 * @brief A segment in the route graph
124 * This is a segment in the route graph. A segment represents a driveable way.
126 struct route_graph_segment {
127 struct route_graph_segment *next; /**< Linked-list pointer to a list of all route_graph_segments */
128 struct route_graph_segment *start_next; /**< Pointer to the next element in the list of segments that start at the
129 * same point. Start of this list is in route_graph_point->start. */
130 struct route_graph_segment *end_next; /**< Pointer to the next element in the list of segments that end at the
131 * same point. Start of this list is in route_graph_point->end. */
132 struct route_graph_point *start; /**< Pointer to the point this segment starts at. */
133 struct route_graph_point *end; /**< Pointer to the point this segment ends at. */
134 struct route_segment_data data; /**< The segment data */
138 * @brief A segment in the route path
140 * This is a segment in the route path.
142 struct route_path_segment {
143 struct route_path_segment *next; /**< Pointer to the next segment in the path */
144 struct route_segment_data *data; /**< The segment data */
145 int direction; /**< Order in which the coordinates are ordered. >0 means "First
146 * coordinate of the segment is the first coordinate of the item", <=0
148 unsigned ncoords; /**< How many coordinates does this segment have? */
149 struct coord c[0]; /**< Pointer to the ncoords coordinates of this segment */
150 /* WARNING: There will be coordinates following here, so do not create new fields after c! */
154 * @brief Usually represents a destination or position
156 * This struct usually represents a destination or position
159 struct coord c; /**< The actual destination / position */
160 struct coord lp; /**< The nearest point on a street to c */
161 int pos; /**< The position of lp within the coords of the street */
162 int lenpos; /**< Distance between lp and the end of the street */
163 int lenneg; /**< Distance between lp and the start of the street */
164 int lenextra; /**< Distance between lp and c */
165 int percent; /**< ratio of lenneg to lenght of whole street in percent */
166 struct street_data *street; /**< The street lp is on */
170 * @brief A complete route path
172 * This structure describes a whole routing path
175 int in_use; /**< The path is in use and can not be updated */
176 int update_required; /**< The path needs to be updated after it is no longer in use */
177 int updated; /**< The path has only been updated */
178 struct route_path_segment *path; /**< The first segment in the path, i.e. the segment one should
180 struct route_path_segment *path_last; /**< The last segment in the path */
181 /* XXX: path_hash is not necessery now */
182 struct item_hash *path_hash; /**< A hashtable of all the items represented by this route's segements */
185 #define RF_FASTEST (1<<0)
186 #define RF_SHORTEST (1<<1)
187 #define RF_AVOIDHW (1<<2)
188 #define RF_AVOIDPAID (1<<3)
189 #define RF_LOCKONROAD (1<<4)
190 #define RF_SHOWGRAPH (1<<5)
193 * @brief Routing preferences
195 * This struct holds all information about route preferences (fastest, shortest, etc)
198 struct route_preferences {
199 int mode; /**< 0 = Auto, 1 = On-Road, 2 = Off-Road */
200 int flags_forward_mask; /**< Flags mask for moving in positive direction */
201 int flags_reverse_mask; /**< Flags mask for moving in reverse direction */
202 int flags; /**< Required flags to move through a segment */
203 int maxspeed_handling; /**< 0 = Always, 1 = Only if lower, 2 = Never */
204 int speedlist[route_item_last-route_item_first+1]; /**< The speedlist for this route */
208 * @brief A complete route
210 * This struct holds all information about a route.
213 struct mapset *ms; /**< The mapset this route is built upon */
215 struct route_info *pos; /**< Current position within this route */
216 struct route_info *dst; /**< Destination of the route */
218 struct route_graph *graph; /**< Pointer to the route graph */
219 struct route_path *path2; /**< Pointer to the route path */
221 struct map *graph_map;
222 struct callback * route_graph_done_cb ; /**< Callback when route graph is done */
223 struct callback * route_graph_flood_done_cb ; /**< Callback when route graph flooding is done */
224 struct callback_list *cbl; /**< Callback list to call when route changes */
225 int destination_distance; /**< Distance to the destination at which the destination is considered "reached" */
226 struct route_preferences preferences; /**< Routing preferences */
230 * @brief A complete route graph
232 * This structure describes a whole routing graph
235 int busy; /**< The graph is being built */
236 struct map_selection *sel; /**< The rectangle selection for the graph */
237 struct mapset_handle *h; /**< Handle to the mapset */
238 struct map *m; /**< Pointer to the currently active map */
239 struct map_rect *mr; /**< Pointer to the currently active map rectangle */
240 struct callback *idle_cb; /**< Idle callback to process the graph */
241 struct callback *done_cb; /**< Callback when graph is done */
242 struct event_idle *idle_ev; /**< The pointer to the idle event */
243 struct route_graph_point *route_points; /**< Pointer to the first route_graph_point in the linked list of all points */
244 struct route_graph_segment *route_segments; /**< Pointer to the first route_graph_segment in the linked list of all segments */
245 #define HASH_SIZE 8192
246 struct route_graph_point *hash[HASH_SIZE]; /**< A hashtable containing all route_graph_points in this graph */
249 #define HASHCOORD(c) ((((c)->x +(c)->y) * 2654435761UL) & (HASH_SIZE-1))
252 * @brief Iterator to iterate through all route graph segments in a route graph point
254 * This structure can be used to iterate through all route graph segments connected to a
255 * route graph point. Use this with the rp_iterator_* functions.
257 struct route_graph_point_iterator {
258 struct route_graph_point *p; /**< The route graph point whose segments should be iterated */
259 int end; /**< Indicates if we have finished iterating through the "start" segments */
260 struct route_graph_segment *next; /**< The next segment to be returned */
263 static struct route_info * route_find_nearest_street(struct mapset *ms, struct pcoord *c);
264 static struct route_graph_point *route_graph_get_point(struct route_graph *this, struct coord *c);
265 static void route_graph_update(struct route *this, struct callback *cb);
266 static void route_graph_build_done(struct route_graph *rg, int cancel);
267 static struct route_path *route_path_new(struct route_graph *this, struct route_path *oldpath, struct route_info *pos, struct route_info *dst, struct route_preferences *pref);
268 static void route_process_street_graph(struct route_graph *this, struct item *item);
269 static void route_graph_destroy(struct route_graph *this);
270 static void route_path_update(struct route *this, int cancel);
273 * @brief Returns the projection used for this route
275 * @param route The route to return the projection for
276 * @return The projection used for this route
278 static enum projection route_projection(struct route *route)
280 struct street_data *street;
281 if (!route->pos && !route->dst)
282 return projection_none;
283 street = route->pos ? route->pos->street : route->dst->street;
284 if (!street || !street->item.map)
285 return projection_none;
286 return map_projection(street->item.map);
290 * @brief Creates a new graph point iterator
292 * This function creates a new route graph point iterator, that can be used to
293 * iterate through all segments connected to the point.
295 * @param p The route graph point to create the iterator from
296 * @return A new iterator.
298 static struct route_graph_point_iterator
299 rp_iterator_new(struct route_graph_point *p)
301 struct route_graph_point_iterator it;
316 * @brief Gets the next segment connected to a route graph point from an iterator
318 * @param it The route graph point iterator to get the segment from
319 * @return The next segment or NULL if there are no more segments
321 static struct route_graph_segment
322 *rp_iterator_next(struct route_graph_point_iterator *it)
324 struct route_graph_segment *ret;
332 if (ret->start_next) {
333 it->next = ret->start_next;
335 it->next = it->p->end;
339 it->next = ret->end_next;
346 * @brief Checks if the last segment returned from a route_graph_point_iterator comes from the end
348 * @param it The route graph point iterator to be checked
349 * @return 1 if the last segment returned comes from the end of the route graph point, 0 otherwise
352 rp_iterator_end(struct route_graph_point_iterator *it) {
353 if (it->end && (it->next != it->p->end)) {
361 * @brief Destroys a route_path
363 * @param this The route_path to be destroyed
366 route_path_destroy(struct route_path *this)
368 struct route_path_segment *c,*n;
371 if (this->path_hash) {
372 item_hash_destroy(this->path_hash);
373 this->path_hash=NULL;
385 * @brief Creates a completely new route structure
387 * @param attrs Not used
388 * @return The newly created route
391 route_new(struct attr *parent, struct attr **attrs)
393 struct route *this=g_new0(struct route, 1);
394 struct attr dest_attr;
396 if (attr_generic_get_attr(attrs, NULL, attr_destination_distance, &dest_attr, NULL)) {
397 this->destination_distance = dest_attr.u.num;
399 this->destination_distance = 50; // Default value
401 this->cbl=callback_list_new();
402 this->preferences.flags_forward_mask=AF_ONEWAYREV|AF_CAR;
403 this->preferences.flags_reverse_mask=AF_ONEWAY|AF_CAR;
404 this->preferences.flags=AF_CAR;
410 * @brief Checks if a segment is part of a roundabout
412 * This function checks if a segment is part of a roundabout.
414 * @param seg The segment to be checked
415 * @param level How deep to scan the route graph
416 * @param direction Set this to 1 if we're entering the segment through its end, to 0 otherwise
417 * @param origin Used internally, set to NULL
418 * @return 1 If a roundabout was detected, 0 otherwise
421 route_check_roundabout(struct route_graph_segment *seg, int level, int direction, struct route_graph_segment *origin)
423 struct route_graph_point_iterator it,it2;
424 struct route_graph_segment *cur;
430 if (!direction && !(seg->data.flags & AF_ONEWAY)) {
433 if (direction && !(seg->data.flags & AF_ONEWAYREV)) {
442 it = rp_iterator_new(seg->end);
444 it = rp_iterator_new(seg->start);
448 while ((cur = rp_iterator_next(&it2)))
453 cur = rp_iterator_next(&it);
456 cur = rp_iterator_next(&it);
460 if (cur->item.type != origin->item.type) {
461 // This street is of another type, can't be part of the roundabout
462 cur = rp_iterator_next(&it);
467 seg->data.flags |= AF_ROUNDABOUT;
471 if (route_check_roundabout(cur, (level-1), rp_iterator_end(&it), origin)) {
472 seg->data.flags |= AF_ROUNDABOUT;
476 cur = rp_iterator_next(&it);
483 * @brief Sets the mapset of the route passwd
485 * @param this The route to set the mapset for
486 * @param ms The mapset to set for this route
489 route_set_mapset(struct route *this, struct mapset *ms)
495 * @brief Returns the mapset of the route passed
497 * @param this The route to get the mapset of
498 * @return The mapset of the route passed
501 route_get_mapset(struct route *this)
507 * @brief Returns the current position within the route passed
509 * @param this The route to get the position for
510 * @return The position within the route passed
513 route_get_pos(struct route *this)
519 * @brief Returns the destination of the route passed
521 * @param this The route to get the destination for
522 * @return The destination of the route passed
525 route_get_dst(struct route *this)
531 * @brief Returns the speedlist of the route passed
533 * @param this The route to get the speedlist for
534 * @return The speedlist of the route passed
537 route_get_speedlist(struct route *this)
539 return this->preferences.speedlist;
543 * @brief Checks if the path is calculated for the route passed
545 * @param this The route to check
546 * @return True if the path is calculated, false if not
549 route_get_path_set(struct route *this)
551 return this->path2 != NULL;
555 * @brief Sets the driving speed for a certain itemtype
557 * @param this The route to set the speed for
558 * @param type The itemtype to set the speed for
559 * @param value The speed that should be set
560 * @return True on success, false if the itemtype does not exist
563 route_set_speed(struct route *this, enum item_type type, int value)
565 if (type < route_item_first || type > route_item_last) {
566 dbg(0,"street type %d out of range [%d,%d]", type, route_item_first, route_item_last);
569 this->preferences.speedlist[type-route_item_first]=value;
574 * @brief Checks if the route passed contains a certain item within the route path
576 * This function checks if a certain items exists in the path that navit will guide
577 * the user to his destination. It does *not* check if this item exists in the route
580 * @param this The route to check for this item
581 * @param item The item to search for
582 * @return True if the item was found, false if the item was not found or the route was not calculated
585 route_contains(struct route *this, struct item *item)
587 if (! this->path2 || !this->path2->path_hash)
589 return (int)item_hash_lookup(this->path2->path_hash, item);
593 * @brief Checks if the current position in a route is a certain item
595 * @param this The route to check for this item
596 * @param item The item to search for
597 * @return True if the current position is this item, false otherwise
600 route_pos_contains(struct route *this, struct item *item)
602 if (! this->pos || !this->pos->street)
604 return item_is_equal(this->pos->street->item, *item);
608 * @brief Checks if a route has reached its destination
610 * @param this The route to be checked
611 * @return True if the destination is "reached", false otherwise.
614 route_destination_reached(struct route *this)
616 struct street_data *sd = NULL;
622 sd = this->pos->street;
628 if (!item_is_equal(this->pos->street->item, this->dst->street->item)) {
632 if ((sd->flags & AF_ONEWAY) && (this->pos->lenneg >= this->dst->lenneg)) { // We would have to drive against the one-way road
635 if ((sd->flags & AF_ONEWAYREV) && (this->pos->lenpos >= this->dst->lenpos)) {
638 pro=route_projection(this);
639 if (pro == projection_none)
642 if (transform_distance(pro, &this->pos->c, &this->dst->lp) > this->destination_distance) {
650 route_path_update_done(struct route *this, int new_graph)
652 struct route_path *oldpath=this->path2;
654 if (this->path2 && this->path2->in_use) {
655 this->path2->update_required=1+new_graph;
659 this->path2=route_path_new(this->graph, oldpath, this->pos, this->dst, &this->preferences);
660 route_path_destroy(oldpath);
665 val=2+!this->path2->updated;
668 callback_list_call_attr_1(this->cbl, attr_route, (void *)val);
672 * @brief Updates the route graph and the route path if something changed with the route
674 * This will update the route graph and the route path of the route if some of the
675 * route's settings (destination, position) have changed.
677 * @attention For this to work the route graph has to be destroyed if the route's
678 * @attention destination is changed somewhere!
680 * @param this The route to update
683 route_path_update(struct route *this, int cancel)
685 dbg(1,"enter %d\n", cancel);
686 if (! this->pos || ! this->dst) {
688 route_path_destroy(this->path2);
693 route_graph_destroy(this->graph);
696 /* the graph is destroyed when setting the destination */
698 if (this->graph->busy) {
699 dbg(1,"busy building graph\n");
702 // we can try to update
703 dbg(1,"try update\n");
704 route_path_update_done(this, 0);
706 route_path_destroy(this->path2);
709 if (!this->graph || !this->path2) {
710 dbg(1,"rebuild graph\n");
711 if (! this->route_graph_flood_done_cb)
712 this->route_graph_flood_done_cb=callback_new_2(callback_cast(route_path_update_done), this, 1);
713 dbg(1,"route_graph_update\n");
714 route_graph_update(this, this->route_graph_flood_done_cb);
719 * @brief This will calculate all the distances stored in a route_info
721 * @param ri The route_info to calculate the distances for
722 * @param pro The projection used for this route
725 route_info_distances(struct route_info *ri, enum projection pro)
728 struct street_data *sd=ri->street;
729 /* 0 1 2 X 3 4 5 6 pos=2 npos=3 count=7 0,1,2 3,4,5,6*/
730 ri->lenextra=transform_distance(pro, &ri->lp, &ri->c);
731 ri->lenneg=transform_polyline_length(pro, sd->c, npos)+transform_distance(pro, &sd->c[ri->pos], &ri->lp);
732 ri->lenpos=transform_polyline_length(pro, sd->c+npos, sd->count-npos)+transform_distance(pro, &sd->c[npos], &ri->lp);
733 if (ri->lenneg || ri->lenpos)
734 ri->percent=(ri->lenneg*100)/(ri->lenneg+ri->lenpos);
740 * @brief This sets the current position of the route passed
742 * This will set the current position of the route passed to the street that is nearest to the
743 * passed coordinates. It also automatically updates the route.
745 * @param this The route to set the position of
746 * @param pos Coordinates to set as position
749 route_set_position(struct route *this, struct pcoord *pos)
752 route_info_free(this->pos);
754 this->pos=route_find_nearest_street(this->ms, pos);
755 dbg(1,"this->pos=%p\n", this->pos);
758 route_info_distances(this->pos, pos->pro);
759 route_path_update(this, 0);
763 * @brief Sets a route's current position based on coordinates from tracking
765 * @param this The route to set the current position of
766 * @param tracking The tracking to get the coordinates from
769 route_set_position_from_tracking(struct route *this, struct tracking *tracking)
772 struct route_info *ret;
773 struct street_data *sd;
776 c=tracking_get_pos(tracking);
777 ret=g_new0(struct route_info, 1);
779 printf("%s:Out of memory\n", __FUNCTION__);
783 route_info_free(this->pos);
789 ret->pos=tracking_get_segment_pos(tracking);
790 sd=tracking_get_street_data(tracking);
792 ret->street=street_data_dup(sd);
793 route_info_distances(ret, c->pro);
795 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);
796 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);
799 route_path_update(this, 0);
803 /* Used for debuging of route_rect, what routing sees */
804 struct map_selection *route_selection;
807 * @brief Returns a single map selection
809 struct map_selection *
810 route_rect(int order, struct coord *c1, struct coord *c2, int rel, int abs)
812 int dx,dy,sx=1,sy=1,d,m;
813 struct map_selection *sel=g_new(struct map_selection, 1);
815 printf("%s:Out of memory\n", __FUNCTION__);
819 sel->range.min=route_item_first;
820 sel->range.max=route_item_last;
821 dbg(1,"%p %p\n", c1, c2);
826 sel->u.c_rect.lu.x=c1->x;
827 sel->u.c_rect.rl.x=c2->x;
829 sel->u.c_rect.lu.x=c2->x;
830 sel->u.c_rect.rl.x=c1->x;
834 sel->u.c_rect.lu.y=c2->y;
835 sel->u.c_rect.rl.y=c1->y;
837 sel->u.c_rect.lu.y=c1->y;
838 sel->u.c_rect.rl.y=c2->y;
845 sel->u.c_rect.lu.x-=m;
846 sel->u.c_rect.rl.x+=m;
847 sel->u.c_rect.lu.y+=m;
848 sel->u.c_rect.rl.y-=m;
854 * @brief Returns a list of map selections useable to create a route graph
856 * Returns a list of map selections useable to get a map rect from which items can be
857 * retrieved to build a route graph. The selections are a rectangle with
858 * c1 and c2 as two corners.
860 * @param c1 Corner 1 of the rectangle
861 * @param c2 Corder 2 of the rectangle
863 static struct map_selection *
864 route_calc_selection(struct coord *c1, struct coord *c2)
866 struct map_selection *ret,*sel;
867 sel=route_rect(4, c1, c2, 25, 0);
869 sel->next=route_rect(8, c1, c1, 0, 40000);
871 sel->next=route_rect(18, c1, c1, 0, 10000);
873 sel->next=route_rect(8, c2, c2, 0, 40000);
875 sel->next=route_rect(18, c2, c2, 0, 10000);
876 /* route_selection=ret; */
881 * @brief Destroys a list of map selections
883 * @param sel Start of the list to be destroyed
886 route_free_selection(struct map_selection *sel)
888 struct map_selection *next;
898 * @brief Sets the destination of a route
900 * This sets the destination of a route to the street nearest to the coordinates passed
901 * and updates the route.
903 * @param this The route to set the destination for
904 * @param dst Coordinates to set as destination
907 route_set_destination(struct route *this, struct pcoord *dst)
911 route_info_free(this->dst);
914 this->dst=route_find_nearest_street(this->ms, dst);
916 route_info_distances(this->dst, dst->pro);
918 callback_list_call_attr_1(this->cbl, attr_route, (void *)0);
919 profile(1,"find_nearest_street");
921 /* The graph has to be destroyed and set to NULL, otherwise route_path_update() doesn't work */
922 route_graph_destroy(this->graph);
924 route_path_update(this, 1);
929 * @brief Gets the route_graph_point with the specified coordinates
931 * @param this The route in which to search
932 * @param c Coordinates to search for
933 * @return The point at the specified coordinates or NULL if not found
935 static struct route_graph_point *
936 route_graph_get_point(struct route_graph *this, struct coord *c)
938 struct route_graph_point *p;
939 int hashval=HASHCOORD(c);
940 p=this->hash[hashval];
942 if (p->c.x == c->x && p->c.y == c->y)
950 * @brief Inserts a point into the route graph at the specified coordinates
952 * This will insert a point into the route graph at the coordinates passed in f.
953 * Note that the point is not yet linked to any segments.
955 * @param this The route to insert the point into
956 * @param f The coordinates at which the point should be inserted
957 * @return The point inserted or NULL on failure
959 static struct route_graph_point *
960 route_graph_add_point(struct route_graph *this, struct coord *f)
963 struct route_graph_point *p;
965 p=route_graph_get_point(this,f);
967 hashval=HASHCOORD(f);
969 printf("p (0x%x,0x%x)\n", f->x, f->y);
970 p=g_new(struct route_graph_point,1);
972 printf("%s:Out of memory\n", __FUNCTION__);
975 p->hash_next=this->hash[hashval];
976 this->hash[hashval]=p;
977 p->next=this->route_points;
984 this->route_points=p;
990 * @brief Frees all the memory used for points in the route graph passed
992 * @param this The route graph to delete all points from
995 route_graph_free_points(struct route_graph *this)
997 struct route_graph_point *curr,*next;
998 curr=this->route_points;
1004 this->route_points=NULL;
1005 memset(this->hash, 0, sizeof(this->hash));
1009 * @brief Returns the position of a certain field appended to a route graph segment
1011 * This function returns a pointer to a field that is appended to a route graph
1014 * @param seg The route graph segment the field is appended to
1015 * @param type Type of the field that should be returned
1016 * @return A pointer to a field of a certain type, or NULL if no such field is present
1019 route_segment_data_field_pos(struct route_segment_data *seg, enum attr_type type)
1023 ptr = ((unsigned char*)seg) + sizeof(struct route_graph_segment);
1025 if (seg->flags & AF_SPEED_LIMIT) {
1026 if (type == attr_maxspeed)
1030 if (seg->flags & AF_SEGMENTED) {
1031 if (type == attr_offset)
1039 * @brief Calculates the size of a route_segment_data struct with given flags
1041 * @param flags The flags of the route_segment_data
1045 route_segment_data_size(int flags)
1047 int ret=sizeof(struct route_segment_data);
1048 if (flags & AF_SPEED_LIMIT)
1050 if (flags & AF_SEGMENTED)
1057 * @brief Inserts a new segment into the route graph
1059 * This function performs a check if a segment for the item specified already exists, and inserts
1060 * a new segment representing this item if it does not.
1062 * @param this The route graph to insert the segment into
1063 * @param start The graph point which should be connected to the start of this segment
1064 * @param end The graph point which should be connected to the end of this segment
1065 * @param len The length of this segment
1066 * @param item The item that is represented by this segment
1067 * @param flags Flags for this segment
1068 * @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
1069 * @param maxspeed The maximum speed allowed on this segment in km/h. -1 if not known.
1072 route_graph_add_segment(struct route_graph *this, struct route_graph_point *start,
1073 struct route_graph_point *end, int len, struct item *item,
1074 int flags, int offset, int maxspeed)
1076 struct route_graph_segment *s;
1080 if (item_is_equal(*item, s->data.item)) {
1081 if (flags & AF_SEGMENTED) {
1082 if (RSD_OFFSET(&s->data) == offset) {
1091 size = sizeof(struct route_graph_segment)-sizeof(struct route_segment_data)+route_segment_data_size(flags);
1092 s = g_malloc0(size);
1094 printf("%s:Out of memory\n", __FUNCTION__);
1098 s->start_next=start->start;
1101 s->end_next=end->end;
1103 dbg_assert(len >= 0);
1106 s->data.flags=flags;
1108 if (flags & AF_SPEED_LIMIT)
1109 RSD_MAXSPEED(&s->data)=maxspeed;
1110 if (flags & AF_SEGMENTED)
1111 RSD_OFFSET(&s->data)=offset;
1113 s->next=this->route_segments;
1114 this->route_segments=s;
1116 printf("l (0x%x,0x%x)-(0x%x,0x%x)\n", start->c.x, start->c.y, end->c.x, end->c.y);
1120 * @brief Gets all the coordinates of an item
1122 * This will get all the coordinates of the item i and return them in c,
1123 * up to max coordinates. Additionally it is possible to limit the coordinates
1124 * returned to all the coordinates of the item between the two coordinates
1127 * @important Make shure that whatever c points to has enough memory allocated
1128 * @important to hold max coordinates!
1130 * @param i The item to get the coordinates of
1131 * @param c Pointer to memory allocated for holding the coordinates
1132 * @param max Maximum number of coordinates to return
1133 * @param start First coordinate to get
1134 * @param end Last coordinate to get
1135 * @return The number of coordinates returned
1137 static int get_item_seg_coords(struct item *i, struct coord *c, int max,
1138 struct coord *start, struct coord *end)
1140 struct map_rect *mr;
1144 mr=map_rect_new(i->map, NULL);
1147 item = map_rect_get_item_byid(mr, i->id_hi, i->id_lo);
1149 rc = item_coord_get(item, &c1, 1);
1150 while (rc && (c1.x != start->x || c1.y != start->y)) {
1151 rc = item_coord_get(item, &c1, 1);
1153 while (rc && p < max) {
1155 if (c1.x == end->x && c1.y == end->y)
1157 rc = item_coord_get(item, &c1, 1);
1160 map_rect_destroy(mr);
1165 * @brief Returns and removes one segment from a path
1167 * @param path The path to take the segment from
1168 * @param item The item whose segment to remove
1169 * @param offset Offset of the segment within the item to remove. If the item is not segmented this should be 1.
1170 * @return The segment removed
1172 static struct route_path_segment *
1173 route_extract_segment_from_path(struct route_path *path, struct item *item,
1177 struct route_path_segment *sp = NULL, *s;
1180 if (item_is_equal(s->data->item,*item)) {
1181 if (s->data->flags & AF_SEGMENTED)
1182 soffset=RSD_OFFSET(s->data);
1185 if (soffset == offset) {
1190 path->path = s->next;
1199 item_hash_remove(path->path_hash, item);
1204 * @brief Adds a segment and the end of a path
1206 * @param this The path to add the segment to
1207 * @param segment The segment to add
1210 route_path_add_segment(struct route_path *this, struct route_path_segment *segment)
1214 if (this->path_last)
1215 this->path_last->next=segment;
1216 this->path_last=segment;
1220 * @brief Adds a two coordinate line to a path
1222 * This adds a new line to a path, creating a new segment for it.
1224 * @param this The path to add the item to
1225 * @param start coordinate to add to the start of the item. If none should be added, make this NULL.
1226 * @param end coordinate to add to the end of the item. If none should be added, make this NULL.
1227 * @param len The length of the item
1230 route_path_add_line(struct route_path *this, struct coord *start, struct coord *end, int len)
1233 struct route_path_segment *segment;
1234 int seg_size,seg_dat_size;
1236 seg_size=sizeof(*segment) + sizeof(struct coord) * ccnt;
1237 seg_dat_size=sizeof(struct route_segment_data);
1238 segment=g_malloc0(seg_size + seg_dat_size);
1239 segment->data=(struct route_segment_data *)((char *)segment+seg_size);
1240 segment->ncoords=ccnt;
1241 segment->direction=0;
1242 segment->c[0]=*start;
1244 segment->data->len=len;
1245 route_path_add_segment(this, segment);
1249 * @brief Inserts a new item into the path
1251 * This function does almost the same as "route_path_add_item()", but identifies
1252 * the item to add by a segment from the route graph. Another difference is that it "copies" the
1253 * segment from the route graph, i.e. if the item is segmented, only the segment passed in rgs will
1254 * be added to the route path, not all segments of the item.
1256 * The function can be sped up by passing an old path already containing this segment in oldpath -
1257 * the segment will then be extracted from this old path. Please note that in this case the direction
1258 * parameter has no effect.
1260 * @param this The path to add the item to
1261 * @param oldpath Old path containing the segment to be added. Speeds up the function, but can be NULL.
1262 * @param rgs Segment of the route graph that should be "copied" to the route path
1263 * @param dir Order in which to add the coordinates. See route_path_add_item()
1264 * @param pos Information about start point if this is the first segment
1265 * @param dst Information about end point if this is the last segment
1269 route_path_add_item_from_graph(struct route_path *this, struct route_path *oldpath, struct route_graph_segment *rgs, int dir, struct route_info *pos, struct route_info *dst)
1271 struct route_path_segment *segment;
1272 int i,ccnt = 0, extra=0, ret=1;
1273 struct coord *c,*cd,ca[2048];
1275 int seg_size,seg_dat_size;
1276 if (rgs->data.flags & AF_SEGMENTED)
1277 offset=RSD_OFFSET(&rgs->data);
1279 dbg(1,"enter (0x%x,0x%x)\n", rgs->data.item.id_hi, rgs->data.item.id_lo);
1281 ccnt = (int)item_hash_lookup(oldpath->path_hash, &rgs->data.item);
1283 segment = route_extract_segment_from_path(oldpath, &rgs->data.item, offset);
1292 if (dst->lenneg >= pos->lenneg) {
1294 ccnt=dst->pos-pos->pos;
1295 c=pos->street->c+pos->pos+1;
1298 ccnt=pos->pos-dst->pos;
1299 c=pos->street->c+dst->pos+1;
1303 dbg(0,"pos dir=%d\n", dir);
1304 dbg(0,"pos pos=%d\n", pos->pos);
1305 dbg(0,"pos count=%d\n", pos->street->count);
1307 c=pos->street->c+pos->pos+1;
1308 ccnt=pos->street->count-pos->pos-1;
1316 dbg(0,"dst dir=%d\n", dir);
1317 dbg(0,"dst pos=%d\n", dst->pos);
1322 c=dst->street->c+dst->pos+1;
1323 ccnt=dst->street->count-dst->pos-1;
1326 ccnt=get_item_seg_coords(&rgs->data.item, ca, 2047, &rgs->start->c, &rgs->end->c);
1329 seg_size=sizeof(*segment) + sizeof(struct coord) * (ccnt + extra);
1330 seg_dat_size=route_segment_data_size(rgs->data.flags);
1331 segment=g_malloc0(seg_size + seg_dat_size);
1332 segment->data=(struct route_segment_data *)((char *)segment+seg_size);
1333 segment->direction=dir;
1335 if (pos && (c[0].x != pos->lp.x || c[0].y != pos->lp.y))
1339 for (i = 0 ; i < ccnt ; i++) {
1343 segment->ncoords+=ccnt;
1344 if (dst && (cd[-1].x != dst->lp.x || cd[-1].y != dst->lp.y))
1346 segment->ncoords=cd-segment->c;
1348 /* We check if the route graph segment is part of a roundabout here, because this
1349 * only matters for route graph segments which form parts of the route path */
1350 if (!(rgs->data.flags & AF_ROUNDABOUT)) { // We identified this roundabout earlier
1351 route_check_roundabout(rgs, 13, (dir < 1), NULL);
1355 memcpy(segment->data, &rgs->data, seg_dat_size);
1358 segment->data->len=rgs->data.len;
1360 item_hash_insert(this->path_hash, &rgs->data.item, (void *)ccnt);
1362 route_path_add_segment(this, segment);
1368 * @brief Destroys all segments of a route graph
1370 * @param this The graph to destroy all segments from
1373 route_graph_free_segments(struct route_graph *this)
1375 struct route_graph_segment *curr,*next;
1376 curr=this->route_segments;
1382 this->route_segments=NULL;
1386 * @brief Destroys a route graph
1388 * @param this The route graph to be destroyed
1391 route_graph_destroy(struct route_graph *this)
1394 route_graph_build_done(this, 1);
1395 route_graph_free_points(this);
1396 route_graph_free_segments(this);
1402 * @brief Returns the time needed to drive len on item
1404 * This function returns the time needed to drive len meters on
1405 * the item passed in item in tenth of seconds.
1407 * @param preferences The routing preferences
1408 * @param over The segment which is passed
1409 * @return The time needed to drive len on item in thenth of senconds
1413 route_time_seg(struct route_preferences *preferences, struct route_segment_data *over)
1415 int pspeed=preferences->speedlist[over->item.type-route_item_first];
1417 if (preferences->maxspeed_handling != 2 && (over->flags & AF_SPEED_LIMIT)) {
1418 speed=RSD_MAXSPEED(over);
1419 if (preferences->maxspeed_handling == 1 && speed > pspeed)
1422 speed=preferences->speedlist[over->item.type-route_item_first];
1425 return over->len*36/speed;
1429 * @brief Returns the "costs" of driving from point from over segment over in direction dir
1431 * @param preferences The routing preferences
1432 * @param from The point where we are starting
1433 * @param over The segment we are using
1434 * @param dir The direction of segment which we are driving
1435 * @return The "costs" needed to drive len on item
1439 route_value_seg(struct route_preferences *preferences, struct route_graph_point *from, struct route_segment_data *over, int dir)
1442 dbg(0,"flags 0x%x mask 0x%x flags 0x%x\n", over->flags, dir >= 0 ? preferences->flags_forward_mask : preferences->flags_reverse_mask, preferences->flags);
1444 if ((over->flags & (dir >= 0 ? preferences->flags_forward_mask : preferences->flags_reverse_mask)) != preferences->flags)
1446 return route_time_seg(preferences, over);
1450 * @brief Adds an item to the route graph
1452 * This adds an item (e.g. a street) to the route graph, creating as many segments as needed for a
1455 * @param this The route graph to add to
1456 * @param item The item to add
1459 route_process_street_graph(struct route_graph *this, struct item *item)
1466 struct route_graph_point *s_pnt,*e_pnt;
1468 struct attr flags_attr, maxspeed_attr;
1474 if (item_coord_get(item, &l, 1)) {
1475 if (item_attr_get(item, attr_flags, &flags_attr)) {
1476 flags = flags_attr.u.num;
1477 if (flags & AF_SEGMENTED)
1480 flags = default_flags[item->type-route_item_first];
1483 if (flags & AF_SPEED_LIMIT) {
1484 if (item_attr_get(item, attr_maxspeed, &maxspeed_attr)) {
1485 maxspeed = maxspeed_attr.u.num;
1489 s_pnt=route_graph_add_point(this,&l);
1491 while (item_coord_get(item, &c, 1)) {
1492 len+=transform_distance(map_projection(item->map), &l, &c);
1495 e_pnt=route_graph_add_point(this,&l);
1496 dbg_assert(len >= 0);
1497 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset, maxspeed);
1502 isseg = item_coord_is_node(item);
1503 rc = item_coord_get(item, &c, 1);
1505 len+=transform_distance(map_projection(item->map), &l, &c);
1508 e_pnt=route_graph_add_point(this,&l);
1509 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset, maxspeed);
1511 s_pnt=route_graph_add_point(this,&l);
1516 e_pnt=route_graph_add_point(this,&l);
1517 dbg_assert(len >= 0);
1519 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset, maxspeed);
1525 * @brief Compares the costs of reaching the destination from two points on
1527 * @important Do not pass anything other than route_graph_points in v1 and v2!
1531 * @return The additional costs of v1 compared to v2 (may be negative)
1534 compare(void *v1, void *v2)
1536 struct route_graph_point *p1=v1;
1537 struct route_graph_point *p2=v2;
1540 printf("compare %d (%p) vs %d (%p)\n", p1->value,p1,p2->value,p2);
1542 return p1->value-p2->value;
1545 static struct route_graph_segment *
1546 route_graph_get_segment(struct route_graph *graph, struct street_data *sd)
1548 struct route_graph_point *start=route_graph_get_point(graph, &sd->c[0]);
1549 struct route_graph_segment *s;
1552 if (item_is_equal(sd->item, s->data.item))
1560 * @brief Calculates the routing costs for each point
1562 * This function is the heart of routing. It assigns each point in the route graph a
1563 * cost at which one can reach the destination from this point on. Additionally it assigns
1564 * each point a segment one should follow from this point on to reach the destination at the
1567 * This function uses Dijkstra's algorithm to do the routing. To understand it you should have a look
1568 * at this algorithm.
1571 route_graph_flood(struct route_graph *this, struct route_info *dst, struct route_preferences *preferences, struct callback *cb)
1573 struct route_graph_point *p_min;
1574 struct route_graph_segment *s;
1575 int min,new,old,val;
1576 struct fibheap *heap; /* This heap will hold all points with "temporarily" calculated costs */
1578 heap = fh_makeheap();
1579 fh_setcmp(heap, compare);
1582 s=route_graph_get_segment(this, dst->street);
1584 dbg(0,"no segment for destination found\n");
1587 val=route_value_seg(preferences, NULL, &s->data, 1);
1588 if (val != INT_MAX) {
1589 val=val*(100-dst->percent)/100;
1592 s->end->el=fh_insert(heap, s->end);
1594 val=route_value_seg(preferences, NULL, &s->data, -1);
1595 if (val != INT_MAX) {
1596 val=val*dst->percent/100;
1598 s->start->value=val;
1599 s->start->el=fh_insert(heap, s->start);
1602 p_min=fh_extractmin(heap); /* Starting Dijkstra by selecting the point with the minimum costs on the heap */
1603 if (! p_min) /* There are no more points with temporarily calculated costs, Dijkstra has finished */
1607 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);
1608 p_min->el=NULL; /* This point is permanently calculated now, we've taken it out of the heap */
1610 while (s) { /* Iterating all the segments leading away from our point to update the points at their ends */
1611 val=route_value_seg(preferences, p_min, &s->data, -1);
1612 if (val != INT_MAX) {
1615 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);
1616 if (new < s->end->value) { /* We've found a less costly way to reach the end of s, update it */
1621 printf("insert_end p=%p el=%p val=%d ", s->end, s->end->el, s->end->value);
1622 s->end->el=fh_insert(heap, s->end);
1624 printf("el new=%p\n", s->end->el);
1628 printf("replace_end p=%p el=%p val=%d\n", s->end, s->end->el, s->end->value);
1629 fh_replacedata(heap, s->end->el, s->end);
1638 while (s) { /* Doing the same as above with the segments leading towards our point */
1639 val=route_value_seg(preferences, p_min, &s->data, 1);
1640 if (val != INT_MAX) {
1643 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);
1644 if (new < s->start->value) {
1645 old=s->start->value;
1646 s->start->value=new;
1648 if (! s->start->el) {
1650 printf("insert_start p=%p el=%p val=%d ", s->start, s->start->el, s->start->value);
1651 s->start->el=fh_insert(heap, s->start);
1653 printf("el new=%p\n", s->start->el);
1657 printf("replace_start p=%p el=%p val=%d\n", s->start, s->start->el, s->start->value);
1658 fh_replacedata(heap, s->start->el, s->start);
1667 fh_deleteheap(heap);
1668 callback_call_0(cb);
1673 * @brief Starts an "offroad" path
1675 * This starts a path that is not located on a street. It creates a new route path
1676 * adding only one segment, that leads from pos to dest, and which is not associated with an item.
1678 * @param this Not used
1679 * @param pos The starting position for the new path
1680 * @param dst The destination of the new path
1681 * @param dir Not used
1682 * @return The new path
1684 static struct route_path *
1685 route_path_new_offroad(struct route_graph *this, struct route_info *pos, struct route_info *dst)
1687 struct route_path *ret;
1689 ret=g_new0(struct route_path, 1);
1690 ret->path_hash=item_hash_new();
1691 route_path_add_line(ret, &pos->c, &dst->c, pos->lenextra+dst->lenextra);
1698 * @brief Returns a coordinate at a given distance
1700 * This function returns the coordinate, where the user will be if he
1701 * follows the current route for a certain distance.
1703 * @param this_ The route we're driving upon
1704 * @param dist The distance in meters
1705 * @return The coordinate where the user will be in that distance
1708 route_get_coord_dist(struct route *this_, int dist)
1713 struct route_path_segment *cur;
1715 enum projection pro=route_projection(this_);
1719 if (!this_->path2 || pro == projection_none) {
1720 return this_->pos->c;
1723 ret = this_->pos->c;
1724 cur = this_->path2->path;
1726 if (cur->data->len < d) {
1727 d -= cur->data->len;
1729 for (i=0; i < (cur->ncoords-1); i++) {
1731 len = (int)transform_polyline_length(pro, (cur->c + i), 2);
1734 // We interpolate a bit here...
1735 frac = (double)l / len;
1737 dx = (cur->c + i + 1)->x - (cur->c + i)->x;
1738 dy = (cur->c + i + 1)->y - (cur->c + i)->y;
1740 ret.x = (cur->c + i)->x + (frac * dx);
1741 ret.y = (cur->c + i)->y + (frac * dy);
1745 return cur->c[(cur->ncoords-1)];
1750 return this_->dst->c;
1754 * @brief Creates a new route path
1756 * This creates a new non-trivial route. It therefore needs the routing information created by route_graph_flood, so
1757 * make shure to run route_graph_flood() after changing the destination before using this function.
1759 * @param this The route graph to create the route from
1760 * @param oldpath (Optional) old path which may contain parts of the new part - this speeds things up a bit. May be NULL.
1761 * @param pos The starting position of the route
1762 * @param dst The destination of the route
1763 * @param preferences The routing preferences
1764 * @return The new route path
1766 static struct route_path *
1767 route_path_new(struct route_graph *this, struct route_path *oldpath, struct route_info *pos, struct route_info *dst, struct route_preferences *preferences)
1769 struct route_graph_segment *first,*s=NULL;
1770 struct route_graph_point *start;
1771 struct route_info *posinfo, *dstinfo;
1773 int val1=INT_MAX,val2=INT_MAX;
1775 struct route_path *ret;
1777 if (! pos->street || ! dst->street)
1780 if (preferences->mode == 2 || (preferences->mode == 0 && pos->lenextra + dst->lenextra + pos->lenpos-dst->lenpos > transform_distance(map_projection(pos->street->item.map), &pos->c, &dst->c)))
1781 return route_path_new_offroad(this, pos, dst);
1783 s=route_graph_get_segment(this, pos->street);
1785 dbg(0,"no segment for position found\n");
1788 val=route_value_seg(preferences, NULL, &s->data, -1);
1789 if (val != INT_MAX) {
1790 val=val*(100-pos->percent)/100;
1791 val1=s->end->value+val;
1793 val=route_value_seg(preferences, NULL, &s->data, 1);
1794 if (val != INT_MAX) {
1795 val=val*pos->percent/100;
1796 val2=s->start->value+val;
1798 if (val1 == INT_MAX && val2 == INT_MAX) {
1799 dbg(0,"no route found, pos blocked\n");
1804 val2=s->start->value;
1810 ret=g_new0(struct route_path, 1);
1813 route_path_add_line(ret, &pos->c, &pos->lp, pos->lenextra);
1814 ret->path_hash=item_hash_new();
1818 while (s && !dstinfo) { /* following start->seg, which indicates the least costly way to reach our destination */
1821 printf("start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
1823 if (s->start == start) {
1824 if (item_is_equal(s->data.item, dst->street->item) && (s->end->seg == s || !posinfo))
1826 if (!route_path_add_item_from_graph(ret, oldpath, s, 1, posinfo, dstinfo))
1830 if (item_is_equal(s->data.item, dst->street->item) && (s->start->seg == s || !posinfo))
1832 if (!route_path_add_item_from_graph(ret, oldpath, s, -1, posinfo, dstinfo))
1840 route_path_add_line(ret, &dst->lp, &dst->c, dst->lenextra);
1841 dbg(1, "%d segments\n", segs);
1846 route_graph_build_next_map(struct route_graph *rg)
1849 rg->m=mapset_next(rg->h, 1);
1852 map_rect_destroy(rg->mr);
1853 rg->mr=map_rect_new(rg->m, rg->sel);
1860 route_graph_build_done(struct route_graph *rg, int cancel)
1862 dbg(1,"cancel=%d\n",cancel);
1863 event_remove_idle(rg->idle_ev);
1864 callback_destroy(rg->idle_cb);
1865 map_rect_destroy(rg->mr);
1866 mapset_close(rg->h);
1867 route_free_selection(rg->sel);
1874 callback_call_0(rg->done_cb);
1879 route_graph_build_idle(struct route_graph *rg)
1886 item=map_rect_get_item(rg->mr);
1889 if (!route_graph_build_next_map(rg)) {
1890 route_graph_build_done(rg, 0);
1894 if (item->type >= route_item_first && item->type <= route_item_last)
1895 route_process_street_graph(rg, item);
1901 * @brief Builds a new route graph from a mapset
1903 * This function builds a new route graph from a map. Please note that this function does not
1904 * add any routing information to the route graph - this has to be done via the route_graph_flood()
1907 * The function does not create a graph covering the whole map, but only covering the rectangle
1908 * between c1 and c2.
1910 * @param ms The mapset to build the route graph from
1911 * @param c1 Corner 1 of the rectangle to use from the map
1912 * @param c2 Corner 2 of the rectangle to use from the map
1913 * @param done_cb The callback which will be called when graph is complete
1914 * @return The new route graph.
1916 static struct route_graph *
1917 route_graph_build(struct mapset *ms, struct coord *c1, struct coord *c2, struct callback *done_cb)
1919 struct route_graph *ret=g_new0(struct route_graph, 1);
1923 ret->sel=route_calc_selection(c1, c2);
1924 ret->h=mapset_open(ms);
1925 ret->done_cb=done_cb;
1927 if (route_graph_build_next_map(ret)) {
1928 ret->idle_cb=callback_new_1(callback_cast(route_graph_build_idle), ret);
1929 ret->idle_ev=event_add_idle(50, ret->idle_cb);
1931 route_graph_build_done(ret, 0);
1937 route_graph_update_done(struct route *this, struct callback *cb)
1939 route_graph_flood(this->graph, this->dst, &this->preferences, cb);
1943 * @brief Updates the route graph
1945 * This updates the route graph after settings in the route have changed. It also
1946 * adds routing information afterwards by calling route_graph_flood().
1948 * @param this The route to update the graph for
1951 route_graph_update(struct route *this, struct callback *cb)
1953 route_graph_destroy(this->graph);
1954 callback_destroy(this->route_graph_done_cb);
1955 this->route_graph_done_cb=callback_new_2(callback_cast(route_graph_update_done), this, cb);
1956 callback_list_call_attr_1(this->cbl, attr_route, (void *)0);
1957 this->graph=route_graph_build(this->ms, &this->pos->c, &this->dst->c, this->route_graph_done_cb);
1961 * @brief Gets street data for an item
1963 * @param item The item to get the data for
1964 * @return Street data for the item
1966 struct street_data *
1967 street_get_data (struct item *item)
1970 struct street_data *ret = NULL, *ret1;
1971 struct attr flags_attr, maxspeed_attr;
1972 const int step = 128;
1976 ret1=g_realloc(ret, sizeof(struct street_data)+(count+step)*sizeof(struct coord));
1983 c = item_coord_get(item, &ret->c[count], step);
1985 } while (c && c == step);
1987 ret1=g_realloc(ret, sizeof(struct street_data)+count*sizeof(struct coord));
1992 if (item_attr_get(item, attr_flags, &flags_attr))
1993 ret->flags=flags_attr.u.num;
1998 if (ret->flags & AF_SPEED_LIMIT) {
1999 if (item_attr_get(item, attr_maxspeed, &maxspeed_attr)) {
2000 ret->maxspeed = maxspeed_attr.u.num;
2008 * @brief Copies street data
2010 * @param orig The street data to copy
2011 * @return The copied street data
2013 struct street_data *
2014 street_data_dup(struct street_data *orig)
2016 struct street_data *ret;
2017 int size=sizeof(struct street_data)+orig->count*sizeof(struct coord);
2020 memcpy(ret, orig, size);
2026 * @brief Frees street data
2028 * @param sd Street data to be freed
2031 street_data_free(struct street_data *sd)
2037 * @brief Finds the nearest street to a given coordinate
2039 * @param ms The mapset to search in for the street
2040 * @param pc The coordinate to find a street nearby
2041 * @return The nearest street
2043 static struct route_info *
2044 route_find_nearest_street(struct mapset *ms, struct pcoord *pc)
2046 struct route_info *ret=NULL;
2048 struct map_selection *sel;
2049 int dist,mindist=0,pos;
2050 struct mapset_handle *h;
2052 struct map_rect *mr;
2055 struct street_data *sd;
2059 ret=g_new0(struct route_info, 1);
2061 dbg(0,"Out of memory\n");
2067 while ((m=mapset_next(h,1))) {
2070 if (map_projection(m) != pc->pro) {
2071 transform_to_geo(pc->pro, &c, &g);
2072 transform_from_geo(map_projection(m), &g, &c);
2074 sel = route_rect(18, &c, &c, 0, max_dist);
2077 mr=map_rect_new(m, sel);
2079 map_selection_destroy(sel);
2082 while ((item=map_rect_get_item(mr))) {
2083 if (item->type >= route_item_first && item->type <= route_item_last) {
2084 sd=street_get_data(item);
2087 dist=transform_distance_polyline_sq(sd->c, sd->count, &c, &lp, &pos);
2088 if (dist < mindist) {
2091 street_data_free(ret->street);
2097 dbg(1,"dist=%d id 0x%x 0x%x pos=%d\n", dist, item->id_hi, item->id_lo, pos);
2099 street_data_free(sd);
2103 map_selection_destroy(sel);
2104 map_rect_destroy(mr);
2108 if (!ret->street || mindist > max_dist*max_dist) {
2110 street_data_free(ret->street);
2111 dbg(1,"Much too far %d > %d\n", mindist, max_dist);
2121 * @brief Destroys a route_info
2123 * @param info The route info to be destroyed
2126 route_info_free(struct route_info *inf)
2129 street_data_free(inf->street);
2137 * @brief Returns street data for a route info
2139 * @param rinf The route info to return the street data for
2140 * @return Street data for the route info
2142 struct street_data *
2143 route_info_street(struct route_info *rinf)
2145 return rinf->street;
2149 struct route_crossings *
2150 route_crossings_get(struct route *this, struct coord *c)
2152 struct route_point *pnt;
2153 struct route_segment *seg;
2155 struct route_crossings *ret;
2157 pnt=route_graph_get_point(this, c);
2160 printf("start: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
2162 seg=seg->start_next;
2166 printf("end: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
2170 ret=g_malloc(sizeof(struct route_crossings)+crossings*sizeof(struct route_crossing));
2171 ret->count=crossings;
2177 struct map_rect_priv {
2178 struct route_info_handle *ri;
2179 enum attr_type attr_next;
2181 struct map_priv *mpriv;
2184 unsigned int last_coord;
2185 struct route_path *path;
2186 struct route_path_segment *seg,*seg_next;
2187 struct route_graph_point *point;
2188 struct route_graph_segment *rseg;
2190 struct coord *coord_sel; /**< Set this to a coordinate if you want to filter for just a single route graph point */
2191 struct route_graph_point_iterator it;
2195 rm_coord_rewind(void *priv_data)
2197 struct map_rect_priv *mr = priv_data;
2202 rm_attr_rewind(void *priv_data)
2204 struct map_rect_priv *mr = priv_data;
2205 mr->attr_next = attr_street_item;
2209 rm_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
2211 struct map_rect_priv *mr = priv_data;
2212 struct route_path_segment *seg=mr->seg;
2213 struct route *route=mr->mpriv->route;
2214 if (mr->item.type != type_street_route)
2216 attr->type=attr_type;
2217 switch (attr_type) {
2219 while (mr->attr_next != attr_none) {
2220 if (rm_attr_get(priv_data, mr->attr_next, attr))
2225 mr->attr_next = attr_street_item;
2226 if (seg && seg->data->flags && AF_SPEED_LIMIT) {
2227 attr->u.num=RSD_MAXSPEED(seg->data);
2233 case attr_street_item:
2234 mr->attr_next=attr_direction;
2235 if (seg && seg->data->item.map)
2236 attr->u.item=&seg->data->item;
2240 case attr_direction:
2241 mr->attr_next=attr_route;
2243 attr->u.num=seg->direction;
2248 mr->attr_next=attr_length;
2249 attr->u.route = mr->mpriv->route;
2253 attr->u.num=seg->data->len;
2255 attr->u.num=mr->length;
2256 mr->attr_next=attr_time;
2259 mr->attr_next=attr_none;
2261 attr->u.num=route_time_seg(&route->preferences, seg->data);
2266 mr->attr_next=attr_none;
2269 mr->attr_next=attr_none;
2270 attr->type=attr_none;
2277 rm_coord_get(void *priv_data, struct coord *c, int count)
2279 struct map_rect_priv *mr = priv_data;
2280 struct route_path_segment *seg = mr->seg;
2282 struct route *r = mr->mpriv->route;
2283 enum projection pro = route_projection(r);
2285 if (pro == projection_none)
2287 if (mr->item.type == type_route_start || mr->item.type == type_route_end) {
2288 if (! count || mr->last_coord)
2291 if (mr->item.type == type_route_start)
2299 for (i=0; i < count; i++) {
2300 if (mr->last_coord >= seg->ncoords)
2302 if (i >= seg->ncoords)
2304 if (pro != projection_mg)
2305 transform_from_to(&seg->c[mr->last_coord++], pro,
2306 &c[i],projection_mg);
2308 c[i] = seg->c[mr->last_coord++];
2311 dbg(1,"return %d\n",rc);
2315 static struct item_methods methods_route_item = {
2323 rp_attr_rewind(void *priv_data)
2325 struct map_rect_priv *mr = priv_data;
2326 mr->attr_next = attr_label;
2330 rp_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
2332 struct map_rect_priv *mr = priv_data;
2333 struct route_graph_point *p = mr->point;
2334 struct route_graph_segment *seg = mr->rseg;
2335 switch (attr_type) {
2336 case attr_any: // works only with rg_points for now
2337 if (mr->item.type != type_rg_point)
2339 while (mr->attr_next != attr_none) {
2340 if (rp_attr_get(priv_data, mr->attr_next, attr))
2345 mr->attr_next = attr_label;
2346 if (mr->item.type != type_rg_segment)
2348 if (seg && (seg->data.flags & AF_SPEED_LIMIT)) {
2349 attr->type = attr_maxspeed;
2350 attr->u.num=RSD_MAXSPEED(&seg->data);
2356 if (mr->item.type != type_rg_point)
2358 attr->type = attr_label;
2361 if (p->value != INT_MAX)
2362 mr->str=g_strdup_printf("%d", p->value);
2364 mr->str=g_strdup("-");
2365 attr->u.str = mr->str;
2366 mr->attr_next=attr_none;
2368 case attr_street_item:
2369 if (mr->item.type != type_rg_segment)
2371 mr->attr_next=attr_none;
2372 if (seg && seg->data.item.map)
2373 attr->u.item=&seg->data.item;
2378 if (mr->item.type != type_rg_segment)
2380 mr->attr_next = attr_none;
2382 attr->u.num = seg->data.flags;
2387 case attr_direction:
2388 // This only works if the map has been opened at a single point, and in that case indicates if the
2389 // segment returned last is connected to this point via its start (1) or its end (-1)
2390 if (!mr->coord_sel || (mr->item.type != type_rg_segment))
2392 if (seg->start == mr->point) {
2394 } else if (seg->end == mr->point) {
2401 if (mr->item.type != type_rg_point)
2403 attr->type = attr_debug;
2406 mr->str=g_strdup_printf("x=%d y=%d", p->c.x, p->c.y);
2407 attr->u.str = mr->str;
2408 mr->attr_next=attr_none;
2411 mr->attr_next=attr_none;
2412 attr->type=attr_none;
2418 * @brief Returns the coordinates of a route graph item
2420 * @param priv_data The route graph item's private data
2421 * @param c Pointer where to store the coordinates
2422 * @param count How many coordinates to get at a max?
2423 * @return The number of coordinates retrieved
2426 rp_coord_get(void *priv_data, struct coord *c, int count)
2428 struct map_rect_priv *mr = priv_data;
2429 struct route_graph_point *p = mr->point;
2430 struct route_graph_segment *seg = mr->rseg;
2432 struct route *r = mr->mpriv->route;
2433 enum projection pro = route_projection(r);
2435 if (pro == projection_none)
2437 for (i=0; i < count; i++) {
2438 if (mr->item.type == type_rg_point) {
2439 if (mr->last_coord >= 1)
2441 if (pro != projection_mg)
2442 transform_from_to(&p->c, pro,
2443 &c[i],projection_mg);
2447 if (mr->last_coord >= 2)
2450 if (seg->end->seg == seg)
2455 if (pro != projection_mg)
2456 transform_from_to(&seg->end->c, pro,
2457 &c[i],projection_mg);
2461 if (pro != projection_mg)
2462 transform_from_to(&seg->start->c, pro,
2463 &c[i],projection_mg);
2465 c[i] = seg->start->c;
2474 static struct item_methods methods_point_item = {
2482 rp_destroy(struct map_priv *priv)
2488 rm_destroy(struct map_priv *priv)
2493 static struct map_rect_priv *
2494 rm_rect_new(struct map_priv *priv, struct map_selection *sel)
2496 struct map_rect_priv * mr;
2498 if (! route_get_pos(priv->route))
2500 if (! route_get_dst(priv->route))
2503 if (! priv->route->path2)
2506 mr=g_new0(struct map_rect_priv, 1);
2508 mr->item.priv_data = mr;
2509 mr->item.type = type_none;
2510 mr->item.meth = &methods_route_item;
2511 if (priv->route->path2) {
2512 mr->path=priv->route->path2;
2513 mr->seg_next=mr->path->path;
2521 * @brief Opens a new map rectangle on the route graph's map
2523 * This function opens a new map rectangle on the route graph's map.
2524 * The "sel" parameter enables you to only search for a single route graph
2525 * point on this map (or exactly: open a map rectangle that only contains
2526 * this one point). To do this, pass here a single map selection, whose
2527 * c_rect has both coordinates set to the same point. Otherwise this parameter
2530 * @param priv The route graph map's private data
2531 * @param sel Here it's possible to specify a point for which to search. Please read the function's description.
2532 * @return A new map rect's private data
2534 static struct map_rect_priv *
2535 rp_rect_new(struct map_priv *priv, struct map_selection *sel)
2537 struct map_rect_priv * mr;
2540 if (! priv->route->graph || ! priv->route->graph->route_points)
2542 mr=g_new0(struct map_rect_priv, 1);
2544 mr->item.priv_data = mr;
2545 mr->item.type = type_rg_point;
2546 mr->item.meth = &methods_point_item;
2548 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)) {
2549 mr->coord_sel = g_malloc(sizeof(struct coord));
2550 *(mr->coord_sel) = sel->u.c_rect.lu;
2557 rm_rect_destroy(struct map_rect_priv *mr)
2561 if (mr->coord_sel) {
2562 g_free(mr->coord_sel);
2566 if (mr->path->update_required && !mr->path->in_use)
2567 route_path_update_done(mr->mpriv->route, mr->path->update_required-1);
2573 static struct item *
2574 rp_get_item(struct map_rect_priv *mr)
2576 struct route *r = mr->mpriv->route;
2577 struct route_graph_point *p = mr->point;
2578 struct route_graph_segment *seg = mr->rseg;
2580 if (mr->item.type == type_rg_point) {
2581 if (mr->coord_sel) {
2582 // We are supposed to return only the point at one specified coordinate...
2584 p = r->graph->hash[HASHCOORD(mr->coord_sel)];
2585 while ((p) && ((p->c.x != mr->coord_sel->x) || (p->c.y != mr->coord_sel->y))) {
2588 if ((!p) || !((p->c.x == mr->coord_sel->x) && (p->c.y == mr->coord_sel->y))) {
2589 mr->point = NULL; // This indicates that no point has been found
2591 mr->it = rp_iterator_new(p);
2598 p = r->graph->route_points;
2605 rm_coord_rewind(mr);
2609 mr->item.type = type_rg_segment;
2612 if (mr->coord_sel) {
2613 if (!mr->point) { // This means that no point has been found
2616 seg = rp_iterator_next(&(mr->it));
2619 seg=r->graph->route_segments;
2627 rm_coord_rewind(mr);
2635 static struct item *
2636 rp_get_item_byid(struct map_rect_priv *mr, int id_hi, int id_lo)
2638 struct item *ret=NULL;
2640 ret=rp_get_item(mr);
2645 static struct item *
2646 rm_get_item(struct map_rect_priv *mr)
2648 dbg(1,"enter\n", mr->pos);
2650 switch (mr->item.type) {
2652 mr->item.type=type_route_start;
2653 if (mr->mpriv->route->pos)
2656 mr->item.type=type_street_route;
2657 mr->seg=mr->seg_next;
2659 mr->seg_next=mr->seg->next;
2662 mr->item.type=type_route_end;
2663 if (mr->mpriv->route->dst)
2665 case type_route_end:
2674 static struct item *
2675 rm_get_item_byid(struct map_rect_priv *mr, int id_hi, int id_lo)
2677 struct item *ret=NULL;
2679 ret=rm_get_item(mr);
2683 static struct map_methods route_meth = {
2696 static struct map_methods route_graph_meth = {
2710 route_toggle_routegraph_display(struct route *route)
2712 if (route->flags & RF_SHOWGRAPH) {
2713 route->flags &= ~RF_SHOWGRAPH;
2715 route->flags |= RF_SHOWGRAPH;
2719 static struct map_priv *
2720 route_map_new_helper(struct map_methods *meth, struct attr **attrs, int graph)
2722 struct map_priv *ret;
2723 struct attr *route_attr;
2725 route_attr=attr_search(attrs, NULL, attr_route);
2728 ret=g_new0(struct map_priv, 1);
2730 *meth=route_graph_meth;
2733 ret->route=route_attr->u.route;
2738 static struct map_priv *
2739 route_map_new(struct map_methods *meth, struct attr **attrs)
2741 return route_map_new_helper(meth, attrs, 0);
2744 static struct map_priv *
2745 route_graph_map_new(struct map_methods *meth, struct attr **attrs)
2747 return route_map_new_helper(meth, attrs, 1);
2751 route_get_map_helper(struct route *this_, struct map **map, char *type, char *description)
2754 *map=map_new(NULL, (struct attr*[]){
2755 &(struct attr){attr_type,{type}},
2756 &(struct attr){attr_route,.u.route=this_},
2757 &(struct attr){attr_data,{""}},
2758 &(struct attr){attr_description,{description}},
2765 * @brief Returns a new map containing the route path
2767 * This function returns a new map containing the route path.
2769 * @important Do not map_destroy() this!
2771 * @param this_ The route to get the map of
2772 * @return A new map containing the route path
2775 route_get_map(struct route *this_)
2777 return route_get_map_helper(this_, &this_->map, "route","Route");
2782 * @brief Returns a new map containing the route graph
2784 * This function returns a new map containing the route graph.
2786 * @important Do not map_destroy() this!
2788 * @param this_ The route to get the map of
2789 * @return A new map containing the route graph
2792 route_get_graph_map(struct route *this_)
2794 return route_get_map_helper(this_, &this_->graph_map, "route_graph","Route Graph");
2798 route_set_projection(struct route *this_, enum projection pro)
2803 route_add_callback(struct route *this_, struct callback *cb)
2805 callback_list_add(this_->cbl, cb);
2809 route_remove_callback(struct route *this_, struct callback *cb)
2811 callback_list_remove(this_->cbl, cb);
2818 plugin_register_map_type("route", route_map_new);
2819 plugin_register_map_type("route_graph", route_graph_map_new);