summaryrefslogtreecommitdiff
path: root/navit
diff options
context:
space:
mode:
authortinloaf <tinloaf@ffa7fe5e-494d-0410-b361-a75ebd5db220>2008-10-14 20:18:27 +0000
committertinloaf <tinloaf@ffa7fe5e-494d-0410-b361-a75ebd5db220>2008-10-14 20:18:27 +0000
commitfae40c6aa75f3807ce917f3f31074fc61fec7b8e (patch)
tree860b01bccce8890ffbc2766b764262898de00351 /navit
parent7ee2eaac0c570a94ceb43c7c1a69aefda4ae7ca6 (diff)
downloadnavit-svn-fae40c6aa75f3807ce917f3f31074fc61fec7b8e.tar.gz
Repairing the repository.
git-svn-id: http://svn.code.sf.net/p/navit/code/trunk/navit@1467 ffa7fe5e-494d-0410-b361-a75ebd5db220
Diffstat (limited to 'navit')
-rw-r--r--navit/navigation.c81
-rw-r--r--navit/route.c169
2 files changed, 234 insertions, 16 deletions
diff --git a/navit/navigation.c b/navit/navigation.c
index 093e7333..1d0e60cd 100644
--- a/navit/navigation.c
+++ b/navit/navigation.c
@@ -132,6 +132,7 @@ struct navigation_itm {
char *name2;
struct item item;
int direction;
+ int straight;
int angle_start;
int angle_end;
struct coord c;
@@ -249,7 +250,7 @@ navigation_destroy_itms_cmds(struct navigation *this_, struct navigation_itm *en
static void
navigation_itm_update(struct navigation_itm *itm, struct item *ritem)
{
- struct attr length, time;
+ struct attr length, time, straight;
if (! item_attr_get(ritem, attr_length, &length)) {
dbg(0,"no length\n");
return;
@@ -258,6 +259,13 @@ navigation_itm_update(struct navigation_itm *itm, struct item *ritem)
dbg(0,"no time\n");
return;
}
+
+ if (item_attr_get(ritem, attr_route_follow_straight, &straight)) {
+ itm->straight = straight.u.num;
+ } else {
+ itm->straight = 0;
+ }
+
dbg(1,"length=%d time=%d\n", length.u.num, time.u.num);
itm->length=length.u.num;
itm->time=time.u.num;
@@ -267,7 +275,7 @@ static struct navigation_itm *
navigation_itm_new(struct navigation *this_, struct item *ritem)
{
struct navigation_itm *ret=g_new0(struct navigation_itm, 1);
- int l,i=0;
+ int i=0;
struct item *sitem;
struct attr street_item,direction;
struct map_rect *mr;
@@ -294,10 +302,10 @@ navigation_itm_new(struct navigation *this_, struct item *ritem)
if (item_attr_get(sitem, attr_street_name_systematic, &attr))
ret->name2=map_convert_string(sitem->map,attr.u.str);
navigation_itm_update(ret, ritem);
- l=-1;
+
while (item_coord_get(ritem, &c[i], 1)) {
dbg(1, "coord %d 0x%x 0x%x\n", i, c[i].x ,c[i].y);
- l=i;
+
if (i < 4)
i++;
else {
@@ -305,11 +313,12 @@ navigation_itm_new(struct navigation *this_, struct item *ritem)
c[3]=c[4];
}
}
- dbg(1,"count=%d\n", l);
- if (l == 4)
- l=3;
+ dbg(1,"count=%d\n", i);
+ i--;
+
ret->angle_start=road_angle(&c[0], &c[1], 0);
- ret->angle_end=road_angle(&c[l-1], &c[l], 0);
+ ret->angle_end=road_angle(&c[i-1], &c[i], 0);
+
ret->c=c[0];
dbg(1,"i=%d start %d end %d '%s' '%s'\n", i, ret->angle_start, ret->angle_end, ret->name1, ret->name2);
map_rect_destroy(mr);
@@ -325,6 +334,17 @@ navigation_itm_new(struct navigation *this_, struct item *ritem)
return ret;
}
+/**
+ * @brief Calculates distance and time to the destination
+ *
+ * This function calculates the distance and the time to the destination of a
+ * navigation. If incr is set, this is only calculated for the first navigation
+ * item, which is a lot faster than re-calculation the whole destination, but works
+ * only if the rest of the navigation already has been calculated.
+ *
+ * @param this_ The navigation whose destination / time should be calculated
+ * @param incr Set this to true to only calculate the first item. See description.
+ */
static void
calculate_dest_distance(struct navigation *this_, int incr)
{
@@ -357,6 +377,17 @@ calculate_dest_distance(struct navigation *this_, int incr)
dbg(1,"len %d time %d\n", len, time);
}
+/**
+ * @brief Checks if two navigation items are on the same street
+ *
+ * This function checks if two navigation items are on the same street. It returns
+ * true if either their name or their "systematic name" (e.g. "A6" or "B256") are the
+ * same.
+ *
+ * @param old The first item to be checked
+ * @param new The second item to be checked
+ * @return True if both old and new are on the same street
+ */
static int
is_same_street2(struct navigation_itm *old, struct navigation_itm *new)
{
@@ -372,6 +403,18 @@ is_same_street2(struct navigation_itm *old, struct navigation_itm *new)
return 0;
}
+/**
+ * @brief Checks if two navigation items are on the same street
+ *
+ * This function checks if two navigation items are on the same street. It returns
+ * true if the first part of their "systematic name" is equal. If the "systematic name" is
+ * for example "A352/E3" (a german highway which at the same time is part of the international
+ * E-road network), it would only search for "A352" in the second item's systematic name.
+ *
+ * @param old The first item to be checked
+ * @param new The second item to be checked
+ * @return True if the "systematic name" of both items matches. See description.
+ */
static int
is_same_street_systematic(struct navigation_itm *old, struct navigation_itm *new)
{
@@ -385,6 +428,17 @@ is_same_street_systematic(struct navigation_itm *old, struct navigation_itm *new
return 1;
}
+/**
+ * @brief Checks if navit has to create a maneuver to drive from old to new
+ *
+ * This function checks if it has to create a "maneuver" - i.e. guide the user - to drive
+ * from "old" to "new".
+ *
+ * @param old The old navigation item, where we're coming from
+ * @param new The new navigation item, where we're going to
+ * @param delta The angle the user has to steer to navigate from old to new
+ * @return True if navit should guide the user, false otherwise
+ */
static int
maneuver_required2(struct navigation_itm *old, struct navigation_itm *new, int *delta)
{
@@ -416,7 +470,11 @@ maneuver_required2(struct navigation_itm *old, struct navigation_itm *new, int *
return 1;
}
if (*delta < 20 && *delta >-20) {
- dbg(1, "maneuver_required: delta(%d) < 20: no\n", *delta);
+ if (! new->straight) { /* We're not entering this item straight, so have a maneuver */
+ return 1;
+ }
+
+ dbg(1, "maneuver_required: delta(%d) < 20: no\n", *delta);
return 0;
}
dbg(1, "maneuver_required: delta=%d: yes\n", *delta);
@@ -493,7 +551,7 @@ navigation_item_destination(struct navigation_itm *itm, struct navigation_itm *n
if(next->item.type == type_ramp)
return NULL;
if(itm->item.type == type_highway_city || itm->item.type == type_highway_land )
- return g_strdup_printf("%s%s",prefix,_("exit"));
+ return g_strdup_printf("%s%s",prefix,_("exit")); /* %FIXME Can this even be reached? */
else
return g_strdup_printf("%s%s",prefix,_("ramp"));
@@ -698,7 +756,8 @@ navigation_update(struct navigation *this_, struct route *route)
{
struct map *map;
struct map_rect *mr;
- struct item *ritem,*sitem;
+ struct item *ritem; /* Holds an item from the route map */
+ struct item *sitem; /* Holds the corresponding item from the actual map */
struct attr street_item,street_direction;
struct navigation_itm *itm;
int incr=0;
diff --git a/navit/route.c b/navit/route.c
index dc8982d5..ff2ada9c 100644
--- a/navit/route.c
+++ b/navit/route.c
@@ -129,7 +129,9 @@ struct route_path_segment {
* coordinate of the segment is the first coordinate of the item", <=0
* means reverse. */
unsigned ncoords; /**< How many coordinates does this segment have? */
+ struct attr **attrs; /**< Attributes of this route path segment */
struct coord c[0]; /**< Pointer to the ncoords coordinates of this segment */
+ /* WARNING: There will be coordinates following here, so do not create new fields after c! */
};
/**
@@ -904,20 +906,23 @@ route_path_add_item(struct route_path *this, struct item *item, int len, struct
* @param len Length of the item to be added
* @param offset Offset of rgs within the item it represents
* @param dir Order in which to add the coordinates. See route_path_add_item()
+ * @param straight Indicates if this segment is being entered "straight". See route_check_straight().
*/
static void
route_path_add_item_from_graph(struct route_path *this, struct route_path *oldpath,
- struct route_graph_segment *rgs, int len, int offset, int dir)
+ struct route_graph_segment *rgs, int len, int offset, int dir, int straight)
{
struct route_path_segment *segment;
int i,ccnt = 0;
struct coord ca[2048];
+ struct attr straight_attr;
if (oldpath) {
ccnt = (int)item_hash_lookup(oldpath->path_hash, &rgs->item);
if (ccnt) {
segment = route_extract_segment_from_path(oldpath,
&rgs->item, offset);
+
if (segment)
goto linkold;
}
@@ -944,6 +949,12 @@ linkold:
segment->length=len;
segment->next=NULL;
item_hash_insert(this->path_hash, &rgs->item, (void *)ccnt);
+
+ straight_attr.type = attr_route_follow_straight;
+ straight_attr.u.num = straight;
+
+ segment->attrs = attr_generic_set_attr(segment->attrs, &straight_attr);
+
route_path_add_segment(this, segment);
}
@@ -1274,6 +1285,137 @@ route_path_new_trivial(struct route_graph *this, struct route_info *pos, struct
}
/**
+ * @brief Calculates of two coordinates' connection
+ *
+ * This function calculates the angle between coordinates, with north = 0
+ * and east = 90.
+ *
+ * %FIXME This is a duplicate of road_angle() in navigation.c - combine them?
+ *
+ * @param c1 Coordinate 1
+ * @param c2 Coordinate 2
+ * @param dir Set to true if c1 is the prior, and c2 the later coordinate.
+ * @return The angle of the coordinate's connection
+ */
+static int
+route_road_angle(struct coord *c1, struct coord *c2, int dir)
+{
+ int ret=transform_get_angle_delta(c1, c2, dir);
+ dbg(1, "road_angle(0x%x,0x%x - 0x%x,0x%x)=%d\n", c1->x, c1->y, c2->x, c2->y, ret);
+ return ret;
+}
+
+/**
+ * @brief Checks if entering one segment from another is a "straight" road
+ *
+ * This checks if one can enter seg_to from seg_from by driving "straight" - i.e.
+ * if seg_to is the segment you can drive to from seg_from by steering less than
+ * all to all other segments.
+ *
+ * This function returns true on failure, so we don't create maneuvers on every error.
+ *
+ * @param seg_from Segment we are driving from
+ * @param seg_to Segment we are driving to
+ * @param dir Set to true to indicate that seg_from is left throught its "start" instead through its "end"
+ * @return True if driving from seg_from to seg_to is "straight", false otherwise
+ */
+static int
+route_check_straight(struct route_graph_segment *seg_from, struct route_graph_segment *seg_to, int dir)
+{
+ struct route_graph_segment *curr;
+ struct route_graph_point *conn;
+ int from_angle, to_angle, curr_angle, angle_diff;
+ int ccnt;
+ struct coord ca[2048];
+
+ if (!dir) {
+ if ((seg_from->end != seg_to->start) && (seg_from->end != seg_to->end)) {
+ // Not connected!
+ return 0;
+ }
+
+ ccnt = get_item_seg_coords(&seg_from->item, ca, 2047, &seg_from->start->c, &seg_from->end->c);
+ from_angle = route_road_angle(&ca[ccnt-2], &ca[ccnt-1],1);
+
+ conn = seg_from->end;
+ } else {
+ if ((seg_from->start != seg_to->start) && (seg_from->start != seg_to->end)) {
+ // Not connected!
+ return 0;
+ }
+
+ ccnt = get_item_seg_coords(&seg_from->item, ca, 2, &seg_from->start->c, &seg_from->end->c);
+ from_angle = route_road_angle(&ca[1], &ca[0],1);
+
+ conn = seg_from->start;
+ }
+
+ if (seg_to->end == conn) {
+ ccnt = get_item_seg_coords(&seg_to->item, ca, 2047, &seg_to->start->c, &seg_to->end->c);
+ to_angle = route_road_angle(&ca[ccnt-1], &ca[ccnt-2],1);
+ } else {
+ ccnt = get_item_seg_coords(&seg_to->item, ca, 2, &seg_to->start->c, &seg_to->end->c);
+ to_angle = route_road_angle(&ca[0], &ca[1],1);
+ }
+
+
+ angle_diff = from_angle - to_angle;
+ if (angle_diff < 0) {
+ angle_diff *= -1;
+ }
+
+
+ curr = conn->start;
+ while (curr != NULL) {
+ if (curr==seg_to) {
+ curr = curr->start_next;
+ continue;
+ }
+
+ ccnt = get_item_seg_coords(&curr->item, ca, 2, &curr->start->c, &curr->end->c);
+ curr_angle = route_road_angle(&ca[0], &ca[1], 1);
+
+ curr_angle = from_angle - curr_angle;
+
+ if (curr_angle < 0) {
+ curr_angle *= -1;
+ }
+
+
+ if (curr_angle <= angle_diff) {
+ return 0;
+ }
+
+ curr = curr->start_next;
+ }
+
+ curr = conn->end;
+ while (curr != NULL) {
+ if (curr==seg_to) {
+ curr = curr->end_next;
+ continue;
+ }
+
+ ccnt = get_item_seg_coords(&curr->item, ca, 2047, &curr->start->c, &curr->end->c);
+ curr_angle = route_road_angle(&ca[ccnt-1], &ca[ccnt-2], 1);
+
+ curr_angle = from_angle - curr_angle;
+
+ if (curr_angle < 0) {
+ curr_angle *= -1;
+ }
+
+ if (curr_angle <= angle_diff) {
+ return 0;
+ }
+
+ curr = curr->end_next;
+ }
+
+ return 1;
+}
+
+/**
* @brief Creates a new route path
*
* This creates a new non-trivial route. It therefore needs the routing information created by route_graph_flood, so
@@ -1291,6 +1433,8 @@ route_path_new(struct route_graph *this, struct route_path *oldpath, struct rout
{
struct route_graph_point *start1=NULL,*start2=NULL,*start;
struct route_graph_segment *s=NULL;
+ struct route_graph_segment *lastseg = NULL;
+ int is_straight;
int len=0,segs=0;
int seg_len;
#if 0
@@ -1350,13 +1494,22 @@ route_path_new(struct route_graph *this, struct route_path *oldpath, struct rout
#endif
seg_len=s->len;
len+=seg_len;
- if (s->start == start) {
- route_path_add_item_from_graph(ret, oldpath, s, seg_len, s->offset, 1);
+
+ if (lastseg) {
+ is_straight = route_check_straight(lastseg,s,(s->end == start));
+ } else {
+ is_straight = 0;
+ }
+
+ if (s->start == start) {
+ route_path_add_item_from_graph(ret, oldpath, s, seg_len, s->offset, 1, is_straight);
start=s->end;
} else {
- route_path_add_item_from_graph(ret, oldpath, s, seg_len, s->offset, -1);
+ route_path_add_item_from_graph(ret, oldpath, s, seg_len, s->offset, -1, is_straight);
start=s->start;
}
+
+ lastseg = s;
}
sd=dst->street;
dbg(1,"start->value=%d 0x%x,0x%x\n", start->value, start->c.x, start->c.y);
@@ -1685,12 +1838,18 @@ rm_attr_get(void *priv_data, enum attr_type attr_type, struct attr *attr)
}
return 0;
case attr_street_item:
- mr->attr_next=attr_direction;
+ mr->attr_next=attr_route_follow_straight;
if (seg && seg->item.map)
attr->u.item=&seg->item;
else
return 0;
return 1;
+ case attr_route_follow_straight:
+ mr->attr_next=attr_direction;
+ if (seg) {
+ return attr_generic_get_attr(seg->attrs,NULL,attr_route_follow_straight,attr,NULL);
+ }
+ return 0;
case attr_direction:
mr->attr_next=attr_length;
if (seg)