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.
51 #include "glib_slice.h"
57 #include "projection.h"
63 #include "transform.h"
69 #include "vehicleprofile.h"
70 #include "roadprofile.h"
80 * @brief A point in the route graph
82 * This represents a point in the route graph. A point usually connects two or more segments,
83 * but there are also points which don't do that (e.g. at the end of a dead-end).
85 struct route_graph_point {
86 struct route_graph_point *hash_next; /**< Pointer to a chained hashlist of all route_graph_points with this hash */
87 struct route_graph_segment *start; /**< Pointer to a list of segments of which this point is the start. The links
88 * of this linked-list are in route_graph_segment->start_next.*/
89 struct route_graph_segment *end; /**< Pointer to a list of segments of which this pointer is the end. The links
90 * of this linked-list are in route_graph_segment->end_next. */
91 struct route_graph_segment *seg; /**< Pointer to the segment one should use to reach the destination at
93 struct fibheap_el *el; /**< When this point is put on a Fibonacci heap, this is a pointer
94 * to this point's heap-element */
95 int value; /**< The cost at which one can reach the destination from this point on */
96 struct coord c; /**< Coordinates of this point */
97 int flags; /**< Flags for this point (eg traffic distortion) */
100 #define RP_TRAFFIC_DISTORTION 1
101 #define RP_TURN_RESTRICTION 2
102 #define RP_TURN_RESTRICTION_RESOLVED 4
105 * @brief A segment in the route graph or path
107 * This is a segment in the route graph or path. A segment represents a driveable way.
110 struct route_segment_data {
111 struct item item; /**< The item (e.g. street) that this segment represents. */
113 int len; /**< Length of this segment */
114 /*NOTE: After a segment, various fields may follow, depending on what flags are set. Order of fields:
115 1.) maxspeed Maximum allowed speed on this segment. Present if AF_SPEED_LIMIT is set.
116 2.) offset If the item is segmented (i.e. represented by more than one segment), this
117 indicates the position of this segment in the item. Present if AF_SEGMENTED is set.
122 struct size_weight_limit {
130 #define RSD_OFFSET(x) *((int *)route_segment_data_field_pos((x), attr_offset))
131 #define RSD_MAXSPEED(x) *((int *)route_segment_data_field_pos((x), attr_maxspeed))
132 #define RSD_SIZE_WEIGHT(x) *((struct size_weight_limit *)route_segment_data_field_pos((x), attr_vehicle_width))
133 #define RSD_DANGEROUS_GOODS(x) *((int *)route_segment_data_field_pos((x), attr_vehicle_dangerous_goods))
136 struct route_graph_segment_data {
142 struct size_weight_limit size_weight;
147 * @brief A segment in the route graph
149 * This is a segment in the route graph. A segment represents a driveable way.
151 struct route_graph_segment {
152 struct route_graph_segment *next; /**< Linked-list pointer to a list of all route_graph_segments */
153 struct route_graph_segment *start_next; /**< Pointer to the next element in the list of segments that start at the
154 * same point. Start of this list is in route_graph_point->start. */
155 struct route_graph_segment *end_next; /**< Pointer to the next element in the list of segments that end at the
156 * same point. Start of this list is in route_graph_point->end. */
157 struct route_graph_point *start; /**< Pointer to the point this segment starts at. */
158 struct route_graph_point *end; /**< Pointer to the point this segment ends at. */
159 struct route_segment_data data; /**< The segment data */
163 * @brief A traffic distortion
165 * This is distortion in the traffic where you can't drive as fast as usual or have to wait for some time
167 struct route_traffic_distortion {
168 int maxspeed; /**< Maximum speed possible in km/h */
169 int delay; /**< Delay in tenths of seconds */
173 * @brief A segment in the route path
175 * This is a segment in the route path.
177 struct route_path_segment {
178 struct route_path_segment *next; /**< Pointer to the next segment in the path */
179 struct route_segment_data *data; /**< The segment data */
180 int direction; /**< Order in which the coordinates are ordered. >0 means "First
181 * coordinate of the segment is the first coordinate of the item", <=0
183 unsigned ncoords; /**< How many coordinates does this segment have? */
184 struct coord c[0]; /**< Pointer to the ncoords coordinates of this segment */
185 /* WARNING: There will be coordinates following here, so do not create new fields after c! */
189 * @brief Usually represents a destination or position
191 * This struct usually represents a destination or position
194 struct coord c; /**< The actual destination / position */
195 struct coord lp; /**< The nearest point on a street to c */
196 int pos; /**< The position of lp within the coords of the street */
197 int lenpos; /**< Distance between lp and the end of the street */
198 int lenneg; /**< Distance between lp and the start of the street */
199 int lenextra; /**< Distance between lp and c */
200 int percent; /**< ratio of lenneg to lenght of whole street in percent */
201 struct street_data *street; /**< The street lp is on */
202 int street_direction; /**< Direction of vehicle on street -1 = Negative direction, 1 = Positive direction, 0 = Unknown */
203 int dir; /**< Direction to take when following the route -1 = Negative direction, 1 = Positive direction */
207 * @brief A complete route path
209 * This structure describes a whole routing path
212 int in_use; /**< The path is in use and can not be updated */
213 int update_required; /**< The path needs to be updated after it is no longer in use */
214 int updated; /**< The path has only been updated */
215 int path_time; /**< Time to pass the path */
216 int path_len; /**< Length of the path */
217 struct route_path_segment *path; /**< The first segment in the path, i.e. the segment one should
219 struct route_path_segment *path_last; /**< The last segment in the path */
220 /* XXX: path_hash is not necessery now */
221 struct item_hash *path_hash; /**< A hashtable of all the items represented by this route's segements */
222 struct route_path *next; /**< Next route path in case of intermediate destinations */
226 * @brief A complete route
228 * This struct holds all information about a route.
231 struct mapset *ms; /**< The mapset this route is built upon */
233 struct route_info *pos; /**< Current position within this route */
234 GList *destinations; /**< Destinations of the route */
235 struct route_info *current_dst; /**< Current destination */
237 struct route_graph *graph; /**< Pointer to the route graph */
238 struct route_path *path2; /**< Pointer to the route path */
240 struct map *graph_map;
241 struct callback * route_graph_done_cb ; /**< Callback when route graph is done */
242 struct callback * route_graph_flood_done_cb ; /**< Callback when route graph flooding is done */
243 struct callback_list *cbl2; /**< Callback list to call when route changes */
244 int destination_distance; /**< Distance to the destination at which the destination is considered "reached" */
245 struct vehicleprofile *vehicleprofile; /**< Routing preferences */
246 int route_status; /**< Route Status */
247 int link_path; /**< Link paths over multiple waypoints together */
253 * @brief A complete route graph
255 * This structure describes a whole routing graph
258 int busy; /**< The graph is being built */
259 struct map_selection *sel; /**< The rectangle selection for the graph */
260 struct mapset_handle *h; /**< Handle to the mapset */
261 struct map *m; /**< Pointer to the currently active map */
262 struct map_rect *mr; /**< Pointer to the currently active map rectangle */
263 struct vehicleprofile *vehicleprofile; /**< The vehicle profile */
264 struct callback *idle_cb; /**< Idle callback to process the graph */
265 struct callback *done_cb; /**< Callback when graph is done */
266 struct event_idle *idle_ev; /**< The pointer to the idle event */
267 struct route_graph_segment *route_segments; /**< Pointer to the first route_graph_segment in the linked list of all segments */
268 #define HASH_SIZE 8192
269 struct route_graph_point *hash[HASH_SIZE]; /**< A hashtable containing all route_graph_points in this graph */
272 #define HASHCOORD(c) ((((c)->x +(c)->y) * 2654435761UL) & (HASH_SIZE-1))
275 * @brief Iterator to iterate through all route graph segments in a route graph point
277 * This structure can be used to iterate through all route graph segments connected to a
278 * route graph point. Use this with the rp_iterator_* functions.
280 struct route_graph_point_iterator {
281 struct route_graph_point *p; /**< The route graph point whose segments should be iterated */
282 int end; /**< Indicates if we have finished iterating through the "start" segments */
283 struct route_graph_segment *next; /**< The next segment to be returned */
292 static struct route_info * route_find_nearest_street(struct vehicleprofile *vehicleprofile, struct mapset *ms, struct pcoord *c);
293 static struct route_graph_point *route_graph_get_point(struct route_graph *this, struct coord *c);
294 static void route_graph_update(struct route *this, struct callback *cb, int async);
295 static void route_graph_build_done(struct route_graph *rg, int cancel);
296 static struct route_path *route_path_new(struct route_graph *this, struct route_path *oldpath, struct route_info *pos, struct route_info *dst, struct vehicleprofile *profile);
297 static void route_process_street_graph(struct route_graph *this, struct item *item, struct vehicleprofile *profile);
298 static void route_graph_destroy(struct route_graph *this);
299 static void route_path_update(struct route *this, int cancel, int async);
300 static int route_time_seg(struct vehicleprofile *profile, struct route_segment_data *over, struct route_traffic_distortion *dist);
301 static void route_graph_flood(struct route_graph *this, struct route_info *dst, struct vehicleprofile *profile, struct callback *cb);
302 static void route_graph_reset(struct route_graph *this);
306 * @brief Returns the projection used for this route
308 * @param route The route to return the projection for
309 * @return The projection used for this route
311 static enum projection route_projection(struct route *route)
313 struct street_data *street;
314 struct route_info *dst=route_get_dst(route);
315 if (!route->pos && !dst)
316 return projection_none;
317 street = route->pos ? route->pos->street : dst->street;
318 if (!street || !street->item.map)
319 return projection_none;
320 return map_projection(street->item.map);
324 * @brief Creates a new graph point iterator
326 * This function creates a new route graph point iterator, that can be used to
327 * iterate through all segments connected to the point.
329 * @param p The route graph point to create the iterator from
330 * @return A new iterator.
332 static struct route_graph_point_iterator
333 rp_iterator_new(struct route_graph_point *p)
335 struct route_graph_point_iterator it;
350 * @brief Gets the next segment connected to a route graph point from an iterator
352 * @param it The route graph point iterator to get the segment from
353 * @return The next segment or NULL if there are no more segments
355 static struct route_graph_segment
356 *rp_iterator_next(struct route_graph_point_iterator *it)
358 struct route_graph_segment *ret;
366 if (ret->start_next) {
367 it->next = ret->start_next;
369 it->next = it->p->end;
373 it->next = ret->end_next;
380 * @brief Checks if the last segment returned from a route_graph_point_iterator comes from the end
382 * @param it The route graph point iterator to be checked
383 * @return 1 if the last segment returned comes from the end of the route graph point, 0 otherwise
386 rp_iterator_end(struct route_graph_point_iterator *it) {
387 if (it->end && (it->next != it->p->end)) {
395 * @brief Destroys a route_path
397 * @param this The route_path to be destroyed
400 route_path_destroy(struct route_path *this, int recurse)
402 struct route_path_segment *c,*n;
403 struct route_path *next;
406 if (this->path_hash) {
407 item_hash_destroy(this->path_hash);
408 this->path_hash=NULL;
426 * @brief Creates a completely new route structure
428 * @param attrs Not used
429 * @return The newly created route
432 route_new(struct attr *parent, struct attr **attrs)
434 struct route *this=g_new0(struct route, 1);
435 struct attr dest_attr;
437 if (attr_generic_get_attr(attrs, NULL, attr_destination_distance, &dest_attr, NULL)) {
438 this->destination_distance = dest_attr.u.num;
440 this->destination_distance = 50; // Default value
442 this->cbl2=callback_list_new();
448 * @brief Checks if a segment is part of a roundabout
450 * This function checks if a segment is part of a roundabout.
452 * @param seg The segment to be checked
453 * @param level How deep to scan the route graph
454 * @param direction Set this to 1 if we're entering the segment through its end, to 0 otherwise
455 * @param origin Used internally, set to NULL
456 * @return 1 If a roundabout was detected, 0 otherwise
459 route_check_roundabout(struct route_graph_segment *seg, int level, int direction, struct route_graph_segment *origin)
461 struct route_graph_point_iterator it,it2;
462 struct route_graph_segment *cur;
468 if (!direction && !(seg->data.flags & AF_ONEWAY)) {
471 if (direction && !(seg->data.flags & AF_ONEWAYREV)) {
474 if (seg->data.flags & AF_ROUNDABOUT_VALID)
482 it = rp_iterator_new(seg->end);
484 it = rp_iterator_new(seg->start);
488 while ((cur = rp_iterator_next(&it2)))
493 cur = rp_iterator_next(&it);
496 cur = rp_iterator_next(&it);
500 if (cur->data.item.type != origin->data.item.type) {
501 // This street is of another type, can't be part of the roundabout
502 cur = rp_iterator_next(&it);
507 seg->data.flags |= AF_ROUNDABOUT;
511 if (route_check_roundabout(cur, (level-1), rp_iterator_end(&it), origin)) {
512 seg->data.flags |= AF_ROUNDABOUT;
516 cur = rp_iterator_next(&it);
523 * @brief Sets the mapset of the route passwd
525 * @param this The route to set the mapset for
526 * @param ms The mapset to set for this route
529 route_set_mapset(struct route *this, struct mapset *ms)
535 * @brief Sets the vehicle profile of a route
537 * @param this The route to set the profile for
538 * @param prof The vehicle profile
542 route_set_profile(struct route *this, struct vehicleprofile *prof)
544 if (this->vehicleprofile != prof) {
545 this->vehicleprofile=prof;
546 route_path_update(this, 1, 1);
551 * @brief Returns the mapset of the route passed
553 * @param this The route to get the mapset of
554 * @return The mapset of the route passed
557 route_get_mapset(struct route *this)
563 * @brief Returns the current position within the route passed
565 * @param this The route to get the position for
566 * @return The position within the route passed
569 route_get_pos(struct route *this)
575 * @brief Returns the destination of the route passed
577 * @param this The route to get the destination for
578 * @return The destination of the route passed
581 route_get_dst(struct route *this)
583 struct route_info *dst=NULL;
585 if (this->destinations)
586 dst=g_list_last(this->destinations)->data;
591 * @brief Checks if the path is calculated for the route passed
593 * @param this The route to check
594 * @return True if the path is calculated, false if not
597 route_get_path_set(struct route *this)
599 return this->path2 != NULL;
603 * @brief Checks if the route passed contains a certain item within the route path
605 * This function checks if a certain items exists in the path that navit will guide
606 * the user to his destination. It does *not* check if this item exists in the route
609 * @param this The route to check for this item
610 * @param item The item to search for
611 * @return True if the item was found, false if the item was not found or the route was not calculated
614 route_contains(struct route *this, struct item *item)
616 if (! this->path2 || !this->path2->path_hash)
618 if (item_hash_lookup(this->path2->path_hash, item))
620 if (! this->pos || !this->pos->street)
622 return item_is_equal(this->pos->street->item, *item);
626 static struct route_info *
627 route_next_destination(struct route *this)
629 if (!this->destinations)
631 return this->destinations->data;
635 * @brief Checks if a route has reached its destination
637 * @param this The route to be checked
638 * @return True if the destination is "reached", false otherwise.
641 route_destination_reached(struct route *this)
643 struct street_data *sd = NULL;
645 struct route_info *dst=route_next_destination(this);
652 sd = this->pos->street;
658 if (!item_is_equal(this->pos->street->item, dst->street->item)) {
662 if ((sd->flags & AF_ONEWAY) && (this->pos->lenneg >= dst->lenneg)) { // We would have to drive against the one-way road
665 if ((sd->flags & AF_ONEWAYREV) && (this->pos->lenpos >= dst->lenpos)) {
668 pro=route_projection(this);
669 if (pro == projection_none)
672 if (transform_distance(pro, &this->pos->c, &dst->lp) > this->destination_distance) {
676 if (g_list_next(this->destinations))
682 static struct route_info *
683 route_previous_destination(struct route *this)
685 GList *l=g_list_find(this->destinations, this->current_dst);
688 l=g_list_previous(l);
695 route_path_update_done(struct route *this, int new_graph)
697 struct route_path *oldpath=this->path2;
698 struct attr route_status;
699 struct route_info *prev_dst;
700 route_status.type=attr_route_status;
701 if (this->path2 && (this->path2->in_use>1)) {
702 this->path2->update_required=1+new_graph;
705 route_status.u.num=route_status_building_path;
706 route_set_attr(this, &route_status);
707 prev_dst=route_previous_destination(this);
708 if (this->link_path) {
709 this->path2=route_path_new(this->graph, NULL, prev_dst, this->current_dst, this->vehicleprofile);
711 this->path2->next=oldpath;
713 this->path2=route_path_new(this->graph, oldpath, prev_dst, this->current_dst, this->vehicleprofile);
714 if (oldpath && this->path2) {
715 this->path2->next=oldpath->next;
716 route_path_destroy(oldpath,0);
720 struct route_path_segment *seg=this->path2->path;
721 int path_time=0,path_len=0;
724 int seg_time=route_time_seg(this->vehicleprofile, seg->data, NULL);
725 if (seg_time == INT_MAX) {
729 path_len+=seg->data->len;
732 this->path2->path_time=path_time;
733 this->path2->path_len=path_len;
734 if (prev_dst != this->pos) {
736 this->current_dst=prev_dst;
737 route_graph_reset(this->graph);
738 route_graph_flood(this->graph, this->current_dst, this->vehicleprofile, this->route_graph_flood_done_cb);
741 if (!new_graph && this->path2->updated)
742 route_status.u.num=route_status_path_done_incremental;
744 route_status.u.num=route_status_path_done_new;
746 route_status.u.num=route_status_not_found;
748 route_set_attr(this, &route_status);
752 * @brief Updates the route graph and the route path if something changed with the route
754 * This will update the route graph and the route path of the route if some of the
755 * route's settings (destination, position) have changed.
757 * @attention For this to work the route graph has to be destroyed if the route's
758 * @attention destination is changed somewhere!
760 * @param this The route to update
763 route_path_update(struct route *this, int cancel, int async)
765 dbg(1,"enter %d\n", cancel);
766 if (! this->pos || ! this->destinations) {
768 route_path_destroy(this->path2,1);
773 route_graph_destroy(this->graph);
776 /* the graph is destroyed when setting the destination */
778 if (this->graph->busy) {
779 dbg(1,"busy building graph\n");
782 // we can try to update
783 dbg(1,"try update\n");
784 route_path_update_done(this, 0);
786 route_path_destroy(this->path2,1);
789 if (!this->graph || !this->path2) {
790 dbg(1,"rebuild graph\n");
791 if (! this->route_graph_flood_done_cb)
792 this->route_graph_flood_done_cb=callback_new_2(callback_cast(route_path_update_done), this, (long)1);
793 dbg(1,"route_graph_update\n");
794 route_graph_update(this, this->route_graph_flood_done_cb, async);
799 * @brief This will calculate all the distances stored in a route_info
801 * @param ri The route_info to calculate the distances for
802 * @param pro The projection used for this route
805 route_info_distances(struct route_info *ri, enum projection pro)
808 struct street_data *sd=ri->street;
809 /* 0 1 2 X 3 4 5 6 pos=2 npos=3 count=7 0,1,2 3,4,5,6*/
810 ri->lenextra=transform_distance(pro, &ri->lp, &ri->c);
811 ri->lenneg=transform_polyline_length(pro, sd->c, npos)+transform_distance(pro, &sd->c[ri->pos], &ri->lp);
812 ri->lenpos=transform_polyline_length(pro, sd->c+npos, sd->count-npos)+transform_distance(pro, &sd->c[npos], &ri->lp);
813 if (ri->lenneg || ri->lenpos)
814 ri->percent=(ri->lenneg*100)/(ri->lenneg+ri->lenpos);
820 * @brief This sets the current position of the route passed
822 * This will set the current position of the route passed to the street that is nearest to the
823 * passed coordinates. It also automatically updates the route.
825 * @param this The route to set the position of
826 * @param pos Coordinates to set as position
829 route_set_position(struct route *this, struct pcoord *pos)
832 route_info_free(this->pos);
834 this->pos=route_find_nearest_street(this->vehicleprofile, this->ms, pos);
836 // If there is no nearest street, bail out.
837 if (!this->pos) return;
839 this->pos->street_direction=0;
840 dbg(1,"this->pos=%p\n", this->pos);
841 route_info_distances(this->pos, pos->pro);
842 route_path_update(this, 0, 1);
846 * @brief Sets a route's current position based on coordinates from tracking
848 * @param this The route to set the current position of
849 * @param tracking The tracking to get the coordinates from
852 route_set_position_from_tracking(struct route *this, struct tracking *tracking, enum projection pro)
855 struct route_info *ret;
856 struct street_data *sd;
859 c=tracking_get_pos(tracking);
860 ret=g_new0(struct route_info, 1);
862 printf("%s:Out of memory\n", __FUNCTION__);
866 route_info_free(this->pos);
870 ret->pos=tracking_get_segment_pos(tracking);
871 ret->street_direction=tracking_get_street_direction(tracking);
872 sd=tracking_get_street_data(tracking);
874 ret->street=street_data_dup(sd);
875 route_info_distances(ret, pro);
877 dbg(3,"position 0x%x,0x%x item 0x%x,0x%x direction %d pos %d lenpos %d lenneg %d\n",c->x,c->y,sd?sd->item.id_hi:0,sd?sd->item.id_lo:0,ret->street_direction,ret->pos,ret->lenpos,ret->lenneg);
878 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?ret->street->item.id_hi:0, ret->street?ret->street->item.id_lo:0);
879 dbg(3,"street 0=(0x%x,0x%x) %d=(0x%x,0x%x)\n", ret->street?ret->street->c[0].x:0, ret->street?ret->street->c[0].y:0, ret->street?ret->street->count-1:0, ret->street?ret->street->c[ret->street->count-1].x:0, ret->street?ret->street->c[ret->street->count-1].y:0);
881 if (this->destinations)
882 route_path_update(this, 0, 1);
886 /* Used for debuging of route_rect, what routing sees */
887 struct map_selection *route_selection;
890 * @brief Returns a single map selection
892 struct map_selection *
893 route_rect(int order, struct coord *c1, struct coord *c2, int rel, int abs)
895 int dx,dy,sx=1,sy=1,d,m;
896 struct map_selection *sel=g_new(struct map_selection, 1);
898 printf("%s:Out of memory\n", __FUNCTION__);
902 sel->range.min=route_item_first;
903 sel->range.max=route_item_last;
904 dbg(1,"%p %p\n", c1, c2);
909 sel->u.c_rect.lu.x=c1->x;
910 sel->u.c_rect.rl.x=c2->x;
912 sel->u.c_rect.lu.x=c2->x;
913 sel->u.c_rect.rl.x=c1->x;
917 sel->u.c_rect.lu.y=c2->y;
918 sel->u.c_rect.rl.y=c1->y;
920 sel->u.c_rect.lu.y=c1->y;
921 sel->u.c_rect.rl.y=c2->y;
928 sel->u.c_rect.lu.x-=m;
929 sel->u.c_rect.rl.x+=m;
930 sel->u.c_rect.lu.y+=m;
931 sel->u.c_rect.rl.y-=m;
937 * @brief Returns a list of map selections useable to create a route graph
939 * Returns a list of map selections useable to get a map rect from which items can be
940 * retrieved to build a route graph. The selections are a rectangle with
941 * c1 and c2 as two corners.
943 * @param c1 Corner 1 of the rectangle
944 * @param c2 Corder 2 of the rectangle
946 static struct map_selection *
947 route_calc_selection(struct coord *c, int count)
949 struct map_selection *ret,*sel;
957 for (i = 1 ; i < count ; i++)
958 coord_rect_extend(&r, &c[i]);
959 sel=route_rect(4, &r.lu, &r.rl, 25, 0);
961 for (i = 0 ; i < count ; i++) {
962 sel->next=route_rect(8, &c[i], &c[i], 0, 40000);
964 sel->next=route_rect(18, &c[i], &c[i], 0, 10000);
967 /* route_selection=ret; */
972 * @brief Destroys a list of map selections
974 * @param sel Start of the list to be destroyed
977 route_free_selection(struct map_selection *sel)
979 struct map_selection *next;
989 route_clear_destinations(struct route *this_)
991 g_list_foreach(this_->destinations, (GFunc)route_info_free, NULL);
992 g_list_free(this_->destinations);
993 this_->destinations=NULL;
997 * @brief Sets the destination of a route
999 * This sets the destination of a route to the street nearest to the coordinates passed
1000 * and updates the route.
1002 * @param this The route to set the destination for
1003 * @param dst Coordinates to set as destination
1004 * @param count: Number of destinations (last one is final)
1005 * @param async: If set, do routing asynchronously
1009 route_set_destinations(struct route *this, struct pcoord *dst, int count, int async)
1011 struct attr route_status;
1012 struct route_info *dsti;
1014 route_status.type=attr_route_status;
1017 route_clear_destinations(this);
1019 for (i = 0 ; i < count ; i++) {
1020 dsti=route_find_nearest_street(this->vehicleprofile, this->ms, &dst[i]);
1022 route_info_distances(dsti, dst->pro);
1023 this->destinations=g_list_append(this->destinations, dsti);
1026 route_status.u.num=route_status_destination_set;
1028 route_status.u.num=route_status_no_destination;
1029 callback_list_call_attr_1(this->cbl2, attr_destination, this);
1030 route_set_attr(this, &route_status);
1031 profile(1,"find_nearest_street");
1033 /* The graph has to be destroyed and set to NULL, otherwise route_path_update() doesn't work */
1034 route_graph_destroy(this->graph);
1036 this->current_dst=route_get_dst(this);
1037 route_path_update(this, 1, async);
1042 route_get_destinations(struct route *this, struct pcoord *pc, int count)
1045 GList *l=this->destinations;
1046 while (l && ret < count) {
1047 struct route_info *dst=l->data;
1050 pc->pro=projection_mg; /* FIXME */
1059 route_set_destination(struct route *this, struct pcoord *dst, int async)
1061 route_set_destinations(this, dst, dst?1:0, async);
1065 route_remove_waypoint(struct route *this)
1067 struct route_path *path=this->path2;
1068 this->destinations=g_list_remove(this->destinations,this->destinations->data);
1069 this->path2=this->path2->next;
1070 route_path_destroy(path,0);
1071 if (!this->destinations)
1073 route_graph_reset(this->graph);
1074 this->current_dst=this->destinations->data;
1075 route_graph_flood(this->graph, this->current_dst, this->vehicleprofile, this->route_graph_flood_done_cb);
1080 * @brief Gets the route_graph_point with the specified coordinates
1082 * @param this The route in which to search
1083 * @param c Coordinates to search for
1084 * @param last The last route graph point returned to iterate over multiple points with the same coordinates
1085 * @return The point at the specified coordinates or NULL if not found
1087 static struct route_graph_point *
1088 route_graph_get_point_next(struct route_graph *this, struct coord *c, struct route_graph_point *last)
1090 struct route_graph_point *p;
1091 int seen=0,hashval=HASHCOORD(c);
1092 p=this->hash[hashval];
1094 if (p->c.x == c->x && p->c.y == c->y) {
1105 static struct route_graph_point *
1106 route_graph_get_point(struct route_graph *this, struct coord *c)
1108 return route_graph_get_point_next(this, c, NULL);
1112 * @brief Gets the last route_graph_point with the specified coordinates
1114 * @param this The route in which to search
1115 * @param c Coordinates to search for
1116 * @return The point at the specified coordinates or NULL if not found
1118 static struct route_graph_point *
1119 route_graph_get_point_last(struct route_graph *this, struct coord *c)
1121 struct route_graph_point *p,*ret=NULL;
1122 int hashval=HASHCOORD(c);
1123 p=this->hash[hashval];
1125 if (p->c.x == c->x && p->c.y == c->y)
1135 * @brief Create a new point for the route graph with the specified coordinates
1137 * @param this The route to insert the point into
1138 * @param f The coordinates at which the point should be created
1139 * @return The point created
1142 static struct route_graph_point *
1143 route_graph_point_new(struct route_graph *this, struct coord *f)
1146 struct route_graph_point *p;
1148 hashval=HASHCOORD(f);
1150 printf("p (0x%x,0x%x)\n", f->x, f->y);
1151 p=g_slice_new0(struct route_graph_point);
1152 p->hash_next=this->hash[hashval];
1153 this->hash[hashval]=p;
1160 * @brief Inserts a point into the route graph at the specified coordinates
1162 * This will insert a point into the route graph at the coordinates passed in f.
1163 * Note that the point is not yet linked to any segments.
1165 * @param this The route to insert the point into
1166 * @param f The coordinates at which the point should be inserted
1167 * @return The point inserted or NULL on failure
1169 static struct route_graph_point *
1170 route_graph_add_point(struct route_graph *this, struct coord *f)
1172 struct route_graph_point *p;
1174 p=route_graph_get_point(this,f);
1176 p=route_graph_point_new(this,f);
1181 * @brief Frees all the memory used for points in the route graph passed
1183 * @param this The route graph to delete all points from
1186 route_graph_free_points(struct route_graph *this)
1188 struct route_graph_point *curr,*next;
1190 for (i = 0 ; i < HASH_SIZE ; i++) {
1193 next=curr->hash_next;
1194 g_slice_free(struct route_graph_point, curr);
1202 * @brief Resets all nodes
1204 * @param this The route graph to reset
1207 route_graph_reset(struct route_graph *this)
1209 struct route_graph_point *curr;
1211 for (i = 0 ; i < HASH_SIZE ; i++) {
1214 curr->value=INT_MAX;
1217 curr=curr->hash_next;
1223 * @brief Returns the position of a certain field appended to a route graph segment
1225 * This function returns a pointer to a field that is appended to a route graph
1228 * @param seg The route graph segment the field is appended to
1229 * @param type Type of the field that should be returned
1230 * @return A pointer to a field of a certain type, or NULL if no such field is present
1233 route_segment_data_field_pos(struct route_segment_data *seg, enum attr_type type)
1237 ptr = ((unsigned char*)seg) + sizeof(struct route_segment_data);
1239 if (seg->flags & AF_SPEED_LIMIT) {
1240 if (type == attr_maxspeed)
1244 if (seg->flags & AF_SEGMENTED) {
1245 if (type == attr_offset)
1249 if (seg->flags & AF_SIZE_OR_WEIGHT_LIMIT) {
1250 if (type == attr_vehicle_width)
1252 ptr += sizeof(struct size_weight_limit);
1254 if (seg->flags & AF_DANGEROUS_GOODS) {
1255 if (type == attr_vehicle_dangerous_goods)
1263 * @brief Calculates the size of a route_segment_data struct with given flags
1265 * @param flags The flags of the route_segment_data
1269 route_segment_data_size(int flags)
1271 int ret=sizeof(struct route_segment_data);
1272 if (flags & AF_SPEED_LIMIT)
1274 if (flags & AF_SEGMENTED)
1276 if (flags & AF_SIZE_OR_WEIGHT_LIMIT)
1277 ret+=sizeof(struct size_weight_limit);
1278 if (flags & AF_DANGEROUS_GOODS)
1285 route_graph_segment_is_duplicate(struct route_graph_point *start, struct route_graph_segment_data *data)
1287 struct route_graph_segment *s;
1290 if (item_is_equal(*data->item, s->data.item)) {
1291 if (data->flags & AF_SEGMENTED) {
1292 if (RSD_OFFSET(&s->data) == data->offset) {
1304 * @brief Inserts a new segment into the route graph
1306 * This function performs a check if a segment for the item specified already exists, and inserts
1307 * a new segment representing this item if it does not.
1309 * @param this The route graph to insert the segment into
1310 * @param start The graph point which should be connected to the start of this segment
1311 * @param end The graph point which should be connected to the end of this segment
1312 * @param len The length of this segment
1313 * @param item The item that is represented by this segment
1314 * @param flags Flags for this segment
1315 * @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
1316 * @param maxspeed The maximum speed allowed on this segment in km/h. -1 if not known.
1319 route_graph_add_segment(struct route_graph *this, struct route_graph_point *start,
1320 struct route_graph_point *end, struct route_graph_segment_data *data)
1322 struct route_graph_segment *s;
1325 size = sizeof(struct route_graph_segment)-sizeof(struct route_segment_data)+route_segment_data_size(data->flags);
1326 s = g_slice_alloc0(size);
1328 printf("%s:Out of memory\n", __FUNCTION__);
1332 s->start_next=start->start;
1335 s->end_next=end->end;
1337 dbg_assert(data->len >= 0);
1338 s->data.len=data->len;
1339 s->data.item=*data->item;
1340 s->data.flags=data->flags;
1342 if (data->flags & AF_SPEED_LIMIT)
1343 RSD_MAXSPEED(&s->data)=data->maxspeed;
1344 if (data->flags & AF_SEGMENTED)
1345 RSD_OFFSET(&s->data)=data->offset;
1346 if (data->flags & AF_SIZE_OR_WEIGHT_LIMIT)
1347 RSD_SIZE_WEIGHT(&s->data)=data->size_weight;
1348 if (data->flags & AF_DANGEROUS_GOODS)
1349 RSD_DANGEROUS_GOODS(&s->data)=data->dangerous_goods;
1351 s->next=this->route_segments;
1352 this->route_segments=s;
1354 printf("l (0x%x,0x%x)-(0x%x,0x%x)\n", start->c.x, start->c.y, end->c.x, end->c.y);
1358 * @brief Gets all the coordinates of an item
1360 * This will get all the coordinates of the item i and return them in c,
1361 * up to max coordinates. Additionally it is possible to limit the coordinates
1362 * returned to all the coordinates of the item between the two coordinates
1365 * @important Make sure that whatever c points to has enough memory allocated
1366 * @important to hold max coordinates!
1368 * @param i The item to get the coordinates of
1369 * @param c Pointer to memory allocated for holding the coordinates
1370 * @param max Maximum number of coordinates to return
1371 * @param start First coordinate to get
1372 * @param end Last coordinate to get
1373 * @return The number of coordinates returned
1375 static int get_item_seg_coords(struct item *i, struct coord *c, int max,
1376 struct coord *start, struct coord *end)
1378 struct map_rect *mr;
1382 mr=map_rect_new(i->map, NULL);
1385 item = map_rect_get_item_byid(mr, i->id_hi, i->id_lo);
1387 rc = item_coord_get(item, &c1, 1);
1388 while (rc && (c1.x != start->x || c1.y != start->y)) {
1389 rc = item_coord_get(item, &c1, 1);
1391 while (rc && p < max) {
1393 if (c1.x == end->x && c1.y == end->y)
1395 rc = item_coord_get(item, &c1, 1);
1398 map_rect_destroy(mr);
1403 * @brief Returns and removes one segment from a path
1405 * @param path The path to take the segment from
1406 * @param item The item whose segment to remove
1407 * @param offset Offset of the segment within the item to remove. If the item is not segmented this should be 1.
1408 * @return The segment removed
1410 static struct route_path_segment *
1411 route_extract_segment_from_path(struct route_path *path, struct item *item,
1415 struct route_path_segment *sp = NULL, *s;
1418 if (item_is_equal(s->data->item,*item)) {
1419 if (s->data->flags & AF_SEGMENTED)
1420 soffset=RSD_OFFSET(s->data);
1423 if (soffset == offset) {
1428 path->path = s->next;
1437 item_hash_remove(path->path_hash, item);
1442 * @brief Adds a segment and the end of a path
1444 * @param this The path to add the segment to
1445 * @param segment The segment to add
1448 route_path_add_segment(struct route_path *this, struct route_path_segment *segment)
1452 if (this->path_last)
1453 this->path_last->next=segment;
1454 this->path_last=segment;
1458 * @brief Adds a two coordinate line to a path
1460 * This adds a new line to a path, creating a new segment for it.
1462 * @param this The path to add the item to
1463 * @param start coordinate to add to the start of the item. If none should be added, make this NULL.
1464 * @param end coordinate to add to the end of the item. If none should be added, make this NULL.
1465 * @param len The length of the item
1468 route_path_add_line(struct route_path *this, struct coord *start, struct coord *end, int len)
1471 struct route_path_segment *segment;
1472 int seg_size,seg_dat_size;
1474 dbg(1,"line from 0x%x,0x%x-0x%x,0x%x\n", start->x, start->y, end->x, end->y);
1475 seg_size=sizeof(*segment) + sizeof(struct coord) * ccnt;
1476 seg_dat_size=sizeof(struct route_segment_data);
1477 segment=g_malloc0(seg_size + seg_dat_size);
1478 segment->data=(struct route_segment_data *)((char *)segment+seg_size);
1479 segment->ncoords=ccnt;
1480 segment->direction=0;
1481 segment->c[0]=*start;
1483 segment->data->len=len;
1484 route_path_add_segment(this, segment);
1488 * @brief Inserts a new item into the path
1490 * This function does almost the same as "route_path_add_item()", but identifies
1491 * the item to add by a segment from the route graph. Another difference is that it "copies" the
1492 * segment from the route graph, i.e. if the item is segmented, only the segment passed in rgs will
1493 * be added to the route path, not all segments of the item.
1495 * The function can be sped up by passing an old path already containing this segment in oldpath -
1496 * the segment will then be extracted from this old path. Please note that in this case the direction
1497 * parameter has no effect.
1499 * @param this The path to add the item to
1500 * @param oldpath Old path containing the segment to be added. Speeds up the function, but can be NULL.
1501 * @param rgs Segment of the route graph that should be "copied" to the route path
1502 * @param dir Order in which to add the coordinates. See route_path_add_item()
1503 * @param pos Information about start point if this is the first segment
1504 * @param dst Information about end point if this is the last segment
1508 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)
1510 struct route_path_segment *segment;
1511 int i, ccnt, extra=0, ret=0;
1512 struct coord *c,*cd,ca[2048];
1514 int seg_size,seg_dat_size;
1515 int len=rgs->data.len;
1516 if (rgs->data.flags & AF_SEGMENTED)
1517 offset=RSD_OFFSET(&rgs->data);
1519 dbg(1,"enter (0x%x,0x%x) dir=%d pos=%p dst=%p\n", rgs->data.item.id_hi, rgs->data.item.id_lo, dir, pos, dst);
1521 segment=item_hash_lookup(oldpath->path_hash, &rgs->data.item);
1522 if (segment && segment->direction == dir) {
1523 segment = route_extract_segment_from_path(oldpath, &rgs->data.item, offset);
1535 if (dst->lenneg >= pos->lenneg) {
1537 ccnt=dst->pos-pos->pos;
1538 c=pos->street->c+pos->pos+1;
1539 len=dst->lenneg-pos->lenneg;
1542 ccnt=pos->pos-dst->pos;
1543 c=pos->street->c+dst->pos+1;
1544 len=pos->lenneg-dst->lenneg;
1548 dbg(1,"pos dir=%d\n", dir);
1549 dbg(1,"pos pos=%d\n", pos->pos);
1550 dbg(1,"pos count=%d\n", pos->street->count);
1552 c=pos->street->c+pos->pos+1;
1553 ccnt=pos->street->count-pos->pos-1;
1564 dbg(1,"dst dir=%d\n", dir);
1565 dbg(1,"dst pos=%d\n", dst->pos);
1571 c=dst->street->c+dst->pos+1;
1572 ccnt=dst->street->count-dst->pos-1;
1576 ccnt=get_item_seg_coords(&rgs->data.item, ca, 2047, &rgs->start->c, &rgs->end->c);
1579 seg_size=sizeof(*segment) + sizeof(struct coord) * (ccnt + extra);
1580 seg_dat_size=route_segment_data_size(rgs->data.flags);
1581 segment=g_malloc0(seg_size + seg_dat_size);
1582 segment->data=(struct route_segment_data *)((char *)segment+seg_size);
1583 segment->direction=dir;
1585 if (pos && (c[0].x != pos->lp.x || c[0].y != pos->lp.y))
1589 for (i = 0 ; i < ccnt ; i++) {
1593 segment->ncoords+=ccnt;
1594 if (dst && (cd[-1].x != dst->lp.x || cd[-1].y != dst->lp.y))
1596 segment->ncoords=cd-segment->c;
1597 if (segment->ncoords <= 1) {
1602 /* We check if the route graph segment is part of a roundabout here, because this
1603 * only matters for route graph segments which form parts of the route path */
1604 if (!(rgs->data.flags & AF_ROUNDABOUT)) { // We identified this roundabout earlier
1605 route_check_roundabout(rgs, 13, (dir < 1), NULL);
1608 memcpy(segment->data, &rgs->data, seg_dat_size);
1610 segment->data->len=len;
1612 item_hash_insert(this->path_hash, &rgs->data.item, segment);
1614 route_path_add_segment(this, segment);
1620 * @brief Destroys all segments of a route graph
1622 * @param this The graph to destroy all segments from
1625 route_graph_free_segments(struct route_graph *this)
1627 struct route_graph_segment *curr,*next;
1629 curr=this->route_segments;
1632 size = sizeof(struct route_graph_segment)-sizeof(struct route_segment_data)+route_segment_data_size(curr->data.flags);
1633 g_slice_free1(size, curr);
1636 this->route_segments=NULL;
1640 * @brief Destroys a route graph
1642 * @param this The route graph to be destroyed
1645 route_graph_destroy(struct route_graph *this)
1648 route_graph_build_done(this, 1);
1649 route_graph_free_points(this);
1650 route_graph_free_segments(this);
1656 * @brief Returns the estimated speed on a segment
1658 * This function returns the estimated speed to be driven on a segment, 0=not passable
1660 * @param profile The routing preferences
1661 * @param over The segment which is passed
1662 * @param dist A traffic distortion if applicable
1663 * @return The estimated speed
1666 route_seg_speed(struct vehicleprofile *profile, struct route_segment_data *over, struct route_traffic_distortion *dist)
1668 struct roadprofile *roadprofile=vehicleprofile_get_roadprofile(profile, over->item.type);
1670 if (!roadprofile || !roadprofile->route_weight)
1672 /* maxspeed_handling: 0=always, 1 only if maxspeed restricts the speed, 2 never */
1673 speed=roadprofile->route_weight;
1674 if (profile->maxspeed_handling != 2) {
1675 if (over->flags & AF_SPEED_LIMIT) {
1676 maxspeed=RSD_MAXSPEED(over);
1677 if (!profile->maxspeed_handling)
1681 if (dist && maxspeed > dist->maxspeed)
1682 maxspeed=dist->maxspeed;
1683 if (maxspeed != INT_MAX && (profile->maxspeed_handling != 1 || maxspeed < speed))
1686 if (over->flags & AF_DANGEROUS_GOODS) {
1687 if (profile->dangerous_goods & RSD_DANGEROUS_GOODS(over))
1690 if (over->flags & AF_SIZE_OR_WEIGHT_LIMIT) {
1691 struct size_weight_limit *size_weight=&RSD_SIZE_WEIGHT(over);
1692 if (size_weight->width != -1 && profile->width != -1 && profile->width > size_weight->width)
1694 if (size_weight->height != -1 && profile->height != -1 && profile->height > size_weight->height)
1696 if (size_weight->length != -1 && profile->length != -1 && profile->length > size_weight->length)
1698 if (size_weight->weight != -1 && profile->weight != -1 && profile->weight > size_weight->weight)
1700 if (size_weight->axle_weight != -1 && profile->axle_weight != -1 && profile->axle_weight > size_weight->axle_weight)
1707 * @brief Returns the time needed to drive len on item
1709 * This function returns the time needed to drive len meters on
1710 * the item passed in item in tenth of seconds.
1712 * @param profile The routing preferences
1713 * @param over The segment which is passed
1714 * @param dist A traffic distortion if applicable
1715 * @return The time needed to drive len on item in thenth of senconds
1719 route_time_seg(struct vehicleprofile *profile, struct route_segment_data *over, struct route_traffic_distortion *dist)
1721 int speed=route_seg_speed(profile, over, dist);
1724 return over->len*36/speed+(dist ? dist->delay : 0);
1728 route_get_traffic_distortion(struct route_graph_segment *seg, struct route_traffic_distortion *ret)
1730 struct route_graph_point *start=seg->start;
1731 struct route_graph_point *end=seg->end;
1732 struct route_graph_segment *tmp,*found=NULL;
1734 while (tmp && !found) {
1735 if (tmp->data.item.type == type_traffic_distortion && tmp->start == start && tmp->end == end)
1737 tmp=tmp->start_next;
1740 while (tmp && !found) {
1741 if (tmp->data.item.type == type_traffic_distortion && tmp->end == start && tmp->start == end)
1746 ret->delay=found->data.len;
1747 if (found->data.flags & AF_SPEED_LIMIT)
1748 ret->maxspeed=RSD_MAXSPEED(&found->data);
1750 ret->maxspeed=INT_MAX;
1757 route_through_traffic_allowed(struct vehicleprofile *profile, struct route_graph_segment *seg)
1759 return (seg->data.flags & AF_THROUGH_TRAFFIC_LIMIT) == 0;
1763 * @brief Returns the "costs" of driving from point from over segment over in direction dir
1765 * @param profile The routing preferences
1766 * @param from The point where we are starting
1767 * @param over The segment we are using
1768 * @param dir The direction of segment which we are driving
1769 * @return The "costs" needed to drive len on item
1773 route_value_seg(struct vehicleprofile *profile, struct route_graph_point *from, struct route_graph_segment *over, int dir)
1776 struct route_traffic_distortion dist,*distp=NULL;
1778 dbg(0,"flags 0x%x mask 0x%x flags 0x%x\n", over->flags, dir >= 0 ? profile->flags_forward_mask : profile->flags_reverse_mask, profile->flags);
1780 if ((over->data.flags & (dir >= 0 ? profile->flags_forward_mask : profile->flags_reverse_mask)) != profile->flags)
1782 if (dir > 0 && (over->start->flags & RP_TURN_RESTRICTION))
1784 if (dir < 0 && (over->end->flags & RP_TURN_RESTRICTION))
1786 if (from && from->seg == over)
1788 if ((over->start->flags & RP_TRAFFIC_DISTORTION) && (over->end->flags & RP_TRAFFIC_DISTORTION) &&
1789 route_get_traffic_distortion(over, &dist)) {
1792 ret=route_time_seg(profile, &over->data, distp);
1795 if (!route_through_traffic_allowed(profile, over) && from && route_through_traffic_allowed(profile, from->seg))
1796 ret+=profile->through_traffic_penalty;
1801 * @brief Adds a route distortion item to the route graph
1803 * @param this The route graph to add to
1804 * @param item The item to add
1807 route_process_traffic_distortion(struct route_graph *this, struct item *item)
1809 struct route_graph_point *s_pnt,*e_pnt;
1811 struct attr delay_attr, maxspeed_attr;
1812 struct route_graph_segment_data data;
1818 data.maxspeed = INT_MAX;
1820 if (item_coord_get(item, &l, 1)) {
1821 s_pnt=route_graph_add_point(this,&l);
1822 while (item_coord_get(item, &c, 1)) {
1825 e_pnt=route_graph_add_point(this,&l);
1826 s_pnt->flags |= RP_TRAFFIC_DISTORTION;
1827 e_pnt->flags |= RP_TRAFFIC_DISTORTION;
1828 if (item_attr_get(item, attr_maxspeed, &maxspeed_attr)) {
1829 data.flags |= AF_SPEED_LIMIT;
1830 data.maxspeed=maxspeed_attr.u.num;
1832 if (item_attr_get(item, attr_delay, &delay_attr))
1833 data.len=delay_attr.u.num;
1834 route_graph_add_segment(this, s_pnt, e_pnt, &data);
1839 * @brief Adds a route distortion item to the route graph
1841 * @param this The route graph to add to
1842 * @param item The item to add
1845 route_process_turn_restriction(struct route_graph *this, struct item *item)
1847 struct route_graph_point *pnt[4];
1850 struct route_graph_segment_data data;
1852 count=item_coord_get(item, c, 5);
1853 if (count != 3 && count != 4) {
1854 dbg(0,"wrong count %d\n",count);
1859 for (i = 0 ; i < count ; i++)
1860 pnt[i]=route_graph_add_point(this,&c[i]);
1861 dbg(1,"%s: (0x%x,0x%x)-(0x%x,0x%x)-(0x%x,0x%x) %p-%p-%p\n",item_to_name(item->type),c[0].x,c[0].y,c[1].x,c[1].y,c[2].x,c[2].y,pnt[0],pnt[1],pnt[2]);
1865 route_graph_add_segment(this, pnt[0], pnt[1], &data);
1866 route_graph_add_segment(this, pnt[1], pnt[2], &data);
1869 pnt[1]->flags |= RP_TURN_RESTRICTION;
1870 pnt[2]->flags |= RP_TURN_RESTRICTION;
1871 route_graph_add_segment(this, pnt[2], pnt[3], &data);
1873 pnt[1]->flags |= RP_TURN_RESTRICTION;
1878 * @brief Adds an item to the route graph
1880 * This adds an item (e.g. a street) to the route graph, creating as many segments as needed for a
1883 * @param this The route graph to add to
1884 * @param item The item to add
1885 * @param profile The vehicle profile currently in use
1888 route_process_street_graph(struct route_graph *this, struct item *item, struct vehicleprofile *profile)
1896 struct roadprofile *roadp;
1897 struct route_graph_point *s_pnt,*e_pnt;
1900 struct route_graph_segment_data data;
1906 roadp = vehicleprofile_get_roadprofile(profile, item->type);
1908 // Don't include any roads that don't have a road profile in our vehicle profile
1912 if (item_coord_get(item, &l, 1)) {
1913 int *default_flags=item_get_default_flags(item->type);
1914 if (! default_flags)
1916 if (item_attr_get(item, attr_flags, &attr)) {
1917 data.flags = attr.u.num;
1918 if (data.flags & AF_SEGMENTED)
1921 data.flags = *default_flags;
1924 if (data.flags & AF_SPEED_LIMIT) {
1925 if (item_attr_get(item, attr_maxspeed, &attr))
1926 data.maxspeed = attr.u.num;
1928 if (data.flags & AF_DANGEROUS_GOODS) {
1929 if (item_attr_get(item, attr_vehicle_dangerous_goods, &attr))
1930 data.dangerous_goods = attr.u.num;
1932 data.flags &= ~AF_DANGEROUS_GOODS;
1934 if (data.flags & AF_SIZE_OR_WEIGHT_LIMIT) {
1935 if (item_attr_get(item, attr_vehicle_width, &attr))
1936 data.size_weight.width=attr.u.num;
1938 data.size_weight.width=-1;
1939 if (item_attr_get(item, attr_vehicle_height, &attr))
1940 data.size_weight.height=attr.u.num;
1942 data.size_weight.height=-1;
1943 if (item_attr_get(item, attr_vehicle_length, &attr))
1944 data.size_weight.length=attr.u.num;
1946 data.size_weight.length=-1;
1947 if (item_attr_get(item, attr_vehicle_weight, &attr))
1948 data.size_weight.weight=attr.u.num;
1950 data.size_weight.weight=-1;
1951 if (item_attr_get(item, attr_vehicle_axle_weight, &attr))
1952 data.size_weight.axle_weight=attr.u.num;
1954 data.size_weight.axle_weight=-1;
1957 s_pnt=route_graph_add_point(this,&l);
1959 while (item_coord_get(item, &c, 1)) {
1960 len+=transform_distance(map_projection(item->map), &l, &c);
1963 e_pnt=route_graph_add_point(this,&l);
1964 dbg_assert(len >= 0);
1966 if (!route_graph_segment_is_duplicate(s_pnt, &data))
1967 route_graph_add_segment(this, s_pnt, e_pnt, &data);
1972 isseg = item_coord_is_node(item);
1973 rc = item_coord_get(item, &c, 1);
1975 len+=transform_distance(map_projection(item->map), &l, &c);
1978 e_pnt=route_graph_add_point(this,&l);
1980 if (!route_graph_segment_is_duplicate(s_pnt, &data))
1981 route_graph_add_segment(this, s_pnt, e_pnt, &data);
1983 s_pnt=route_graph_add_point(this,&l);
1988 e_pnt=route_graph_add_point(this,&l);
1989 dbg_assert(len >= 0);
1992 if (!route_graph_segment_is_duplicate(s_pnt, &data))
1993 route_graph_add_segment(this, s_pnt, e_pnt, &data);
1998 static struct route_graph_segment *
1999 route_graph_get_segment(struct route_graph *graph, struct street_data *sd, struct route_graph_segment *last)
2001 struct route_graph_point *start=NULL;
2002 struct route_graph_segment *s;
2005 while ((start=route_graph_get_point_next(graph, &sd->c[0], start))) {
2008 if (item_is_equal(sd->item, s->data.item)) {
2021 * @brief Calculates the routing costs for each point
2023 * This function is the heart of routing. It assigns each point in the route graph a
2024 * cost at which one can reach the destination from this point on. Additionally it assigns
2025 * each point a segment one should follow from this point on to reach the destination at the
2028 * This function uses Dijkstra's algorithm to do the routing. To understand it you should have a look
2029 * at this algorithm.
2032 route_graph_flood(struct route_graph *this, struct route_info *dst, struct vehicleprofile *profile, struct callback *cb)
2034 struct route_graph_point *p_min;
2035 struct route_graph_segment *s=NULL;
2037 struct fibheap *heap; /* This heap will hold all points with "temporarily" calculated costs */
2039 heap = fh_makekeyheap();
2041 while ((s=route_graph_get_segment(this, dst->street, s))) {
2042 val=route_value_seg(profile, NULL, s, -1);
2043 if (val != INT_MAX) {
2044 val=val*(100-dst->percent)/100;
2047 s->end->el=fh_insertkey(heap, s->end->value, s->end);
2049 val=route_value_seg(profile, NULL, s, 1);
2050 if (val != INT_MAX) {
2051 val=val*dst->percent/100;
2053 s->start->value=val;
2054 s->start->el=fh_insertkey(heap, s->start->value, s->start);
2058 p_min=fh_extractmin(heap); /* Starting Dijkstra by selecting the point with the minimum costs on the heap */
2059 if (! p_min) /* There are no more points with temporarily calculated costs, Dijkstra has finished */
2063 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);
2064 p_min->el=NULL; /* This point is permanently calculated now, we've taken it out of the heap */
2066 while (s) { /* Iterating all the segments leading away from our point to update the points at their ends */
2067 val=route_value_seg(profile, p_min, s, -1);
2068 if (val != INT_MAX && !item_is_equal(s->data.item,p_min->seg->data.item)) {
2071 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);
2072 if (new < s->end->value) { /* We've found a less costly way to reach the end of s, update it */
2077 printf("insert_end p=%p el=%p val=%d ", s->end, s->end->el, s->end->value);
2078 s->end->el=fh_insertkey(heap, new, s->end);
2080 printf("el new=%p\n", s->end->el);
2084 printf("replace_end p=%p el=%p val=%d\n", s->end, s->end->el, s->end->value);
2085 fh_replacekey(heap, s->end->el, new);
2094 while (s) { /* Doing the same as above with the segments leading towards our point */
2095 val=route_value_seg(profile, p_min, s, 1);
2096 if (val != INT_MAX && !item_is_equal(s->data.item,p_min->seg->data.item)) {
2099 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);
2100 if (new < s->start->value) {
2101 s->start->value=new;
2103 if (! s->start->el) {
2105 printf("insert_start p=%p el=%p val=%d ", s->start, s->start->el, s->start->value);
2106 s->start->el=fh_insertkey(heap, new, s->start);
2108 printf("el new=%p\n", s->start->el);
2112 printf("replace_start p=%p el=%p val=%d\n", s->start, s->start->el, s->start->value);
2113 fh_replacekey(heap, s->start->el, new);
2122 fh_deleteheap(heap);
2123 callback_call_0(cb);
2128 * @brief Starts an "offroad" path
2130 * This starts a path that is not located on a street. It creates a new route path
2131 * adding only one segment, that leads from pos to dest, and which is not associated with an item.
2133 * @param this Not used
2134 * @param pos The starting position for the new path
2135 * @param dst The destination of the new path
2136 * @param dir Not used
2137 * @return The new path
2139 static struct route_path *
2140 route_path_new_offroad(struct route_graph *this, struct route_info *pos, struct route_info *dst)
2142 struct route_path *ret;
2144 ret=g_new0(struct route_path, 1);
2146 ret->path_hash=item_hash_new();
2147 route_path_add_line(ret, &pos->c, &dst->c, pos->lenextra+dst->lenextra);
2154 * @brief Returns a coordinate at a given distance
2156 * This function returns the coordinate, where the user will be if he
2157 * follows the current route for a certain distance.
2159 * @param this_ The route we're driving upon
2160 * @param dist The distance in meters
2161 * @return The coordinate where the user will be in that distance
2164 route_get_coord_dist(struct route *this_, int dist)
2169 struct route_path_segment *cur;
2171 enum projection pro=route_projection(this_);
2172 struct route_info *dst=route_get_dst(this_);
2176 if (!this_->path2 || pro == projection_none) {
2177 return this_->pos->c;
2180 ret = this_->pos->c;
2181 cur = this_->path2->path;
2183 if (cur->data->len < d) {
2184 d -= cur->data->len;
2186 for (i=0; i < (cur->ncoords-1); i++) {
2188 len = (int)transform_polyline_length(pro, (cur->c + i), 2);
2191 // We interpolate a bit here...
2192 frac = (double)l / len;
2194 dx = (cur->c + i + 1)->x - (cur->c + i)->x;
2195 dy = (cur->c + i + 1)->y - (cur->c + i)->y;
2197 ret.x = (cur->c + i)->x + (frac * dx);
2198 ret.y = (cur->c + i)->y + (frac * dy);
2202 return cur->c[(cur->ncoords-1)];
2211 * @brief Creates a new route path
2213 * This creates a new non-trivial route. It therefore needs the routing information created by route_graph_flood, so
2214 * make sure to run route_graph_flood() after changing the destination before using this function.
2216 * @param this The route graph to create the route from
2217 * @param oldpath (Optional) old path which may contain parts of the new part - this speeds things up a bit. May be NULL.
2218 * @param pos The starting position of the route
2219 * @param dst The destination of the route
2220 * @param preferences The routing preferences
2221 * @return The new route path
2223 static struct route_path *
2224 route_path_new(struct route_graph *this, struct route_path *oldpath, struct route_info *pos, struct route_info *dst, struct vehicleprofile *profile)
2226 struct route_graph_segment *s=NULL,*s1=NULL,*s2=NULL;
2227 struct route_graph_point *start;
2228 struct route_info *posinfo, *dstinfo;
2230 int val1=INT_MAX,val2=INT_MAX;
2231 int val,val1_new,val2_new;
2232 struct route_path *ret;
2234 if (! pos->street || ! dst->street) {
2235 dbg(0,"pos or dest not set\n");
2239 if (profile->mode == 2 || (profile->mode == 0 && pos->lenextra + dst->lenextra > transform_distance(map_projection(pos->street->item.map), &pos->c, &dst->c)))
2240 return route_path_new_offroad(this, pos, dst);
2241 while ((s=route_graph_get_segment(this, pos->street, s))) {
2242 val=route_value_seg(profile, NULL, s, 1);
2243 if (val != INT_MAX && s->end->value != INT_MAX) {
2244 val=val*(100-pos->percent)/100;
2245 val1_new=s->end->value+val;
2246 if (val1_new < val1) {
2251 val=route_value_seg(profile, NULL, s, -1);
2252 if (val != INT_MAX && s->start->value != INT_MAX) {
2253 val=val*pos->percent/100;
2254 val2_new=s->start->value+val;
2255 if (val2_new < val2) {
2261 if (val1 == INT_MAX && val2 == INT_MAX) {
2262 dbg(0,"no route found, pos blocked\n");
2266 val1=s1->end->value;
2267 val2=s2->start->value;
2276 ret=g_new0(struct route_path, 1);
2280 route_path_add_line(ret, &pos->c, &pos->lp, pos->lenextra);
2281 ret->path_hash=item_hash_new();
2284 while (s && !dstinfo) { /* following start->seg, which indicates the least costly way to reach our destination */
2287 printf("start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
2289 if (s->start == start) {
2290 if (item_is_equal(s->data.item, dst->street->item) && (s->end->seg == s || !posinfo))
2292 if (!route_path_add_item_from_graph(ret, oldpath, s, 1, posinfo, dstinfo))
2296 if (item_is_equal(s->data.item, dst->street->item) && (s->start->seg == s || !posinfo))
2298 if (!route_path_add_item_from_graph(ret, oldpath, s, -1, posinfo, dstinfo))
2306 route_path_add_line(ret, &dst->lp, &dst->c, dst->lenextra);
2307 dbg(1, "%d segments\n", segs);
2312 route_graph_build_next_map(struct route_graph *rg)
2315 rg->m=mapset_next(rg->h, 2);
2318 map_rect_destroy(rg->mr);
2319 rg->mr=map_rect_new(rg->m, rg->sel);
2327 is_turn_allowed(struct route_graph_point *p, struct route_graph_segment *from, struct route_graph_segment *to)
2329 struct route_graph_point *prev,*next;
2330 struct route_graph_segment *tmp1,*tmp2;
2331 if (item_is_equal(from->data.item, to->data.item))
2333 if (from->start == p)
2343 if (tmp1->start->c.x == prev->c.x && tmp1->start->c.y == prev->c.y &&
2344 (tmp1->data.item.type == type_street_turn_restriction_no ||
2345 tmp1->data.item.type == type_street_turn_restriction_only)) {
2347 dbg(1,"found %s (0x%x,0x%x) (0x%x,0x%x)-(0x%x,0x%x) %p-%p\n",item_to_name(tmp1->data.item.type),tmp1->data.item.id_hi,tmp1->data.item.id_lo,tmp1->start->c.x,tmp1->start->c.y,tmp1->end->c.x,tmp1->end->c.y,tmp1->start,tmp1->end);
2349 dbg(1,"compare %s (0x%x,0x%x) (0x%x,0x%x)-(0x%x,0x%x) %p-%p\n",item_to_name(tmp2->data.item.type),tmp2->data.item.id_hi,tmp2->data.item.id_lo,tmp2->start->c.x,tmp2->start->c.y,tmp2->end->c.x,tmp2->end->c.y,tmp2->start,tmp2->end);
2350 if (item_is_equal(tmp1->data.item, tmp2->data.item))
2352 tmp2=tmp2->start_next;
2354 dbg(1,"tmp2=%p\n",tmp2);
2356 dbg(1,"%s tmp2->end=%p next=%p\n",item_to_name(tmp1->data.item.type),tmp2->end,next);
2358 if (tmp1->data.item.type == type_street_turn_restriction_no && tmp2 && tmp2->end->c.x == next->c.x && tmp2->end->c.y == next->c.y) {
2359 dbg(1,"from 0x%x,0x%x over 0x%x,0x%x to 0x%x,0x%x not allowed (no)\n",prev->c.x,prev->c.y,p->c.x,p->c.y,next->c.x,next->c.y);
2362 if (tmp1->data.item.type == type_street_turn_restriction_only && tmp2 && (tmp2->end->c.x != next->c.x || tmp2->end->c.y != next->c.y)) {
2363 dbg(1,"from 0x%x,0x%x over 0x%x,0x%x to 0x%x,0x%x not allowed (only)\n",prev->c.x,prev->c.y,p->c.x,p->c.y,next->c.x,next->c.y);
2367 tmp1=tmp1->end_next;
2369 dbg(1,"from 0x%x,0x%x over 0x%x,0x%x to 0x%x,0x%x allowed\n",prev->c.x,prev->c.y,p->c.x,p->c.y,next->c.x,next->c.y);
2374 route_graph_clone_segment(struct route_graph *this, struct route_graph_segment *s, struct route_graph_point *start, struct route_graph_point *end, int flags)
2376 struct route_graph_segment_data data;
2377 data.flags=s->data.flags|flags;
2380 data.item=&s->data.item;
2381 data.len=s->data.len+1;
2382 if (s->data.flags & AF_SPEED_LIMIT)
2383 data.maxspeed=RSD_MAXSPEED(&s->data);
2384 if (s->data.flags & AF_SEGMENTED)
2385 data.offset=RSD_OFFSET(&s->data);
2386 dbg(1,"cloning segment from %p (0x%x,0x%x) to %p (0x%x,0x%x)\n",start,start->c.x,start->c.y, end, end->c.x, end->c.y);
2387 route_graph_add_segment(this, start, end, &data);
2391 route_graph_process_restriction_segment(struct route_graph *this, struct route_graph_point *p, struct route_graph_segment *s, int dir)
2393 struct route_graph_segment *tmp;
2394 struct route_graph_point *pn;
2395 struct coord c=p->c;
2400 dbg(1,"From %s %d,%d\n",item_to_name(s->data.item.type),dx,dy);
2401 pn=route_graph_point_new(this, &c);
2402 if (dir > 0) { /* going away */
2403 dbg(1,"other 0x%x,0x%x\n",s->end->c.x,s->end->c.y);
2404 if (s->data.flags & AF_ONEWAY) {
2405 dbg(1,"Not possible\n");
2408 route_graph_clone_segment(this, s, pn, s->end, AF_ONEWAYREV);
2409 } else { /* coming in */
2410 dbg(1,"other 0x%x,0x%x\n",s->start->c.x,s->start->c.y);
2411 if (s->data.flags & AF_ONEWAYREV) {
2412 dbg(1,"Not possible\n");
2415 route_graph_clone_segment(this, s, s->start, pn, AF_ONEWAY);
2419 if (tmp != s && tmp->data.item.type != type_street_turn_restriction_no &&
2420 tmp->data.item.type != type_street_turn_restriction_only &&
2421 !(tmp->data.flags & AF_ONEWAYREV) && is_turn_allowed(p, s, tmp)) {
2422 route_graph_clone_segment(this, tmp, pn, tmp->end, AF_ONEWAY);
2423 dbg(1,"To start %s\n",item_to_name(tmp->data.item.type));
2425 tmp=tmp->start_next;
2429 if (tmp != s && tmp->data.item.type != type_street_turn_restriction_no &&
2430 tmp->data.item.type != type_street_turn_restriction_only &&
2431 !(tmp->data.flags & AF_ONEWAY) && is_turn_allowed(p, s, tmp)) {
2432 route_graph_clone_segment(this, tmp, tmp->start, pn, AF_ONEWAYREV);
2433 dbg(1,"To end %s\n",item_to_name(tmp->data.item.type));
2440 route_graph_process_restriction_point(struct route_graph *this, struct route_graph_point *p)
2442 struct route_graph_segment *tmp;
2444 dbg(1,"node 0x%x,0x%x\n",p->c.x,p->c.y);
2446 if (tmp->data.item.type != type_street_turn_restriction_no &&
2447 tmp->data.item.type != type_street_turn_restriction_only)
2448 route_graph_process_restriction_segment(this, p, tmp, 1);
2449 tmp=tmp->start_next;
2453 if (tmp->data.item.type != type_street_turn_restriction_no &&
2454 tmp->data.item.type != type_street_turn_restriction_only)
2455 route_graph_process_restriction_segment(this, p, tmp, -1);
2458 p->flags |= RP_TURN_RESTRICTION_RESOLVED;
2462 route_graph_process_restrictions(struct route_graph *this)
2464 struct route_graph_point *curr;
2467 for (i = 0 ; i < HASH_SIZE ; i++) {
2470 if (curr->flags & RP_TURN_RESTRICTION)
2471 route_graph_process_restriction_point(this, curr);
2472 curr=curr->hash_next;
2478 route_graph_build_done(struct route_graph *rg, int cancel)
2480 dbg(1,"cancel=%d\n",cancel);
2482 event_remove_idle(rg->idle_ev);
2484 callback_destroy(rg->idle_cb);
2485 map_rect_destroy(rg->mr);
2486 mapset_close(rg->h);
2487 route_free_selection(rg->sel);
2494 route_graph_process_restrictions(rg);
2495 callback_call_0(rg->done_cb);
2501 route_graph_build_idle(struct route_graph *rg, struct vehicleprofile *profile)
2508 item=map_rect_get_item(rg->mr);
2511 if (!route_graph_build_next_map(rg)) {
2512 route_graph_build_done(rg, 0);
2516 if (item->type == type_traffic_distortion)
2517 route_process_traffic_distortion(rg, item);
2518 else if (item->type == type_street_turn_restriction_no || item->type == type_street_turn_restriction_only)
2519 route_process_turn_restriction(rg, item);
2521 route_process_street_graph(rg, item, profile);
2527 * @brief Builds a new route graph from a mapset
2529 * This function builds a new route graph from a map. Please note that this function does not
2530 * add any routing information to the route graph - this has to be done via the route_graph_flood()
2533 * The function does not create a graph covering the whole map, but only covering the rectangle
2534 * between c1 and c2.
2536 * @param ms The mapset to build the route graph from
2537 * @param c1 Corner 1 of the rectangle to use from the map
2538 * @param c2 Corner 2 of the rectangle to use from the map
2539 * @param done_cb The callback which will be called when graph is complete
2540 * @return The new route graph.
2542 static struct route_graph *
2543 route_graph_build(struct mapset *ms, struct coord *c, int count, struct callback *done_cb, int async, struct vehicleprofile *profile)
2545 struct route_graph *ret=g_new0(struct route_graph, 1);
2549 ret->sel=route_calc_selection(c, count);
2550 ret->h=mapset_open(ms);
2551 ret->done_cb=done_cb;
2553 if (route_graph_build_next_map(ret)) {
2555 ret->idle_cb=callback_new_2(callback_cast(route_graph_build_idle), ret, profile);
2556 ret->idle_ev=event_add_idle(50, ret->idle_cb);
2559 route_graph_build_done(ret, 0);
2565 route_graph_update_done(struct route *this, struct callback *cb)
2567 route_graph_flood(this->graph, this->current_dst, this->vehicleprofile, cb);
2571 * @brief Updates the route graph
2573 * This updates the route graph after settings in the route have changed. It also
2574 * adds routing information afterwards by calling route_graph_flood().
2576 * @param this The route to update the graph for
2579 route_graph_update(struct route *this, struct callback *cb, int async)
2581 struct attr route_status;
2582 struct coord *c=g_alloca(sizeof(struct coord)*(1+g_list_length(this->destinations)));
2586 route_status.type=attr_route_status;
2587 route_graph_destroy(this->graph);
2589 callback_destroy(this->route_graph_done_cb);
2590 this->route_graph_done_cb=callback_new_2(callback_cast(route_graph_update_done), this, cb);
2591 route_status.u.num=route_status_building_graph;
2592 route_set_attr(this, &route_status);
2593 c[i++]=this->pos->c;
2594 tmp=this->destinations;
2596 struct route_info *dst=tmp->data;
2598 tmp=g_list_next(tmp);
2600 this->graph=route_graph_build(this->ms, c, i, this->route_graph_done_cb, async, this->vehicleprofile);
2602 while (this->graph->busy)
2603 route_graph_build_idle(this->graph, this->vehicleprofile);
2608 * @brief Gets street data for an item
2610 * @param item The item to get the data for
2611 * @return Street data for the item
2613 struct street_data *
2614 street_get_data (struct item *item)
2617 struct street_data *ret = NULL, *ret1;
2618 struct attr flags_attr, maxspeed_attr;
2619 const int step = 128;
2623 ret1=g_realloc(ret, sizeof(struct street_data)+(count+step)*sizeof(struct coord));
2630 c = item_coord_get(item, &ret->c[count], step);
2632 } while (c && c == step);
2634 ret1=g_realloc(ret, sizeof(struct street_data)+count*sizeof(struct coord));
2639 if (item_attr_get(item, attr_flags, &flags_attr))
2640 ret->flags=flags_attr.u.num;
2642 flags=item_get_default_flags(item->type);
2650 if (ret->flags & AF_SPEED_LIMIT) {
2651 if (item_attr_get(item, attr_maxspeed, &maxspeed_attr)) {
2652 ret->maxspeed = maxspeed_attr.u.num;
2660 * @brief Copies street data
2662 * @param orig The street data to copy
2663 * @return The copied street data
2665 struct street_data *
2666 street_data_dup(struct street_data *orig)
2668 struct street_data *ret;
2669 int size=sizeof(struct street_data)+orig->count*sizeof(struct coord);
2672 memcpy(ret, orig, size);
2678 * @brief Frees street data
2680 * @param sd Street data to be freed
2683 street_data_free(struct street_data *sd)
2689 * @brief Finds the nearest street to a given coordinate
2691 * @param ms The mapset to search in for the street
2692 * @param pc The coordinate to find a street nearby
2693 * @return The nearest street
2695 static struct route_info *
2696 route_find_nearest_street(struct vehicleprofile *vehicleprofile, struct mapset *ms, struct pcoord *pc)
2698 struct route_info *ret=NULL;
2700 struct map_selection *sel;
2701 int dist,mindist=0,pos;
2702 struct mapset_handle *h;
2704 struct map_rect *mr;
2707 struct street_data *sd;
2711 ret=g_new0(struct route_info, 1);
2715 while ((m=mapset_next(h,2))) {
2718 if (map_projection(m) != pc->pro) {
2719 transform_to_geo(pc->pro, &c, &g);
2720 transform_from_geo(map_projection(m), &g, &c);
2722 sel = route_rect(18, &c, &c, 0, max_dist);
2725 mr=map_rect_new(m, sel);
2727 map_selection_destroy(sel);
2730 while ((item=map_rect_get_item(mr))) {
2731 if (item_get_default_flags(item->type)) {
2732 sd=street_get_data(item);
2735 dist=transform_distance_polyline_sq(sd->c, sd->count, &c, &lp, &pos);
2736 if (dist < mindist && (
2737 (sd->flags & vehicleprofile->flags_forward_mask) == vehicleprofile->flags ||
2738 (sd->flags & vehicleprofile->flags_reverse_mask) == vehicleprofile->flags)) {
2741 street_data_free(ret->street);
2747 dbg(1,"dist=%d id 0x%x 0x%x pos=%d\n", dist, item->id_hi, item->id_lo, pos);
2749 street_data_free(sd);
2753 map_selection_destroy(sel);
2754 map_rect_destroy(mr);
2758 if (!ret->street || mindist > max_dist*max_dist) {
2760 street_data_free(ret->street);
2761 dbg(1,"Much too far %d > %d\n", mindist, max_dist);
2771 * @brief Destroys a route_info
2773 * @param info The route info to be destroyed
2776 route_info_free(struct route_info *inf)
2781 street_data_free(inf->street);
2789 * @brief Returns street data for a route info
2791 * @param rinf The route info to return the street data for
2792 * @return Street data for the route info
2794 struct street_data *
2795 route_info_street(struct route_info *rinf)
2797 return rinf->street;
2801 struct route_crossings *
2802 route_crossings_get(struct route *this, struct coord *c)
2804 struct route_point *pnt;
2805 struct route_segment *seg;
2807 struct route_crossings *ret;
2809 pnt=route_graph_get_point(this, c);
2812 printf("start: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
2814 seg=seg->start_next;
2818 printf("end: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
2822 ret=g_malloc(sizeof(struct route_crossings)+crossings*sizeof(struct route_crossing));
2823 ret->count=crossings;
2829 struct map_rect_priv {
2830 struct route_info_handle *ri;
2831 enum attr_type attr_next;
2833 struct map_priv *mpriv;
2835 unsigned int last_coord;
2836 struct route_path *path;
2837 struct route_path_segment *seg,*seg_next;
2838 struct route_graph_point *point;
2839 struct route_graph_segment *rseg;
2842 struct coord *coord_sel; /**< Set this to a coordinate if you want to filter for just a single route graph point */
2843 struct route_graph_point_iterator it;
2847 rm_coord_rewind(void *priv_data)
2849 struct map_rect_priv *mr = priv_data;
2854 rm_attr_rewind(void *priv_data)
2856 struct map_rect_priv *mr = priv_data;
2857 mr->attr_next = attr_street_item;
2861 rm_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
2863 struct map_rect_priv *mr = priv_data;
2864 struct route_path_segment *seg=mr->seg;
2865 struct route *route=mr->mpriv->route;
2866 if (mr->item.type != type_street_route)
2868 attr->type=attr_type;
2869 switch (attr_type) {
2871 while (mr->attr_next != attr_none) {
2872 if (rm_attr_get(priv_data, mr->attr_next, attr))
2877 mr->attr_next = attr_street_item;
2878 if (seg && seg->data->flags & AF_SPEED_LIMIT) {
2879 attr->u.num=RSD_MAXSPEED(seg->data);
2885 case attr_street_item:
2886 mr->attr_next=attr_direction;
2887 if (seg && seg->data->item.map)
2888 attr->u.item=&seg->data->item;
2892 case attr_direction:
2893 mr->attr_next=attr_route;
2895 attr->u.num=seg->direction;
2900 mr->attr_next=attr_length;
2901 attr->u.route = mr->mpriv->route;
2904 mr->attr_next=attr_time;
2906 attr->u.num=seg->data->len;
2911 mr->attr_next=attr_speed;
2913 attr->u.num=route_time_seg(route->vehicleprofile, seg->data, NULL);
2918 mr->attr_next=attr_none;
2920 attr->u.num=route_seg_speed(route->vehicleprofile, seg->data, NULL);
2925 mr->attr_next=attr_none;
2928 mr->attr_next=attr_none;
2929 attr->type=attr_none;
2936 rm_coord_get(void *priv_data, struct coord *c, int count)
2938 struct map_rect_priv *mr = priv_data;
2939 struct route_path_segment *seg = mr->seg;
2941 struct route *r = mr->mpriv->route;
2942 enum projection pro = route_projection(r);
2944 if (pro == projection_none)
2946 if (mr->item.type == type_route_start || mr->item.type == type_route_start_reverse || mr->item.type == type_route_end) {
2947 if (! count || mr->last_coord)
2950 if (mr->item.type == type_route_start || mr->item.type == type_route_start_reverse)
2953 c[0]=route_get_dst(r)->c;
2959 for (i=0; i < count; i++) {
2960 if (mr->last_coord >= seg->ncoords)
2962 if (i >= seg->ncoords)
2964 if (pro != projection_mg)
2965 transform_from_to(&seg->c[mr->last_coord++], pro,
2966 &c[i],projection_mg);
2968 c[i] = seg->c[mr->last_coord++];
2971 dbg(1,"return %d\n",rc);
2975 static struct item_methods methods_route_item = {
2983 rp_attr_rewind(void *priv_data)
2985 struct map_rect_priv *mr = priv_data;
2986 mr->attr_next = attr_label;
2990 rp_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
2992 struct map_rect_priv *mr = priv_data;
2993 struct route_graph_point *p = mr->point;
2994 struct route_graph_segment *seg = mr->rseg;
2995 struct route *route=mr->mpriv->route;
2997 attr->type=attr_type;
2998 switch (attr_type) {
2999 case attr_any: // works only with rg_points for now
3000 while (mr->attr_next != attr_none) {
3001 dbg(0,"querying %s\n", attr_to_name(mr->attr_next));
3002 if (rp_attr_get(priv_data, mr->attr_next, attr))
3007 mr->attr_next = attr_label;
3008 if (mr->item.type != type_rg_segment)
3010 if (seg && (seg->data.flags & AF_SPEED_LIMIT)) {
3011 attr->type = attr_maxspeed;
3012 attr->u.num=RSD_MAXSPEED(&seg->data);
3018 mr->attr_next=attr_street_item;
3019 if (mr->item.type != type_rg_point)
3021 attr->type = attr_label;
3024 if (p->value != INT_MAX)
3025 mr->str=g_strdup_printf("%d", p->value);
3027 mr->str=g_strdup("-");
3028 attr->u.str = mr->str;
3030 case attr_street_item:
3031 mr->attr_next=attr_flags;
3032 if (mr->item.type != type_rg_segment)
3034 if (seg && seg->data.item.map)
3035 attr->u.item=&seg->data.item;
3040 mr->attr_next = attr_direction;
3041 if (mr->item.type != type_rg_segment)
3044 attr->u.num = seg->data.flags;
3049 case attr_direction:
3050 mr->attr_next = attr_debug;
3051 // This only works if the map has been opened at a single point, and in that case indicates if the
3052 // segment returned last is connected to this point via its start (1) or its end (-1)
3053 if (!mr->coord_sel || (mr->item.type != type_rg_segment))
3055 if (seg->start == mr->point) {
3057 } else if (seg->end == mr->point) {
3064 mr->attr_next=attr_none;
3067 switch (mr->item.type) {
3070 struct route_graph_segment *tmp;
3076 tmp=tmp->start_next;
3083 mr->str=g_strdup_printf("%d %d %p (0x%x,0x%x)", start, end, p, p->c.x, p->c.y);
3084 attr->u.str = mr->str;
3087 case type_rg_segment:
3090 mr->str=g_strdup_printf("len %d time %d start %p end %p",seg->data.len, route_time_seg(route->vehicleprofile, &seg->data, NULL), seg->start, seg->end);
3091 attr->u.str = mr->str;
3097 mr->attr_next=attr_none;
3098 attr->type=attr_none;
3104 * @brief Returns the coordinates of a route graph item
3106 * @param priv_data The route graph item's private data
3107 * @param c Pointer where to store the coordinates
3108 * @param count How many coordinates to get at a max?
3109 * @return The number of coordinates retrieved
3112 rp_coord_get(void *priv_data, struct coord *c, int count)
3114 struct map_rect_priv *mr = priv_data;
3115 struct route_graph_point *p = mr->point;
3116 struct route_graph_segment *seg = mr->rseg;
3118 struct route *r = mr->mpriv->route;
3119 enum projection pro = route_projection(r);
3121 if (pro == projection_none)
3123 for (i=0; i < count; i++) {
3124 if (mr->item.type == type_rg_point) {
3125 if (mr->last_coord >= 1)
3127 if (pro != projection_mg)
3128 transform_from_to(&p->c, pro,
3129 &c[i],projection_mg);
3133 if (mr->last_coord >= 2)
3136 if (seg->end->seg == seg)
3141 if (pro != projection_mg)
3142 transform_from_to(&seg->end->c, pro,
3143 &c[i],projection_mg);
3147 if (pro != projection_mg)
3148 transform_from_to(&seg->start->c, pro,
3149 &c[i],projection_mg);
3151 c[i] = seg->start->c;
3160 static struct item_methods methods_point_item = {
3168 rp_destroy(struct map_priv *priv)
3174 rm_destroy(struct map_priv *priv)
3179 static struct map_rect_priv *
3180 rm_rect_new(struct map_priv *priv, struct map_selection *sel)
3182 struct map_rect_priv * mr;
3185 if (! route_get_pos(priv->route))
3187 if (! route_get_dst(priv->route))
3191 if (! priv->route->path2)
3194 mr=g_new0(struct map_rect_priv, 1);
3196 mr->item.priv_data = mr;
3197 mr->item.type = type_none;
3198 mr->item.meth = &methods_route_item;
3199 if (priv->route->path2) {
3200 mr->path=priv->route->path2;
3201 mr->seg_next=mr->path->path;
3209 * @brief Opens a new map rectangle on the route graph's map
3211 * This function opens a new map rectangle on the route graph's map.
3212 * The "sel" parameter enables you to only search for a single route graph
3213 * point on this map (or exactly: open a map rectangle that only contains
3214 * this one point). To do this, pass here a single map selection, whose
3215 * c_rect has both coordinates set to the same point. Otherwise this parameter
3218 * @param priv The route graph map's private data
3219 * @param sel Here it's possible to specify a point for which to search. Please read the function's description.
3220 * @return A new map rect's private data
3222 static struct map_rect_priv *
3223 rp_rect_new(struct map_priv *priv, struct map_selection *sel)
3225 struct map_rect_priv * mr;
3228 if (! priv->route->graph)
3230 mr=g_new0(struct map_rect_priv, 1);
3232 mr->item.priv_data = mr;
3233 mr->item.type = type_rg_point;
3234 mr->item.meth = &methods_point_item;
3236 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)) {
3237 mr->coord_sel = g_malloc(sizeof(struct coord));
3238 *(mr->coord_sel) = sel->u.c_rect.lu;
3245 rm_rect_destroy(struct map_rect_priv *mr)
3249 if (mr->coord_sel) {
3250 g_free(mr->coord_sel);
3254 if (mr->path->update_required && (mr->path->in_use==1))
3255 route_path_update_done(mr->mpriv->route, mr->path->update_required-1);
3256 else if (!mr->path->in_use)
3263 static struct item *
3264 rp_get_item(struct map_rect_priv *mr)
3266 struct route *r = mr->mpriv->route;
3267 struct route_graph_point *p = mr->point;
3268 struct route_graph_segment *seg = mr->rseg;
3270 if (mr->item.type == type_rg_point) {
3271 if (mr->coord_sel) {
3272 // We are supposed to return only the point at one specified coordinate...
3274 p = route_graph_get_point_last(r->graph, mr->coord_sel);
3276 mr->point = NULL; // This indicates that no point has been found
3278 mr->it = rp_iterator_new(p);
3286 p = r->graph->hash[0];
3291 if (mr->hash_bucket >= HASH_SIZE)
3293 p = r->graph->hash[mr->hash_bucket];
3299 rm_coord_rewind(mr);
3303 mr->item.type = type_rg_segment;
3306 if (mr->coord_sel) {
3307 if (!mr->point) { // This means that no point has been found
3310 seg = rp_iterator_next(&(mr->it));
3313 seg=r->graph->route_segments;
3321 rm_coord_rewind(mr);
3329 static struct item *
3330 rp_get_item_byid(struct map_rect_priv *mr, int id_hi, int id_lo)
3332 struct item *ret=NULL;
3334 ret=rp_get_item(mr);
3339 static struct item *
3340 rm_get_item(struct map_rect_priv *mr)
3342 struct route *route=mr->mpriv->route;
3343 dbg(1,"enter\n", mr->pos);
3345 switch (mr->item.type) {
3347 if (route->pos && route->pos->street_direction && route->pos->street_direction != route->pos->dir)
3348 mr->item.type=type_route_start_reverse;
3350 mr->item.type=type_route_start;
3354 mr->item.type=type_street_route;
3355 mr->seg=mr->seg_next;
3356 if (!mr->seg && mr->path && mr->path->next) {
3357 struct route_path *p=NULL;
3359 if (!mr->path->in_use)
3361 mr->path=mr->path->next;
3363 mr->seg=mr->path->path;
3368 mr->seg_next=mr->seg->next;
3371 mr->item.type=type_route_end;
3372 if (mr->mpriv->route->destinations)
3374 case type_route_end:
3383 static struct item *
3384 rm_get_item_byid(struct map_rect_priv *mr, int id_hi, int id_lo)
3386 struct item *ret=NULL;
3388 ret=rm_get_item(mr);
3392 static struct map_methods route_meth = {
3405 static struct map_methods route_graph_meth = {
3418 static struct map_priv *
3419 route_map_new_helper(struct map_methods *meth, struct attr **attrs, int graph)
3421 struct map_priv *ret;
3422 struct attr *route_attr;
3424 route_attr=attr_search(attrs, NULL, attr_route);
3427 ret=g_new0(struct map_priv, 1);
3429 *meth=route_graph_meth;
3432 ret->route=route_attr->u.route;
3437 static struct map_priv *
3438 route_map_new(struct map_methods *meth, struct attr **attrs, struct callback_list *cbl)
3440 return route_map_new_helper(meth, attrs, 0);
3443 static struct map_priv *
3444 route_graph_map_new(struct map_methods *meth, struct attr **attrs, struct callback_list *cbl)
3446 return route_map_new_helper(meth, attrs, 1);
3450 route_get_map_helper(struct route *this_, struct map **map, char *type, char *description)
3452 struct attr *attrs[5];
3453 struct attr a_type,navigation,data,a_description;
3454 a_type.type=attr_type;
3456 navigation.type=attr_route;
3457 navigation.u.route=this_;
3458 data.type=attr_data;
3460 a_description.type=attr_description;
3461 a_description.u.str=description;
3464 attrs[1]=&navigation;
3466 attrs[3]=&a_description;
3470 *map=map_new(NULL, attrs);
3478 * @brief Returns a new map containing the route path
3480 * This function returns a new map containing the route path.
3482 * @important Do not map_destroy() this!
3484 * @param this_ The route to get the map of
3485 * @return A new map containing the route path
3488 route_get_map(struct route *this_)
3490 return route_get_map_helper(this_, &this_->map, "route","Route");
3495 * @brief Returns a new map containing the route graph
3497 * This function returns a new map containing the route graph.
3499 * @important Do not map_destroy() this!
3501 * @param this_ The route to get the map of
3502 * @return A new map containing the route graph
3505 route_get_graph_map(struct route *this_)
3507 return route_get_map_helper(this_, &this_->graph_map, "route_graph","Route Graph");
3511 route_set_projection(struct route *this_, enum projection pro)
3516 route_set_attr(struct route *this_, struct attr *attr)
3519 switch (attr->type) {
3520 case attr_route_status:
3521 attr_updated = (this_->route_status != attr->u.num);
3522 this_->route_status = attr->u.num;
3524 case attr_destination:
3525 route_set_destination(this_, attr->u.pcoord, 1);
3528 attr_updated = (this_->v != attr->u.vehicle);
3529 this_->v=attr->u.vehicle;
3534 if (vehicle_get_attr(this_->v, attr_position_coord_geo, &g, NULL)) {
3535 pc.pro=projection_mg;
3536 transform_from_geo(projection_mg, g.u.coord_geo, &c);
3539 route_set_position(this_, &pc);
3544 dbg(0,"unsupported attribute: %s\n",attr_to_name(attr->type));
3548 callback_list_call_attr_2(this_->cbl2, attr->type, this_, attr);
3553 route_add_attr(struct route *this_, struct attr *attr)
3555 switch (attr->type) {
3557 callback_list_add(this_->cbl2, attr->u.callback);
3565 route_remove_attr(struct route *this_, struct attr *attr)
3568 switch (attr->type) {
3570 callback_list_remove(this_->cbl2, attr->u.callback);
3581 route_get_attr(struct route *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
3586 attr->u.map=route_get_map(this_);
3587 ret=(attr->u.map != NULL);
3589 case attr_destination:
3590 if (this_->destinations) {
3591 struct route_info *dst;
3594 iter->u.list=g_list_next(iter->u.list);
3596 iter->u.list=this_->destinations;
3598 if (!iter->u.list) {
3601 dst = (struct route_info*)iter->u.list->data;
3602 } else { //No iter handling
3603 dst=route_get_dst(this_);
3605 attr->u.pcoord=&this_->pc;
3606 this_->pc.pro=projection_mg; /* fixme */
3607 this_->pc.x=dst->c.x;
3608 this_->pc.y=dst->c.y;
3613 attr->u.vehicle=this_->v;
3614 ret=(this_->v != NULL);
3615 dbg(0,"get vehicle %p\n",this_->v);
3617 case attr_vehicleprofile:
3618 attr->u.vehicleprofile=this_->vehicleprofile;
3619 ret=(this_->vehicleprofile != NULL);
3621 case attr_route_status:
3622 attr->u.num=this_->route_status;
3624 case attr_destination_time:
3625 if (this_->path2 && (this_->route_status == route_status_path_done_new || this_->route_status == route_status_path_done_incremental)) {
3627 attr->u.num=this_->path2->path_time;
3628 dbg(1,"path_time %d\n",attr->u.num);
3633 case attr_destination_length:
3634 if (this_->path2 && (this_->route_status == route_status_path_done_new || this_->route_status == route_status_path_done_incremental))
3635 attr->u.num=this_->path2->path_len;
3647 route_attr_iter_new(void)
3649 return g_new0(struct attr_iter, 1);
3653 route_attr_iter_destroy(struct attr_iter *iter)
3661 plugin_register_map_type("route", route_map_new);
3662 plugin_register_map_type("route_graph", route_graph_map_new);
3666 route_destroy(struct route *this_)
3668 route_path_destroy(this_->path2,1);
3669 route_graph_destroy(this_->graph);
3670 route_clear_destinations(this_);
3671 route_info_free(this_->pos);
3672 map_destroy(this_->map);
3673 map_destroy(this_->graph_map);