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"
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.
121 #define RSD_OFFSET(x) *((int *)route_segment_data_field_pos((x), attr_offset))
122 #define RSD_MAXSPEED(x) *((int *)route_segment_data_field_pos((x), attr_maxspeed))
127 * @brief A segment in the route graph
129 * This is a segment in the route graph. A segment represents a driveable way.
131 struct route_graph_segment {
132 struct route_graph_segment *next; /**< Linked-list pointer to a list of all route_graph_segments */
133 struct route_graph_segment *start_next; /**< Pointer to the next element in the list of segments that start at the
134 * same point. Start of this list is in route_graph_point->start. */
135 struct route_graph_segment *end_next; /**< Pointer to the next element in the list of segments that end at the
136 * same point. Start of this list is in route_graph_point->end. */
137 struct route_graph_point *start; /**< Pointer to the point this segment starts at. */
138 struct route_graph_point *end; /**< Pointer to the point this segment ends at. */
139 struct route_segment_data data; /**< The segment data */
143 * @brief A traffic distortion
145 * This is distortion in the traffic where you can't drive as fast as usual or have to wait for some time
147 struct route_traffic_distortion {
148 int maxspeed; /**< Maximum speed possible in km/h */
149 int delay; /**< Delay in tenths of seconds */
153 * @brief A segment in the route path
155 * This is a segment in the route path.
157 struct route_path_segment {
158 struct route_path_segment *next; /**< Pointer to the next segment in the path */
159 struct route_segment_data *data; /**< The segment data */
160 int direction; /**< Order in which the coordinates are ordered. >0 means "First
161 * coordinate of the segment is the first coordinate of the item", <=0
163 unsigned ncoords; /**< How many coordinates does this segment have? */
164 struct coord c[0]; /**< Pointer to the ncoords coordinates of this segment */
165 /* WARNING: There will be coordinates following here, so do not create new fields after c! */
169 * @brief Usually represents a destination or position
171 * This struct usually represents a destination or position
174 struct coord c; /**< The actual destination / position */
175 struct coord lp; /**< The nearest point on a street to c */
176 int pos; /**< The position of lp within the coords of the street */
177 int lenpos; /**< Distance between lp and the end of the street */
178 int lenneg; /**< Distance between lp and the start of the street */
179 int lenextra; /**< Distance between lp and c */
180 int percent; /**< ratio of lenneg to lenght of whole street in percent */
181 struct street_data *street; /**< The street lp is on */
182 int street_direction; /**< Direction of vehicle on street -1 = Negative direction, 1 = Positive direction, 0 = Unknown */
183 int dir; /**< Direction to take when following the route -1 = Negative direction, 1 = Positive direction */
187 * @brief A complete route path
189 * This structure describes a whole routing path
192 int in_use; /**< The path is in use and can not be updated */
193 int update_required; /**< The path needs to be updated after it is no longer in use */
194 int updated; /**< The path has only been updated */
195 struct route_path_segment *path; /**< The first segment in the path, i.e. the segment one should
197 struct route_path_segment *path_last; /**< The last segment in the path */
198 /* XXX: path_hash is not necessery now */
199 struct item_hash *path_hash; /**< A hashtable of all the items represented by this route's segements */
203 * @brief A complete route
205 * This struct holds all information about a route.
208 struct mapset *ms; /**< The mapset this route is built upon */
210 struct route_info *pos; /**< Current position within this route */
211 struct route_info *dst; /**< Destination of the route */
213 struct route_graph *graph; /**< Pointer to the route graph */
214 struct route_path *path2; /**< Pointer to the route path */
216 struct map *graph_map;
217 struct callback * route_graph_done_cb ; /**< Callback when route graph is done */
218 struct callback * route_graph_flood_done_cb ; /**< Callback when route graph flooding is done */
219 struct callback_list *cbl2; /**< Callback list to call when route changes */
220 int destination_distance; /**< Distance to the destination at which the destination is considered "reached" */
221 struct vehicleprofile *vehicleprofile; /**< Routing preferences */
222 int route_status; /**< Route Status */
226 * @brief A complete route graph
228 * This structure describes a whole routing graph
231 int busy; /**< The graph is being built */
232 struct map_selection *sel; /**< The rectangle selection for the graph */
233 struct mapset_handle *h; /**< Handle to the mapset */
234 struct map *m; /**< Pointer to the currently active map */
235 struct map_rect *mr; /**< Pointer to the currently active map rectangle */
236 struct vehicleprofile *vehicleprofile; /**< The vehicle profile */
237 struct callback *idle_cb; /**< Idle callback to process the graph */
238 struct callback *done_cb; /**< Callback when graph is done */
239 struct event_idle *idle_ev; /**< The pointer to the idle event */
240 struct route_graph_segment *route_segments; /**< Pointer to the first route_graph_segment in the linked list of all segments */
241 #define HASH_SIZE 8192
242 struct route_graph_point *hash[HASH_SIZE]; /**< A hashtable containing all route_graph_points in this graph */
245 #define HASHCOORD(c) ((((c)->x +(c)->y) * 2654435761UL) & (HASH_SIZE-1))
248 * @brief Iterator to iterate through all route graph segments in a route graph point
250 * This structure can be used to iterate through all route graph segments connected to a
251 * route graph point. Use this with the rp_iterator_* functions.
253 struct route_graph_point_iterator {
254 struct route_graph_point *p; /**< The route graph point whose segments should be iterated */
255 int end; /**< Indicates if we have finished iterating through the "start" segments */
256 struct route_graph_segment *next; /**< The next segment to be returned */
259 static struct route_info * route_find_nearest_street(struct vehicleprofile *vehicleprofile, struct mapset *ms, struct pcoord *c);
260 static struct route_graph_point *route_graph_get_point(struct route_graph *this, struct coord *c);
261 static void route_graph_update(struct route *this, struct callback *cb, int async);
262 static void route_graph_build_done(struct route_graph *rg, int cancel);
263 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);
264 static void route_process_street_graph(struct route_graph *this, struct item *item);
265 static void route_graph_destroy(struct route_graph *this);
266 static void route_path_update(struct route *this, int cancel, int async);
269 * @brief Returns the projection used for this route
271 * @param route The route to return the projection for
272 * @return The projection used for this route
274 static enum projection route_projection(struct route *route)
276 struct street_data *street;
277 if (!route->pos && !route->dst)
278 return projection_none;
279 street = route->pos ? route->pos->street : route->dst->street;
280 if (!street || !street->item.map)
281 return projection_none;
282 return map_projection(street->item.map);
286 * @brief Creates a new graph point iterator
288 * This function creates a new route graph point iterator, that can be used to
289 * iterate through all segments connected to the point.
291 * @param p The route graph point to create the iterator from
292 * @return A new iterator.
294 static struct route_graph_point_iterator
295 rp_iterator_new(struct route_graph_point *p)
297 struct route_graph_point_iterator it;
312 * @brief Gets the next segment connected to a route graph point from an iterator
314 * @param it The route graph point iterator to get the segment from
315 * @return The next segment or NULL if there are no more segments
317 static struct route_graph_segment
318 *rp_iterator_next(struct route_graph_point_iterator *it)
320 struct route_graph_segment *ret;
328 if (ret->start_next) {
329 it->next = ret->start_next;
331 it->next = it->p->end;
335 it->next = ret->end_next;
342 * @brief Checks if the last segment returned from a route_graph_point_iterator comes from the end
344 * @param it The route graph point iterator to be checked
345 * @return 1 if the last segment returned comes from the end of the route graph point, 0 otherwise
348 rp_iterator_end(struct route_graph_point_iterator *it) {
349 if (it->end && (it->next != it->p->end)) {
357 * @brief Destroys a route_path
359 * @param this The route_path to be destroyed
362 route_path_destroy(struct route_path *this)
364 struct route_path_segment *c,*n;
367 if (this->path_hash) {
368 item_hash_destroy(this->path_hash);
369 this->path_hash=NULL;
381 * @brief Creates a completely new route structure
383 * @param attrs Not used
384 * @return The newly created route
387 route_new(struct attr *parent, struct attr **attrs)
389 struct route *this=g_new0(struct route, 1);
390 struct attr dest_attr;
392 if (attr_generic_get_attr(attrs, NULL, attr_destination_distance, &dest_attr, NULL)) {
393 this->destination_distance = dest_attr.u.num;
395 this->destination_distance = 50; // Default value
397 this->cbl2=callback_list_new();
403 * @brief Checks if a segment is part of a roundabout
405 * This function checks if a segment is part of a roundabout.
407 * @param seg The segment to be checked
408 * @param level How deep to scan the route graph
409 * @param direction Set this to 1 if we're entering the segment through its end, to 0 otherwise
410 * @param origin Used internally, set to NULL
411 * @return 1 If a roundabout was detected, 0 otherwise
414 route_check_roundabout(struct route_graph_segment *seg, int level, int direction, struct route_graph_segment *origin)
416 struct route_graph_point_iterator it,it2;
417 struct route_graph_segment *cur;
423 if (!direction && !(seg->data.flags & AF_ONEWAY)) {
426 if (direction && !(seg->data.flags & AF_ONEWAYREV)) {
429 if (seg->data.flags & AF_ROUNDABOUT_VALID)
437 it = rp_iterator_new(seg->end);
439 it = rp_iterator_new(seg->start);
443 while ((cur = rp_iterator_next(&it2)))
448 cur = rp_iterator_next(&it);
451 cur = rp_iterator_next(&it);
455 if (cur->data.item.type != origin->data.item.type) {
456 // This street is of another type, can't be part of the roundabout
457 cur = rp_iterator_next(&it);
462 seg->data.flags |= AF_ROUNDABOUT;
466 if (route_check_roundabout(cur, (level-1), rp_iterator_end(&it), origin)) {
467 seg->data.flags |= AF_ROUNDABOUT;
471 cur = rp_iterator_next(&it);
478 * @brief Sets the mapset of the route passwd
480 * @param this The route to set the mapset for
481 * @param ms The mapset to set for this route
484 route_set_mapset(struct route *this, struct mapset *ms)
490 * @brief Sets the vehicle profile of a route
492 * @param this The route to set the profile for
493 * @param prof The vehicle profile
497 route_set_profile(struct route *this, struct vehicleprofile *prof)
499 if (this->vehicleprofile != prof) {
500 this->vehicleprofile=prof;
501 route_path_update(this, 1, 1);
506 * @brief Returns the mapset of the route passed
508 * @param this The route to get the mapset of
509 * @return The mapset of the route passed
512 route_get_mapset(struct route *this)
518 * @brief Returns the current position within the route passed
520 * @param this The route to get the position for
521 * @return The position within the route passed
524 route_get_pos(struct route *this)
530 * @brief Returns the destination of the route passed
532 * @param this The route to get the destination for
533 * @return The destination of the route passed
536 route_get_dst(struct route *this)
542 * @brief Checks if the path is calculated for the route passed
544 * @param this The route to check
545 * @return True if the path is calculated, false if not
548 route_get_path_set(struct route *this)
550 return this->path2 != NULL;
554 * @brief Checks if the route passed contains a certain item within the route path
556 * This function checks if a certain items exists in the path that navit will guide
557 * the user to his destination. It does *not* check if this item exists in the route
560 * @param this The route to check for this item
561 * @param item The item to search for
562 * @return True if the item was found, false if the item was not found or the route was not calculated
565 route_contains(struct route *this, struct item *item)
567 if (! this->path2 || !this->path2->path_hash)
569 if (item_hash_lookup(this->path2->path_hash, item))
571 if (! this->pos || !this->pos->street)
573 return item_is_equal(this->pos->street->item, *item);
578 * @brief Checks if a route has reached its destination
580 * @param this The route to be checked
581 * @return True if the destination is "reached", false otherwise.
584 route_destination_reached(struct route *this)
586 struct street_data *sd = NULL;
592 sd = this->pos->street;
598 if (!item_is_equal(this->pos->street->item, this->dst->street->item)) {
602 if ((sd->flags & AF_ONEWAY) && (this->pos->lenneg >= this->dst->lenneg)) { // We would have to drive against the one-way road
605 if ((sd->flags & AF_ONEWAYREV) && (this->pos->lenpos >= this->dst->lenpos)) {
608 pro=route_projection(this);
609 if (pro == projection_none)
612 if (transform_distance(pro, &this->pos->c, &this->dst->lp) > this->destination_distance) {
620 route_path_update_done(struct route *this, int new_graph)
622 struct route_path *oldpath=this->path2;
623 struct attr route_status;
624 route_status.type=attr_route_status;
625 if (this->path2 && this->path2->in_use) {
626 this->path2->update_required=1+new_graph;
629 route_status.u.num=route_status_building_path;
630 route_set_attr(this, &route_status);
632 this->path2=route_path_new(this->graph, oldpath, this->pos, this->dst, this->vehicleprofile);
633 route_path_destroy(oldpath);
635 if (!new_graph && this->path2->updated)
636 route_status.u.num=route_status_path_done_incremental;
638 route_status.u.num=route_status_path_done_new;
640 route_status.u.num=route_status_not_found;
641 route_set_attr(this, &route_status);
645 * @brief Updates the route graph and the route path if something changed with the route
647 * This will update the route graph and the route path of the route if some of the
648 * route's settings (destination, position) have changed.
650 * @attention For this to work the route graph has to be destroyed if the route's
651 * @attention destination is changed somewhere!
653 * @param this The route to update
656 route_path_update(struct route *this, int cancel, int async)
658 dbg(1,"enter %d\n", cancel);
659 if (! this->pos || ! this->dst) {
661 route_path_destroy(this->path2);
666 route_graph_destroy(this->graph);
669 /* the graph is destroyed when setting the destination */
671 if (this->graph->busy) {
672 dbg(1,"busy building graph\n");
675 // we can try to update
676 dbg(1,"try update\n");
677 route_path_update_done(this, 0);
679 route_path_destroy(this->path2);
682 if (!this->graph || !this->path2) {
683 dbg(1,"rebuild graph\n");
684 if (! this->route_graph_flood_done_cb)
685 this->route_graph_flood_done_cb=callback_new_2(callback_cast(route_path_update_done), this, (long)1);
686 dbg(1,"route_graph_update\n");
687 route_graph_update(this, this->route_graph_flood_done_cb, async);
692 * @brief This will calculate all the distances stored in a route_info
694 * @param ri The route_info to calculate the distances for
695 * @param pro The projection used for this route
698 route_info_distances(struct route_info *ri, enum projection pro)
701 struct street_data *sd=ri->street;
702 /* 0 1 2 X 3 4 5 6 pos=2 npos=3 count=7 0,1,2 3,4,5,6*/
703 ri->lenextra=transform_distance(pro, &ri->lp, &ri->c);
704 ri->lenneg=transform_polyline_length(pro, sd->c, npos)+transform_distance(pro, &sd->c[ri->pos], &ri->lp);
705 ri->lenpos=transform_polyline_length(pro, sd->c+npos, sd->count-npos)+transform_distance(pro, &sd->c[npos], &ri->lp);
706 if (ri->lenneg || ri->lenpos)
707 ri->percent=(ri->lenneg*100)/(ri->lenneg+ri->lenpos);
713 * @brief This sets the current position of the route passed
715 * This will set the current position of the route passed to the street that is nearest to the
716 * passed coordinates. It also automatically updates the route.
718 * @param this The route to set the position of
719 * @param pos Coordinates to set as position
722 route_set_position(struct route *this, struct pcoord *pos)
725 route_info_free(this->pos);
727 this->pos=route_find_nearest_street(this->vehicleprofile, this->ms, pos);
729 // If there is no nearest street, bail out.
730 if (!this->pos) return;
732 this->pos->street_direction=0;
733 dbg(1,"this->pos=%p\n", this->pos);
734 route_info_distances(this->pos, pos->pro);
735 route_path_update(this, 0, 1);
739 * @brief Sets a route's current position based on coordinates from tracking
741 * @param this The route to set the current position of
742 * @param tracking The tracking to get the coordinates from
745 route_set_position_from_tracking(struct route *this, struct tracking *tracking, enum projection pro)
748 struct route_info *ret;
749 struct street_data *sd;
752 c=tracking_get_pos(tracking);
753 ret=g_new0(struct route_info, 1);
755 printf("%s:Out of memory\n", __FUNCTION__);
759 route_info_free(this->pos);
763 ret->pos=tracking_get_segment_pos(tracking);
764 ret->street_direction=tracking_get_street_direction(tracking);
765 sd=tracking_get_street_data(tracking);
767 ret->street=street_data_dup(sd);
768 route_info_distances(ret, pro);
770 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);
771 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);
774 route_path_update(this, 0, 1);
778 /* Used for debuging of route_rect, what routing sees */
779 struct map_selection *route_selection;
782 * @brief Returns a single map selection
784 struct map_selection *
785 route_rect(int order, struct coord *c1, struct coord *c2, int rel, int abs)
787 int dx,dy,sx=1,sy=1,d,m;
788 struct map_selection *sel=g_new(struct map_selection, 1);
790 printf("%s:Out of memory\n", __FUNCTION__);
794 sel->range.min=route_item_first;
795 sel->range.max=route_item_last;
796 dbg(1,"%p %p\n", c1, c2);
801 sel->u.c_rect.lu.x=c1->x;
802 sel->u.c_rect.rl.x=c2->x;
804 sel->u.c_rect.lu.x=c2->x;
805 sel->u.c_rect.rl.x=c1->x;
809 sel->u.c_rect.lu.y=c2->y;
810 sel->u.c_rect.rl.y=c1->y;
812 sel->u.c_rect.lu.y=c1->y;
813 sel->u.c_rect.rl.y=c2->y;
820 sel->u.c_rect.lu.x-=m;
821 sel->u.c_rect.rl.x+=m;
822 sel->u.c_rect.lu.y+=m;
823 sel->u.c_rect.rl.y-=m;
829 * @brief Returns a list of map selections useable to create a route graph
831 * Returns a list of map selections useable to get a map rect from which items can be
832 * retrieved to build a route graph. The selections are a rectangle with
833 * c1 and c2 as two corners.
835 * @param c1 Corner 1 of the rectangle
836 * @param c2 Corder 2 of the rectangle
838 static struct map_selection *
839 route_calc_selection(struct coord *c1, struct coord *c2)
841 struct map_selection *ret,*sel;
842 sel=route_rect(4, c1, c2, 25, 0);
844 sel->next=route_rect(8, c1, c1, 0, 40000);
846 sel->next=route_rect(18, c1, c1, 0, 10000);
848 sel->next=route_rect(8, c2, c2, 0, 40000);
850 sel->next=route_rect(18, c2, c2, 0, 10000);
851 /* route_selection=ret; */
856 * @brief Destroys a list of map selections
858 * @param sel Start of the list to be destroyed
861 route_free_selection(struct map_selection *sel)
863 struct map_selection *next;
873 * @brief Sets the destination of a route
875 * This sets the destination of a route to the street nearest to the coordinates passed
876 * and updates the route.
878 * @param this The route to set the destination for
879 * @param dst Coordinates to set as destination
882 route_set_destination(struct route *this, struct pcoord *dst, int async)
886 route_info_free(this->dst);
889 this->dst=route_find_nearest_street(this->vehicleprofile, this->ms, dst);
891 route_info_distances(this->dst, dst->pro);
893 struct attr route_status;
894 route_status.type=attr_route_status;
895 route_status.u.num=route_status_no_destination;
896 route_set_attr(this, &route_status);
898 profile(1,"find_nearest_street");
900 /* The graph has to be destroyed and set to NULL, otherwise route_path_update() doesn't work */
901 route_graph_destroy(this->graph);
903 route_path_update(this, 1, async);
908 * @brief Gets the route_graph_point with the specified coordinates
910 * @param this The route in which to search
911 * @param c Coordinates to search for
912 * @param last The last route graph point returned to iterate over multiple points with the same coordinates
913 * @return The point at the specified coordinates or NULL if not found
915 static struct route_graph_point *
916 route_graph_get_point_next(struct route_graph *this, struct coord *c, struct route_graph_point *last)
918 struct route_graph_point *p;
919 int seen=0,hashval=HASHCOORD(c);
920 p=this->hash[hashval];
922 if (p->c.x == c->x && p->c.y == c->y) {
933 static struct route_graph_point *
934 route_graph_get_point(struct route_graph *this, struct coord *c)
936 return route_graph_get_point_next(this, c, NULL);
940 * @brief Gets the last route_graph_point with the specified coordinates
942 * @param this The route in which to search
943 * @param c Coordinates to search for
944 * @return The point at the specified coordinates or NULL if not found
946 static struct route_graph_point *
947 route_graph_get_point_last(struct route_graph *this, struct coord *c)
949 struct route_graph_point *p,*ret=NULL;
950 int hashval=HASHCOORD(c);
951 p=this->hash[hashval];
953 if (p->c.x == c->x && p->c.y == c->y)
963 * @brief Create a new point for the route graph with the specified coordinates
965 * @param this The route to insert the point into
966 * @param f The coordinates at which the point should be created
967 * @return The point created
970 static struct route_graph_point *
971 route_graph_point_new(struct route_graph *this, struct coord *f)
974 struct route_graph_point *p;
976 hashval=HASHCOORD(f);
978 printf("p (0x%x,0x%x)\n", f->x, f->y);
979 p=g_new0(struct route_graph_point,1);
980 p->hash_next=this->hash[hashval];
981 this->hash[hashval]=p;
988 * @brief Inserts a point into the route graph at the specified coordinates
990 * This will insert a point into the route graph at the coordinates passed in f.
991 * Note that the point is not yet linked to any segments.
993 * @param this The route to insert the point into
994 * @param f The coordinates at which the point should be inserted
995 * @return The point inserted or NULL on failure
997 static struct route_graph_point *
998 route_graph_add_point(struct route_graph *this, struct coord *f)
1000 struct route_graph_point *p;
1002 p=route_graph_get_point(this,f);
1004 p=route_graph_point_new(this,f);
1009 * @brief Frees all the memory used for points in the route graph passed
1011 * @param this The route graph to delete all points from
1014 route_graph_free_points(struct route_graph *this)
1016 struct route_graph_point *curr,*next;
1018 for (i = 0 ; i < HASH_SIZE ; i++) {
1021 next=curr->hash_next;
1030 * @brief Returns the position of a certain field appended to a route graph segment
1032 * This function returns a pointer to a field that is appended to a route graph
1035 * @param seg The route graph segment the field is appended to
1036 * @param type Type of the field that should be returned
1037 * @return A pointer to a field of a certain type, or NULL if no such field is present
1040 route_segment_data_field_pos(struct route_segment_data *seg, enum attr_type type)
1044 ptr = ((unsigned char*)seg) + sizeof(struct route_segment_data);
1046 if (seg->flags & AF_SPEED_LIMIT) {
1047 if (type == attr_maxspeed)
1051 if (seg->flags & AF_SEGMENTED) {
1052 if (type == attr_offset)
1060 * @brief Calculates the size of a route_segment_data struct with given flags
1062 * @param flags The flags of the route_segment_data
1066 route_segment_data_size(int flags)
1068 int ret=sizeof(struct route_segment_data);
1069 if (flags & AF_SPEED_LIMIT)
1071 if (flags & AF_SEGMENTED)
1078 route_graph_segment_is_duplicate(struct route_graph_point *start, struct item *item, int flags, int offset)
1080 struct route_graph_segment *s;
1083 if (item_is_equal(*item, s->data.item)) {
1084 if (flags & AF_SEGMENTED) {
1085 if (RSD_OFFSET(&s->data) == offset) {
1097 * @brief Inserts a new segment into the route graph
1099 * This function performs a check if a segment for the item specified already exists, and inserts
1100 * a new segment representing this item if it does not.
1102 * @param this The route graph to insert the segment into
1103 * @param start The graph point which should be connected to the start of this segment
1104 * @param end The graph point which should be connected to the end of this segment
1105 * @param len The length of this segment
1106 * @param item The item that is represented by this segment
1107 * @param flags Flags for this segment
1108 * @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
1109 * @param maxspeed The maximum speed allowed on this segment in km/h. -1 if not known.
1112 route_graph_add_segment(struct route_graph *this, struct route_graph_point *start,
1113 struct route_graph_point *end, int len, struct item *item,
1114 int flags, int offset, int maxspeed)
1116 struct route_graph_segment *s;
1119 size = sizeof(struct route_graph_segment)-sizeof(struct route_segment_data)+route_segment_data_size(flags);
1120 s = g_malloc0(size);
1122 printf("%s:Out of memory\n", __FUNCTION__);
1126 s->start_next=start->start;
1129 s->end_next=end->end;
1131 dbg_assert(len >= 0);
1134 s->data.flags=flags;
1136 if (flags & AF_SPEED_LIMIT)
1137 RSD_MAXSPEED(&s->data)=maxspeed;
1138 if (flags & AF_SEGMENTED)
1139 RSD_OFFSET(&s->data)=offset;
1141 s->next=this->route_segments;
1142 this->route_segments=s;
1144 printf("l (0x%x,0x%x)-(0x%x,0x%x)\n", start->c.x, start->c.y, end->c.x, end->c.y);
1148 * @brief Gets all the coordinates of an item
1150 * This will get all the coordinates of the item i and return them in c,
1151 * up to max coordinates. Additionally it is possible to limit the coordinates
1152 * returned to all the coordinates of the item between the two coordinates
1155 * @important Make sure that whatever c points to has enough memory allocated
1156 * @important to hold max coordinates!
1158 * @param i The item to get the coordinates of
1159 * @param c Pointer to memory allocated for holding the coordinates
1160 * @param max Maximum number of coordinates to return
1161 * @param start First coordinate to get
1162 * @param end Last coordinate to get
1163 * @return The number of coordinates returned
1165 static int get_item_seg_coords(struct item *i, struct coord *c, int max,
1166 struct coord *start, struct coord *end)
1168 struct map_rect *mr;
1172 mr=map_rect_new(i->map, NULL);
1175 item = map_rect_get_item_byid(mr, i->id_hi, i->id_lo);
1177 rc = item_coord_get(item, &c1, 1);
1178 while (rc && (c1.x != start->x || c1.y != start->y)) {
1179 rc = item_coord_get(item, &c1, 1);
1181 while (rc && p < max) {
1183 if (c1.x == end->x && c1.y == end->y)
1185 rc = item_coord_get(item, &c1, 1);
1188 map_rect_destroy(mr);
1193 * @brief Returns and removes one segment from a path
1195 * @param path The path to take the segment from
1196 * @param item The item whose segment to remove
1197 * @param offset Offset of the segment within the item to remove. If the item is not segmented this should be 1.
1198 * @return The segment removed
1200 static struct route_path_segment *
1201 route_extract_segment_from_path(struct route_path *path, struct item *item,
1205 struct route_path_segment *sp = NULL, *s;
1208 if (item_is_equal(s->data->item,*item)) {
1209 if (s->data->flags & AF_SEGMENTED)
1210 soffset=RSD_OFFSET(s->data);
1213 if (soffset == offset) {
1218 path->path = s->next;
1227 item_hash_remove(path->path_hash, item);
1232 * @brief Adds a segment and the end of a path
1234 * @param this The path to add the segment to
1235 * @param segment The segment to add
1238 route_path_add_segment(struct route_path *this, struct route_path_segment *segment)
1242 if (this->path_last)
1243 this->path_last->next=segment;
1244 this->path_last=segment;
1248 * @brief Adds a two coordinate line to a path
1250 * This adds a new line to a path, creating a new segment for it.
1252 * @param this The path to add the item to
1253 * @param start coordinate to add to the start of the item. If none should be added, make this NULL.
1254 * @param end coordinate to add to the end of the item. If none should be added, make this NULL.
1255 * @param len The length of the item
1258 route_path_add_line(struct route_path *this, struct coord *start, struct coord *end, int len)
1261 struct route_path_segment *segment;
1262 int seg_size,seg_dat_size;
1264 dbg(1,"line from 0x%x,0x%x-0x%x,0x%x\n", start->x, start->y, end->x, end->y);
1265 seg_size=sizeof(*segment) + sizeof(struct coord) * ccnt;
1266 seg_dat_size=sizeof(struct route_segment_data);
1267 segment=g_malloc0(seg_size + seg_dat_size);
1268 segment->data=(struct route_segment_data *)((char *)segment+seg_size);
1269 segment->ncoords=ccnt;
1270 segment->direction=0;
1271 segment->c[0]=*start;
1273 segment->data->len=len;
1274 route_path_add_segment(this, segment);
1278 * @brief Inserts a new item into the path
1280 * This function does almost the same as "route_path_add_item()", but identifies
1281 * the item to add by a segment from the route graph. Another difference is that it "copies" the
1282 * segment from the route graph, i.e. if the item is segmented, only the segment passed in rgs will
1283 * be added to the route path, not all segments of the item.
1285 * The function can be sped up by passing an old path already containing this segment in oldpath -
1286 * the segment will then be extracted from this old path. Please note that in this case the direction
1287 * parameter has no effect.
1289 * @param this The path to add the item to
1290 * @param oldpath Old path containing the segment to be added. Speeds up the function, but can be NULL.
1291 * @param rgs Segment of the route graph that should be "copied" to the route path
1292 * @param dir Order in which to add the coordinates. See route_path_add_item()
1293 * @param pos Information about start point if this is the first segment
1294 * @param dst Information about end point if this is the last segment
1298 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)
1300 struct route_path_segment *segment;
1301 int i, ccnt, extra=0, ret=0;
1302 struct coord *c,*cd,ca[2048];
1304 int seg_size,seg_dat_size;
1305 int len=rgs->data.len;
1306 if (rgs->data.flags & AF_SEGMENTED)
1307 offset=RSD_OFFSET(&rgs->data);
1309 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);
1311 segment=item_hash_lookup(oldpath->path_hash, &rgs->data.item);
1312 if (segment && segment->direction == dir) {
1313 segment = route_extract_segment_from_path(oldpath, &rgs->data.item, offset);
1325 if (dst->lenneg >= pos->lenneg) {
1327 ccnt=dst->pos-pos->pos;
1328 c=pos->street->c+pos->pos+1;
1329 len=dst->lenneg-pos->lenneg;
1332 ccnt=pos->pos-dst->pos;
1333 c=pos->street->c+dst->pos+1;
1334 len=pos->lenneg-dst->lenneg;
1338 dbg(1,"pos dir=%d\n", dir);
1339 dbg(1,"pos pos=%d\n", pos->pos);
1340 dbg(1,"pos count=%d\n", pos->street->count);
1342 c=pos->street->c+pos->pos+1;
1343 ccnt=pos->street->count-pos->pos-1;
1354 dbg(1,"dst dir=%d\n", dir);
1355 dbg(1,"dst pos=%d\n", dst->pos);
1361 c=dst->street->c+dst->pos+1;
1362 ccnt=dst->street->count-dst->pos-1;
1366 ccnt=get_item_seg_coords(&rgs->data.item, ca, 2047, &rgs->start->c, &rgs->end->c);
1369 seg_size=sizeof(*segment) + sizeof(struct coord) * (ccnt + extra);
1370 seg_dat_size=route_segment_data_size(rgs->data.flags);
1371 segment=g_malloc0(seg_size + seg_dat_size);
1372 segment->data=(struct route_segment_data *)((char *)segment+seg_size);
1373 segment->direction=dir;
1375 if (pos && (c[0].x != pos->lp.x || c[0].y != pos->lp.y))
1379 for (i = 0 ; i < ccnt ; i++) {
1383 segment->ncoords+=ccnt;
1384 if (dst && (cd[-1].x != dst->lp.x || cd[-1].y != dst->lp.y))
1386 segment->ncoords=cd-segment->c;
1387 if (segment->ncoords <= 1) {
1392 /* We check if the route graph segment is part of a roundabout here, because this
1393 * only matters for route graph segments which form parts of the route path */
1394 if (!(rgs->data.flags & AF_ROUNDABOUT)) { // We identified this roundabout earlier
1395 route_check_roundabout(rgs, 13, (dir < 1), NULL);
1398 memcpy(segment->data, &rgs->data, seg_dat_size);
1400 segment->data->len=len;
1402 item_hash_insert(this->path_hash, &rgs->data.item, segment);
1404 route_path_add_segment(this, segment);
1410 * @brief Destroys all segments of a route graph
1412 * @param this The graph to destroy all segments from
1415 route_graph_free_segments(struct route_graph *this)
1417 struct route_graph_segment *curr,*next;
1418 curr=this->route_segments;
1424 this->route_segments=NULL;
1428 * @brief Destroys a route graph
1430 * @param this The route graph to be destroyed
1433 route_graph_destroy(struct route_graph *this)
1436 route_graph_build_done(this, 1);
1437 route_graph_free_points(this);
1438 route_graph_free_segments(this);
1444 * @brief Returns the time needed to drive len on item
1446 * This function returns the time needed to drive len meters on
1447 * the item passed in item in tenth of seconds.
1449 * @param profile The routing preferences
1450 * @param over The segment which is passed
1451 * @return The time needed to drive len on item in thenth of senconds
1455 route_time_seg(struct vehicleprofile *profile, struct route_segment_data *over, struct route_traffic_distortion *dist)
1457 struct roadprofile *roadprofile=vehicleprofile_get_roadprofile(profile, over->item.type);
1459 if (!roadprofile || !roadprofile->route_weight)
1461 /* maxspeed_handling: 0=always, 1 only if maxspeed restricts the speed, 2 never */
1462 speed=roadprofile->route_weight;
1463 if (profile->maxspeed_handling != 2) {
1464 if (over->flags & AF_SPEED_LIMIT) {
1465 maxspeed=RSD_MAXSPEED(over);
1466 if (!profile->maxspeed_handling)
1470 if (dist && maxspeed > dist->maxspeed)
1471 maxspeed=dist->maxspeed;
1472 if (maxspeed != INT_MAX && (profile->maxspeed_handling != 1 || maxspeed < speed))
1477 return over->len*36/speed+(dist ? dist->delay : 0);
1481 route_get_traffic_distortion(struct route_graph_segment *seg, struct route_traffic_distortion *ret)
1483 struct route_graph_point *start=seg->start;
1484 struct route_graph_point *end=seg->end;
1485 struct route_graph_segment *tmp,*found=NULL;
1487 while (tmp && !found) {
1488 if (tmp->data.item.type == type_traffic_distortion && tmp->start == start && tmp->end == end)
1490 tmp=tmp->start_next;
1493 while (tmp && !found) {
1494 if (tmp->data.item.type == type_traffic_distortion && tmp->end == start && tmp->start == end)
1499 ret->delay=found->data.len;
1500 if (found->data.flags & AF_SPEED_LIMIT)
1501 ret->maxspeed=RSD_MAXSPEED(&found->data);
1503 ret->maxspeed=INT_MAX;
1510 * @brief Returns the "costs" of driving from point from over segment over in direction dir
1512 * @param profile The routing preferences
1513 * @param from The point where we are starting
1514 * @param over The segment we are using
1515 * @param dir The direction of segment which we are driving
1516 * @return The "costs" needed to drive len on item
1520 route_value_seg(struct vehicleprofile *profile, struct route_graph_point *from, struct route_graph_segment *over, int dir)
1523 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);
1525 if ((over->data.flags & (dir >= 0 ? profile->flags_forward_mask : profile->flags_reverse_mask)) != profile->flags)
1527 if (dir > 0 && (over->start->flags & RP_TURN_RESTRICTION))
1529 if (dir < 0 && (over->end->flags & RP_TURN_RESTRICTION))
1531 if (from && from->seg == over)
1533 if ((over->start->flags & RP_TRAFFIC_DISTORTION) && (over->end->flags & RP_TRAFFIC_DISTORTION)) {
1534 struct route_traffic_distortion dist;
1535 if (route_get_traffic_distortion(over, &dist))
1536 return route_time_seg(profile, &over->data, &dist);
1538 return route_time_seg(profile, &over->data, NULL);
1542 * @brief Adds a route distortion item to the route graph
1544 * @param this The route graph to add to
1545 * @param item The item to add
1548 route_process_traffic_distortion(struct route_graph *this, struct item *item)
1550 struct route_graph_point *s_pnt,*e_pnt;
1552 struct attr delay_attr, maxspeed_attr;
1556 int maxspeed = INT_MAX;
1558 if (item_coord_get(item, &l, 1)) {
1559 s_pnt=route_graph_add_point(this,&l);
1560 while (item_coord_get(item, &c, 1)) {
1563 e_pnt=route_graph_add_point(this,&l);
1564 s_pnt->flags |= RP_TRAFFIC_DISTORTION;
1565 e_pnt->flags |= RP_TRAFFIC_DISTORTION;
1566 if (item_attr_get(item, attr_maxspeed, &maxspeed_attr)) {
1567 flags |= AF_SPEED_LIMIT;
1568 maxspeed=maxspeed_attr.u.num;
1570 if (item_attr_get(item, attr_delay, &delay_attr))
1571 len=delay_attr.u.num;
1572 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset, maxspeed);
1577 * @brief Adds a route distortion item to the route graph
1579 * @param this The route graph to add to
1580 * @param item The item to add
1583 route_process_turn_restriction(struct route_graph *this, struct item *item)
1585 struct route_graph_point *pnt[4];
1589 count=item_coord_get(item, c, 5);
1590 if (count != 3 && count != 4) {
1591 dbg(0,"wrong count %d\n",count);
1596 for (i = 0 ; i < count ; i++)
1597 pnt[i]=route_graph_add_point(this,&c[i]);
1598 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]);
1599 route_graph_add_segment(this, pnt[0], pnt[1], 0, item, 0, 0, 0);
1600 route_graph_add_segment(this, pnt[1], pnt[2], 0, item, 0, 0, 0);
1602 pnt[1]->flags |= RP_TURN_RESTRICTION;
1603 pnt[2]->flags |= RP_TURN_RESTRICTION;
1604 route_graph_add_segment(this, pnt[2], pnt[3], 0, item, 0, 0, 0);
1606 pnt[1]->flags |= RP_TURN_RESTRICTION;
1611 * @brief Adds an item to the route graph
1613 * This adds an item (e.g. a street) to the route graph, creating as many segments as needed for a
1616 * @param this The route graph to add to
1617 * @param item The item to add
1620 route_process_street_graph(struct route_graph *this, struct item *item)
1627 struct route_graph_point *s_pnt,*e_pnt;
1629 struct attr flags_attr, maxspeed_attr;
1635 if (item_coord_get(item, &l, 1)) {
1636 int *default_flags=item_get_default_flags(item->type);
1637 if (! default_flags)
1639 if (item_attr_get(item, attr_flags, &flags_attr)) {
1640 flags = flags_attr.u.num;
1641 if (flags & AF_SEGMENTED)
1644 flags = *default_flags;
1647 if (flags & AF_SPEED_LIMIT) {
1648 if (item_attr_get(item, attr_maxspeed, &maxspeed_attr)) {
1649 maxspeed = maxspeed_attr.u.num;
1653 s_pnt=route_graph_add_point(this,&l);
1655 while (item_coord_get(item, &c, 1)) {
1656 len+=transform_distance(map_projection(item->map), &l, &c);
1659 e_pnt=route_graph_add_point(this,&l);
1660 dbg_assert(len >= 0);
1661 if (!route_graph_segment_is_duplicate(s_pnt, item, flags, offset))
1662 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset, maxspeed);
1667 isseg = item_coord_is_node(item);
1668 rc = item_coord_get(item, &c, 1);
1670 len+=transform_distance(map_projection(item->map), &l, &c);
1673 e_pnt=route_graph_add_point(this,&l);
1674 if (!route_graph_segment_is_duplicate(s_pnt, item, flags, offset))
1675 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset, maxspeed);
1677 s_pnt=route_graph_add_point(this,&l);
1682 e_pnt=route_graph_add_point(this,&l);
1683 dbg_assert(len >= 0);
1685 if (!route_graph_segment_is_duplicate(s_pnt, item, flags, offset))
1686 route_graph_add_segment(this, s_pnt, e_pnt, len, item, flags, offset, maxspeed);
1691 static struct route_graph_segment *
1692 route_graph_get_segment(struct route_graph *graph, struct street_data *sd, struct route_graph_segment *last)
1694 struct route_graph_point *start=NULL;
1695 struct route_graph_segment *s;
1698 while ((start=route_graph_get_point_next(graph, &sd->c[0], start))) {
1701 if (item_is_equal(sd->item, s->data.item)) {
1714 * @brief Calculates the routing costs for each point
1716 * This function is the heart of routing. It assigns each point in the route graph a
1717 * cost at which one can reach the destination from this point on. Additionally it assigns
1718 * each point a segment one should follow from this point on to reach the destination at the
1721 * This function uses Dijkstra's algorithm to do the routing. To understand it you should have a look
1722 * at this algorithm.
1725 route_graph_flood(struct route_graph *this, struct route_info *dst, struct vehicleprofile *profile, struct callback *cb)
1727 struct route_graph_point *p_min;
1728 struct route_graph_segment *s=NULL;
1729 int min,new,old,val;
1730 struct fibheap *heap; /* This heap will hold all points with "temporarily" calculated costs */
1732 heap = fh_makekeyheap();
1734 while ((s=route_graph_get_segment(this, dst->street, s))) {
1735 val=route_value_seg(profile, NULL, s, -1);
1736 if (val != INT_MAX) {
1737 val=val*(100-dst->percent)/100;
1740 s->end->el=fh_insertkey(heap, s->end->value, s->end);
1742 val=route_value_seg(profile, NULL, s, 1);
1743 if (val != INT_MAX) {
1744 val=val*dst->percent/100;
1746 s->start->value=val;
1747 s->start->el=fh_insertkey(heap, s->start->value, s->start);
1751 p_min=fh_extractmin(heap); /* Starting Dijkstra by selecting the point with the minimum costs on the heap */
1752 if (! p_min) /* There are no more points with temporarily calculated costs, Dijkstra has finished */
1756 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);
1757 p_min->el=NULL; /* This point is permanently calculated now, we've taken it out of the heap */
1759 while (s) { /* Iterating all the segments leading away from our point to update the points at their ends */
1760 val=route_value_seg(profile, p_min, s, -1);
1761 if (val != INT_MAX) {
1764 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);
1765 if (new < s->end->value) { /* We've found a less costly way to reach the end of s, update it */
1770 printf("insert_end p=%p el=%p val=%d ", s->end, s->end->el, s->end->value);
1771 s->end->el=fh_insertkey(heap, new, s->end);
1773 printf("el new=%p\n", s->end->el);
1777 printf("replace_end p=%p el=%p val=%d\n", s->end, s->end->el, s->end->value);
1778 fh_replacekey(heap, s->end->el, new);
1787 while (s) { /* Doing the same as above with the segments leading towards our point */
1788 val=route_value_seg(profile, p_min, s, 1);
1789 if (val != INT_MAX) {
1792 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);
1793 if (new < s->start->value) {
1794 old=s->start->value;
1795 s->start->value=new;
1797 if (! s->start->el) {
1799 printf("insert_start p=%p el=%p val=%d ", s->start, s->start->el, s->start->value);
1800 s->start->el=fh_insertkey(heap, new, s->start);
1802 printf("el new=%p\n", s->start->el);
1806 printf("replace_start p=%p el=%p val=%d\n", s->start, s->start->el, s->start->value);
1807 fh_replacekey(heap, s->start->el, new);
1816 fh_deleteheap(heap);
1817 callback_call_0(cb);
1822 * @brief Starts an "offroad" path
1824 * This starts a path that is not located on a street. It creates a new route path
1825 * adding only one segment, that leads from pos to dest, and which is not associated with an item.
1827 * @param this Not used
1828 * @param pos The starting position for the new path
1829 * @param dst The destination of the new path
1830 * @param dir Not used
1831 * @return The new path
1833 static struct route_path *
1834 route_path_new_offroad(struct route_graph *this, struct route_info *pos, struct route_info *dst)
1836 struct route_path *ret;
1838 ret=g_new0(struct route_path, 1);
1839 ret->path_hash=item_hash_new();
1840 route_path_add_line(ret, &pos->c, &dst->c, pos->lenextra+dst->lenextra);
1847 * @brief Returns a coordinate at a given distance
1849 * This function returns the coordinate, where the user will be if he
1850 * follows the current route for a certain distance.
1852 * @param this_ The route we're driving upon
1853 * @param dist The distance in meters
1854 * @return The coordinate where the user will be in that distance
1857 route_get_coord_dist(struct route *this_, int dist)
1862 struct route_path_segment *cur;
1864 enum projection pro=route_projection(this_);
1868 if (!this_->path2 || pro == projection_none) {
1869 return this_->pos->c;
1872 ret = this_->pos->c;
1873 cur = this_->path2->path;
1875 if (cur->data->len < d) {
1876 d -= cur->data->len;
1878 for (i=0; i < (cur->ncoords-1); i++) {
1880 len = (int)transform_polyline_length(pro, (cur->c + i), 2);
1883 // We interpolate a bit here...
1884 frac = (double)l / len;
1886 dx = (cur->c + i + 1)->x - (cur->c + i)->x;
1887 dy = (cur->c + i + 1)->y - (cur->c + i)->y;
1889 ret.x = (cur->c + i)->x + (frac * dx);
1890 ret.y = (cur->c + i)->y + (frac * dy);
1894 return cur->c[(cur->ncoords-1)];
1899 return this_->dst->c;
1903 * @brief Creates a new route path
1905 * This creates a new non-trivial route. It therefore needs the routing information created by route_graph_flood, so
1906 * make sure to run route_graph_flood() after changing the destination before using this function.
1908 * @param this The route graph to create the route from
1909 * @param oldpath (Optional) old path which may contain parts of the new part - this speeds things up a bit. May be NULL.
1910 * @param pos The starting position of the route
1911 * @param dst The destination of the route
1912 * @param preferences The routing preferences
1913 * @return The new route path
1915 static struct route_path *
1916 route_path_new(struct route_graph *this, struct route_path *oldpath, struct route_info *pos, struct route_info *dst, struct vehicleprofile *profile)
1918 struct route_graph_segment *first,*s=NULL;
1919 struct route_graph_point *start;
1920 struct route_info *posinfo, *dstinfo;
1922 int val1=INT_MAX,val2=INT_MAX;
1924 struct route_path *ret;
1926 if (! pos->street || ! dst->street)
1929 if (profile->mode == 2 || (profile->mode == 0 && pos->lenextra + dst->lenextra > transform_distance(map_projection(pos->street->item.map), &pos->c, &dst->c)))
1930 return route_path_new_offroad(this, pos, dst);
1932 s=route_graph_get_segment(this, pos->street, NULL);
1934 dbg(0,"no segment for position found\n");
1937 val=route_value_seg(profile, NULL, s, 1);
1938 if (val != INT_MAX && s->end->value != INT_MAX) {
1939 val=val*(100-pos->percent)/100;
1940 val1=s->end->value+val;
1942 val=route_value_seg(profile, NULL, s, -1);
1943 if (val != INT_MAX && s->start->value != INT_MAX) {
1944 val=val*pos->percent/100;
1945 val2=s->start->value+val;
1947 if (val1 == INT_MAX && val2 == INT_MAX) {
1948 dbg(0,"no route found, pos blocked\n");
1953 val2=s->start->value;
1959 ret=g_new0(struct route_path, 1);
1962 route_path_add_line(ret, &pos->c, &pos->lp, pos->lenextra);
1963 ret->path_hash=item_hash_new();
1967 while (s && !dstinfo) { /* following start->seg, which indicates the least costly way to reach our destination */
1970 printf("start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
1972 if (s->start == start) {
1973 if (item_is_equal(s->data.item, dst->street->item) && (s->end->seg == s || !posinfo))
1975 if (!route_path_add_item_from_graph(ret, oldpath, s, 1, posinfo, dstinfo))
1979 if (item_is_equal(s->data.item, dst->street->item) && (s->start->seg == s || !posinfo))
1981 if (!route_path_add_item_from_graph(ret, oldpath, s, -1, posinfo, dstinfo))
1989 route_path_add_line(ret, &dst->lp, &dst->c, dst->lenextra);
1990 dbg(1, "%d segments\n", segs);
1995 route_graph_build_next_map(struct route_graph *rg)
1998 rg->m=mapset_next(rg->h, 2);
2001 map_rect_destroy(rg->mr);
2002 rg->mr=map_rect_new(rg->m, rg->sel);
2010 is_turn_allowed(struct route_graph_point *p, struct route_graph_segment *from, struct route_graph_segment *to)
2012 struct route_graph_point *prev,*next;
2013 struct route_graph_segment *tmp1,*tmp2;
2014 if (from->start == p)
2024 if (tmp1->start->c.x == prev->c.x && tmp1->start->c.y == prev->c.y &&
2025 (tmp1->data.item.type == type_street_turn_restriction_no ||
2026 tmp1->data.item.type == type_street_turn_restriction_only)) {
2028 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);
2030 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);
2031 if (item_is_equal(tmp1->data.item, tmp2->data.item))
2033 tmp2=tmp2->start_next;
2035 dbg(1,"tmp2=%p\n",tmp2);
2037 dbg(1,"%s tmp2->end=%p next=%p\n",item_to_name(tmp1->data.item.type),tmp2->end,next);
2039 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) {
2040 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);
2043 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)) {
2044 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);
2048 tmp1=tmp1->end_next;
2050 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);
2055 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)
2059 if (s->data.flags & AF_SPEED_LIMIT)
2060 maxspeed=RSD_MAXSPEED(&s->data);
2061 if (s->data.flags & AF_SEGMENTED)
2062 offset=RSD_OFFSET(&s->data);
2063 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);
2064 route_graph_add_segment(this, start, end, s->data.len+1, &s->data.item, s->data.flags | flags, offset, maxspeed);
2068 route_graph_process_restriction_segment(struct route_graph *this, struct route_graph_point *p, struct route_graph_segment *s, int dir)
2070 struct route_graph_segment *tmp;
2071 struct route_graph_point *pn;
2072 struct coord c=p->c;
2077 dbg(1,"From %s %d,%d\n",item_to_name(s->data.item.type),dx,dy);
2078 pn=route_graph_point_new(this, &c);
2079 if (dir > 0) { /* going away */
2080 dbg(1,"other 0x%x,0x%x\n",s->end->c.x,s->end->c.y);
2081 if (s->data.flags & AF_ONEWAY) {
2082 dbg(1,"Not possible\n");
2085 route_graph_clone_segment(this, s, pn, s->end, AF_ONEWAYREV);
2086 } else { /* coming in */
2087 dbg(1,"other 0x%x,0x%x\n",s->start->c.x,s->start->c.y);
2088 if (s->data.flags & AF_ONEWAYREV) {
2089 dbg(1,"Not possible\n");
2092 route_graph_clone_segment(this, s, s->start, pn, AF_ONEWAY);
2096 if (tmp != s && tmp->data.item.type != type_street_turn_restriction_no &&
2097 tmp->data.item.type != type_street_turn_restriction_only &&
2098 !(tmp->data.flags & AF_ONEWAYREV) && is_turn_allowed(p, s, tmp)) {
2099 route_graph_clone_segment(this, tmp, pn, tmp->end, AF_ONEWAY);
2100 dbg(1,"To start %s\n",item_to_name(tmp->data.item.type));
2102 tmp=tmp->start_next;
2106 if (tmp != s && tmp->data.item.type != type_street_turn_restriction_no &&
2107 tmp->data.item.type != type_street_turn_restriction_only &&
2108 !(tmp->data.flags & AF_ONEWAY) && is_turn_allowed(p, s, tmp)) {
2109 route_graph_clone_segment(this, tmp, tmp->start, pn, AF_ONEWAYREV);
2110 dbg(1,"To end %s\n",item_to_name(tmp->data.item.type));
2117 route_graph_process_restriction_point(struct route_graph *this, struct route_graph_point *p)
2119 struct route_graph_segment *tmp;
2121 dbg(1,"node 0x%x,0x%x\n",p->c.x,p->c.y);
2123 if (tmp->data.item.type != type_street_turn_restriction_no &&
2124 tmp->data.item.type != type_street_turn_restriction_only)
2125 route_graph_process_restriction_segment(this, p, tmp, 1);
2126 tmp=tmp->start_next;
2130 if (tmp->data.item.type != type_street_turn_restriction_no &&
2131 tmp->data.item.type != type_street_turn_restriction_only)
2132 route_graph_process_restriction_segment(this, p, tmp, -1);
2135 p->flags |= RP_TURN_RESTRICTION_RESOLVED;
2139 route_graph_process_restrictions(struct route_graph *this)
2141 struct route_graph_point *curr;
2144 for (i = 0 ; i < HASH_SIZE ; i++) {
2147 if (curr->flags & RP_TURN_RESTRICTION)
2148 route_graph_process_restriction_point(this, curr);
2149 curr=curr->hash_next;
2155 route_graph_build_done(struct route_graph *rg, int cancel)
2157 dbg(1,"cancel=%d\n",cancel);
2159 event_remove_idle(rg->idle_ev);
2161 callback_destroy(rg->idle_cb);
2162 map_rect_destroy(rg->mr);
2163 mapset_close(rg->h);
2164 route_free_selection(rg->sel);
2170 route_graph_process_restrictions(rg);
2172 callback_call_0(rg->done_cb);
2177 route_graph_build_idle(struct route_graph *rg)
2184 item=map_rect_get_item(rg->mr);
2187 if (!route_graph_build_next_map(rg)) {
2188 route_graph_build_done(rg, 0);
2192 if (item->type == type_traffic_distortion)
2193 route_process_traffic_distortion(rg, item);
2194 else if (item->type == type_street_turn_restriction_no || item->type == type_street_turn_restriction_only)
2195 route_process_turn_restriction(rg, item);
2197 route_process_street_graph(rg, item);
2203 * @brief Builds a new route graph from a mapset
2205 * This function builds a new route graph from a map. Please note that this function does not
2206 * add any routing information to the route graph - this has to be done via the route_graph_flood()
2209 * The function does not create a graph covering the whole map, but only covering the rectangle
2210 * between c1 and c2.
2212 * @param ms The mapset to build the route graph from
2213 * @param c1 Corner 1 of the rectangle to use from the map
2214 * @param c2 Corner 2 of the rectangle to use from the map
2215 * @param done_cb The callback which will be called when graph is complete
2216 * @return The new route graph.
2218 static struct route_graph *
2219 route_graph_build(struct mapset *ms, struct coord *c1, struct coord *c2, struct callback *done_cb, int async)
2221 struct route_graph *ret=g_new0(struct route_graph, 1);
2225 ret->sel=route_calc_selection(c1, c2);
2226 ret->h=mapset_open(ms);
2227 ret->done_cb=done_cb;
2229 if (route_graph_build_next_map(ret)) {
2231 ret->idle_cb=callback_new_1(callback_cast(route_graph_build_idle), ret);
2232 ret->idle_ev=event_add_idle(50, ret->idle_cb);
2235 route_graph_build_done(ret, 0);
2241 route_graph_update_done(struct route *this, struct callback *cb)
2243 route_graph_flood(this->graph, this->dst, this->vehicleprofile, cb);
2247 * @brief Updates the route graph
2249 * This updates the route graph after settings in the route have changed. It also
2250 * adds routing information afterwards by calling route_graph_flood().
2252 * @param this The route to update the graph for
2255 route_graph_update(struct route *this, struct callback *cb, int async)
2257 struct attr route_status;
2259 route_status.type=attr_route_status;
2260 route_graph_destroy(this->graph);
2261 callback_destroy(this->route_graph_done_cb);
2262 this->route_graph_done_cb=callback_new_2(callback_cast(route_graph_update_done), this, cb);
2263 route_status.u.num=route_status_building_graph;
2264 route_set_attr(this, &route_status);
2265 this->graph=route_graph_build(this->ms, &this->pos->c, &this->dst->c, this->route_graph_done_cb, async);
2267 while (this->graph->busy)
2268 route_graph_build_idle(this->graph);
2273 * @brief Gets street data for an item
2275 * @param item The item to get the data for
2276 * @return Street data for the item
2278 struct street_data *
2279 street_get_data (struct item *item)
2282 struct street_data *ret = NULL, *ret1;
2283 struct attr flags_attr, maxspeed_attr;
2284 const int step = 128;
2288 ret1=g_realloc(ret, sizeof(struct street_data)+(count+step)*sizeof(struct coord));
2295 c = item_coord_get(item, &ret->c[count], step);
2297 } while (c && c == step);
2299 ret1=g_realloc(ret, sizeof(struct street_data)+count*sizeof(struct coord));
2304 if (item_attr_get(item, attr_flags, &flags_attr))
2305 ret->flags=flags_attr.u.num;
2307 flags=item_get_default_flags(item->type);
2315 if (ret->flags & AF_SPEED_LIMIT) {
2316 if (item_attr_get(item, attr_maxspeed, &maxspeed_attr)) {
2317 ret->maxspeed = maxspeed_attr.u.num;
2325 * @brief Copies street data
2327 * @param orig The street data to copy
2328 * @return The copied street data
2330 struct street_data *
2331 street_data_dup(struct street_data *orig)
2333 struct street_data *ret;
2334 int size=sizeof(struct street_data)+orig->count*sizeof(struct coord);
2337 memcpy(ret, orig, size);
2343 * @brief Frees street data
2345 * @param sd Street data to be freed
2348 street_data_free(struct street_data *sd)
2354 * @brief Finds the nearest street to a given coordinate
2356 * @param ms The mapset to search in for the street
2357 * @param pc The coordinate to find a street nearby
2358 * @return The nearest street
2360 static struct route_info *
2361 route_find_nearest_street(struct vehicleprofile *vehicleprofile, struct mapset *ms, struct pcoord *pc)
2363 struct route_info *ret=NULL;
2365 struct map_selection *sel;
2366 int dist,mindist=0,pos;
2367 struct mapset_handle *h;
2369 struct map_rect *mr;
2372 struct street_data *sd;
2376 ret=g_new0(struct route_info, 1);
2380 while ((m=mapset_next(h,2))) {
2383 if (map_projection(m) != pc->pro) {
2384 transform_to_geo(pc->pro, &c, &g);
2385 transform_from_geo(map_projection(m), &g, &c);
2387 sel = route_rect(18, &c, &c, 0, max_dist);
2390 mr=map_rect_new(m, sel);
2392 map_selection_destroy(sel);
2395 while ((item=map_rect_get_item(mr))) {
2396 if (item_get_default_flags(item->type)) {
2397 sd=street_get_data(item);
2400 dist=transform_distance_polyline_sq(sd->c, sd->count, &c, &lp, &pos);
2401 if (dist < mindist && (
2402 (sd->flags & vehicleprofile->flags_forward_mask) == vehicleprofile->flags ||
2403 (sd->flags & vehicleprofile->flags_reverse_mask) == vehicleprofile->flags)) {
2406 street_data_free(ret->street);
2412 dbg(1,"dist=%d id 0x%x 0x%x pos=%d\n", dist, item->id_hi, item->id_lo, pos);
2414 street_data_free(sd);
2418 map_selection_destroy(sel);
2419 map_rect_destroy(mr);
2423 if (!ret->street || mindist > max_dist*max_dist) {
2425 street_data_free(ret->street);
2426 dbg(1,"Much too far %d > %d\n", mindist, max_dist);
2436 * @brief Destroys a route_info
2438 * @param info The route info to be destroyed
2441 route_info_free(struct route_info *inf)
2444 street_data_free(inf->street);
2452 * @brief Returns street data for a route info
2454 * @param rinf The route info to return the street data for
2455 * @return Street data for the route info
2457 struct street_data *
2458 route_info_street(struct route_info *rinf)
2460 return rinf->street;
2464 struct route_crossings *
2465 route_crossings_get(struct route *this, struct coord *c)
2467 struct route_point *pnt;
2468 struct route_segment *seg;
2470 struct route_crossings *ret;
2472 pnt=route_graph_get_point(this, c);
2475 printf("start: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
2477 seg=seg->start_next;
2481 printf("end: 0x%x 0x%x\n", seg->item.id_hi, seg->item.id_lo);
2485 ret=g_malloc(sizeof(struct route_crossings)+crossings*sizeof(struct route_crossing));
2486 ret->count=crossings;
2492 struct map_rect_priv {
2493 struct route_info_handle *ri;
2494 enum attr_type attr_next;
2496 struct map_priv *mpriv;
2498 unsigned int last_coord;
2499 struct route_path *path;
2500 struct route_path_segment *seg,*seg_next;
2501 struct route_graph_point *point;
2502 struct route_graph_segment *rseg;
2505 struct coord *coord_sel; /**< Set this to a coordinate if you want to filter for just a single route graph point */
2506 struct route_graph_point_iterator it;
2510 rm_coord_rewind(void *priv_data)
2512 struct map_rect_priv *mr = priv_data;
2517 rm_attr_rewind(void *priv_data)
2519 struct map_rect_priv *mr = priv_data;
2520 mr->attr_next = attr_street_item;
2524 rm_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
2526 struct map_rect_priv *mr = priv_data;
2527 struct route_path_segment *seg=mr->seg;
2528 struct route *route=mr->mpriv->route;
2529 if (mr->item.type != type_street_route)
2531 attr->type=attr_type;
2532 switch (attr_type) {
2534 while (mr->attr_next != attr_none) {
2535 if (rm_attr_get(priv_data, mr->attr_next, attr))
2540 mr->attr_next = attr_street_item;
2541 if (seg && seg->data->flags && AF_SPEED_LIMIT) {
2542 attr->u.num=RSD_MAXSPEED(seg->data);
2548 case attr_street_item:
2549 mr->attr_next=attr_direction;
2550 if (seg && seg->data->item.map)
2551 attr->u.item=&seg->data->item;
2555 case attr_direction:
2556 mr->attr_next=attr_route;
2558 attr->u.num=seg->direction;
2563 mr->attr_next=attr_length;
2564 attr->u.route = mr->mpriv->route;
2567 mr->attr_next=attr_time;
2569 attr->u.num=seg->data->len;
2574 mr->attr_next=attr_none;
2576 attr->u.num=route_time_seg(route->vehicleprofile, seg->data, NULL);
2581 mr->attr_next=attr_none;
2584 mr->attr_next=attr_none;
2585 attr->type=attr_none;
2592 rm_coord_get(void *priv_data, struct coord *c, int count)
2594 struct map_rect_priv *mr = priv_data;
2595 struct route_path_segment *seg = mr->seg;
2597 struct route *r = mr->mpriv->route;
2598 enum projection pro = route_projection(r);
2600 if (pro == projection_none)
2602 if (mr->item.type == type_route_start || mr->item.type == type_route_start_reverse || mr->item.type == type_route_end) {
2603 if (! count || mr->last_coord)
2606 if (mr->item.type == type_route_start || mr->item.type == type_route_start_reverse)
2614 for (i=0; i < count; i++) {
2615 if (mr->last_coord >= seg->ncoords)
2617 if (i >= seg->ncoords)
2619 if (pro != projection_mg)
2620 transform_from_to(&seg->c[mr->last_coord++], pro,
2621 &c[i],projection_mg);
2623 c[i] = seg->c[mr->last_coord++];
2626 dbg(1,"return %d\n",rc);
2630 static struct item_methods methods_route_item = {
2638 rp_attr_rewind(void *priv_data)
2640 struct map_rect_priv *mr = priv_data;
2641 mr->attr_next = attr_label;
2645 rp_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
2647 struct map_rect_priv *mr = priv_data;
2648 struct route_graph_point *p = mr->point;
2649 struct route_graph_segment *seg = mr->rseg;
2650 struct route *route=mr->mpriv->route;
2652 attr->type=attr_type;
2653 switch (attr_type) {
2654 case attr_any: // works only with rg_points for now
2655 while (mr->attr_next != attr_none) {
2656 dbg(0,"querying %s\n", attr_to_name(mr->attr_next));
2657 if (rp_attr_get(priv_data, mr->attr_next, attr))
2662 mr->attr_next = attr_label;
2663 if (mr->item.type != type_rg_segment)
2665 if (seg && (seg->data.flags & AF_SPEED_LIMIT)) {
2666 attr->type = attr_maxspeed;
2667 attr->u.num=RSD_MAXSPEED(&seg->data);
2673 mr->attr_next=attr_street_item;
2674 if (mr->item.type != type_rg_point)
2676 attr->type = attr_label;
2679 if (p->value != INT_MAX)
2680 mr->str=g_strdup_printf("%d", p->value);
2682 mr->str=g_strdup("-");
2683 attr->u.str = mr->str;
2685 case attr_street_item:
2686 mr->attr_next=attr_flags;
2687 if (mr->item.type != type_rg_segment)
2689 if (seg && seg->data.item.map)
2690 attr->u.item=&seg->data.item;
2695 mr->attr_next = attr_direction;
2696 if (mr->item.type != type_rg_segment)
2699 attr->u.num = seg->data.flags;
2704 case attr_direction:
2705 mr->attr_next = attr_debug;
2706 // This only works if the map has been opened at a single point, and in that case indicates if the
2707 // segment returned last is connected to this point via its start (1) or its end (-1)
2708 if (!mr->coord_sel || (mr->item.type != type_rg_segment))
2710 if (seg->start == mr->point) {
2712 } else if (seg->end == mr->point) {
2719 mr->attr_next=attr_none;
2722 switch (mr->item.type) {
2725 struct route_graph_segment *tmp;
2731 tmp=tmp->start_next;
2738 mr->str=g_strdup_printf("%d %d %p (0x%x,0x%x)", start, end, p, p->c.x, p->c.y);
2739 attr->u.str = mr->str;
2742 case type_rg_segment:
2745 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);
2746 attr->u.str = mr->str;
2753 mr->attr_next=attr_none;
2754 attr->type=attr_none;
2760 * @brief Returns the coordinates of a route graph item
2762 * @param priv_data The route graph item's private data
2763 * @param c Pointer where to store the coordinates
2764 * @param count How many coordinates to get at a max?
2765 * @return The number of coordinates retrieved
2768 rp_coord_get(void *priv_data, struct coord *c, int count)
2770 struct map_rect_priv *mr = priv_data;
2771 struct route_graph_point *p = mr->point;
2772 struct route_graph_segment *seg = mr->rseg;
2774 struct route *r = mr->mpriv->route;
2775 enum projection pro = route_projection(r);
2777 if (pro == projection_none)
2779 for (i=0; i < count; i++) {
2780 if (mr->item.type == type_rg_point) {
2781 if (mr->last_coord >= 1)
2783 if (pro != projection_mg)
2784 transform_from_to(&p->c, pro,
2785 &c[i],projection_mg);
2789 if (mr->last_coord >= 2)
2792 if (seg->end->seg == seg)
2797 if (pro != projection_mg)
2798 transform_from_to(&seg->end->c, pro,
2799 &c[i],projection_mg);
2803 if (pro != projection_mg)
2804 transform_from_to(&seg->start->c, pro,
2805 &c[i],projection_mg);
2807 c[i] = seg->start->c;
2816 static struct item_methods methods_point_item = {
2824 rp_destroy(struct map_priv *priv)
2830 rm_destroy(struct map_priv *priv)
2835 static struct map_rect_priv *
2836 rm_rect_new(struct map_priv *priv, struct map_selection *sel)
2838 struct map_rect_priv * mr;
2840 if (! route_get_pos(priv->route))
2842 if (! route_get_dst(priv->route))
2845 if (! priv->route->path2)
2848 mr=g_new0(struct map_rect_priv, 1);
2850 mr->item.priv_data = mr;
2851 mr->item.type = type_none;
2852 mr->item.meth = &methods_route_item;
2853 if (priv->route->path2) {
2854 mr->path=priv->route->path2;
2855 mr->seg_next=mr->path->path;
2863 * @brief Opens a new map rectangle on the route graph's map
2865 * This function opens a new map rectangle on the route graph's map.
2866 * The "sel" parameter enables you to only search for a single route graph
2867 * point on this map (or exactly: open a map rectangle that only contains
2868 * this one point). To do this, pass here a single map selection, whose
2869 * c_rect has both coordinates set to the same point. Otherwise this parameter
2872 * @param priv The route graph map's private data
2873 * @param sel Here it's possible to specify a point for which to search. Please read the function's description.
2874 * @return A new map rect's private data
2876 static struct map_rect_priv *
2877 rp_rect_new(struct map_priv *priv, struct map_selection *sel)
2879 struct map_rect_priv * mr;
2882 if (! priv->route->graph)
2884 mr=g_new0(struct map_rect_priv, 1);
2886 mr->item.priv_data = mr;
2887 mr->item.type = type_rg_point;
2888 mr->item.meth = &methods_point_item;
2890 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)) {
2891 mr->coord_sel = g_malloc(sizeof(struct coord));
2892 *(mr->coord_sel) = sel->u.c_rect.lu;
2899 rm_rect_destroy(struct map_rect_priv *mr)
2903 if (mr->coord_sel) {
2904 g_free(mr->coord_sel);
2908 if (mr->path->update_required && !mr->path->in_use)
2909 route_path_update_done(mr->mpriv->route, mr->path->update_required-1);
2915 static struct item *
2916 rp_get_item(struct map_rect_priv *mr)
2918 struct route *r = mr->mpriv->route;
2919 struct route_graph_point *p = mr->point;
2920 struct route_graph_segment *seg = mr->rseg;
2922 if (mr->item.type == type_rg_point) {
2923 if (mr->coord_sel) {
2924 // We are supposed to return only the point at one specified coordinate...
2926 p = route_graph_get_point_last(r->graph, mr->coord_sel);
2928 mr->point = NULL; // This indicates that no point has been found
2930 mr->it = rp_iterator_new(p);
2938 p = r->graph->hash[0];
2943 if (mr->hash_bucket >= HASH_SIZE)
2945 p = r->graph->hash[mr->hash_bucket];
2951 rm_coord_rewind(mr);
2955 mr->item.type = type_rg_segment;
2958 if (mr->coord_sel) {
2959 if (!mr->point) { // This means that no point has been found
2962 seg = rp_iterator_next(&(mr->it));
2965 seg=r->graph->route_segments;
2973 rm_coord_rewind(mr);
2981 static struct item *
2982 rp_get_item_byid(struct map_rect_priv *mr, int id_hi, int id_lo)
2984 struct item *ret=NULL;
2986 ret=rp_get_item(mr);
2991 static struct item *
2992 rm_get_item(struct map_rect_priv *mr)
2994 struct route *route=mr->mpriv->route;
2995 dbg(1,"enter\n", mr->pos);
2997 switch (mr->item.type) {
2999 if (route->pos && route->pos->street_direction && route->pos->street_direction != route->pos->dir)
3000 mr->item.type=type_route_start_reverse;
3002 mr->item.type=type_route_start;
3006 mr->item.type=type_street_route;
3007 mr->seg=mr->seg_next;
3009 mr->seg_next=mr->seg->next;
3012 mr->item.type=type_route_end;
3013 if (mr->mpriv->route->dst)
3015 case type_route_end:
3024 static struct item *
3025 rm_get_item_byid(struct map_rect_priv *mr, int id_hi, int id_lo)
3027 struct item *ret=NULL;
3029 ret=rm_get_item(mr);
3033 static struct map_methods route_meth = {
3046 static struct map_methods route_graph_meth = {
3059 static struct map_priv *
3060 route_map_new_helper(struct map_methods *meth, struct attr **attrs, int graph)
3062 struct map_priv *ret;
3063 struct attr *route_attr;
3065 route_attr=attr_search(attrs, NULL, attr_route);
3068 ret=g_new0(struct map_priv, 1);
3070 *meth=route_graph_meth;
3073 ret->route=route_attr->u.route;
3078 static struct map_priv *
3079 route_map_new(struct map_methods *meth, struct attr **attrs)
3081 return route_map_new_helper(meth, attrs, 0);
3084 static struct map_priv *
3085 route_graph_map_new(struct map_methods *meth, struct attr **attrs)
3087 return route_map_new_helper(meth, attrs, 1);
3091 route_get_map_helper(struct route *this_, struct map **map, char *type, char *description)
3094 *map=map_new(NULL, (struct attr*[]){
3095 &(struct attr){attr_type,{type}},
3096 &(struct attr){attr_route,.u.route=this_},
3097 &(struct attr){attr_data,{""}},
3098 &(struct attr){attr_description,{description}},
3105 * @brief Returns a new map containing the route path
3107 * This function returns a new map containing the route path.
3109 * @important Do not map_destroy() this!
3111 * @param this_ The route to get the map of
3112 * @return A new map containing the route path
3115 route_get_map(struct route *this_)
3117 return route_get_map_helper(this_, &this_->map, "route","Route");
3122 * @brief Returns a new map containing the route graph
3124 * This function returns a new map containing the route graph.
3126 * @important Do not map_destroy() this!
3128 * @param this_ The route to get the map of
3129 * @return A new map containing the route graph
3132 route_get_graph_map(struct route *this_)
3134 return route_get_map_helper(this_, &this_->graph_map, "route_graph","Route Graph");
3138 route_set_projection(struct route *this_, enum projection pro)
3143 route_set_attr(struct route *this_, struct attr *attr)
3146 switch (attr->type) {
3147 case attr_route_status:
3148 attr_updated = (this_->route_status != attr->u.num);
3149 this_->route_status = attr->u.num;
3155 callback_list_call_attr_2(this_->cbl2, attr->type, this_, attr);
3160 route_add_attr(struct route *this_, struct attr *attr)
3162 switch (attr->type) {
3165 callback_list_add(this_->cbl2, attr->u.callback);
3173 route_remove_attr(struct route *this_, struct attr *attr)
3175 switch (attr->type) {
3177 callback_list_remove(this_->cbl2, attr->u.callback);
3185 route_get_attr(struct route *this_, enum attr_type type, struct attr *attr, struct attr_iter *iter)
3190 attr->u.map=route_get_map(this_);
3191 ret=(attr->u.map != NULL);
3193 case attr_route_status:
3194 attr->u.num=this_->route_status;
3206 plugin_register_map_type("route", route_map_new);
3207 plugin_register_map_type("route_graph", route_graph_map_new);