char *name2;
struct item item;
int direction;
+ int straight;
int angle_start;
int angle_end;
struct coord c;
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;
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;
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;
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 {
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);
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)
{
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)
{
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)
{
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)
{
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);
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"));
{
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;
<plugin path="$NAVIT_LIBDIR/*/${NAVIT_LIBPREFIX}lib*.so"/>
<plugin path="$NAVIT_LIBDIR/*/${NAVIT_LIBPREFIX}libgraphics_null.so" active="no" />
</plugins>
- <debug name="navit:do_draw" level="0" />
+ <debug name="navit" level="0" />
<!--
Center coordinates format:
<!-- Use one of gtk_drawing_area, qt_qpainter or sdl. For cegui, use opengl -->
<graphics type="gtk_drawing_area" />
- <vehicle name="Local GPS" enabled="yes" active="1" source="gpsd://localhost" gpsd_query="w+xj" color="#0000ff">
+ <vehicle name="Local GPS" enabled="no" active="1" source="gpsd://localhost" gpsd_query="w+xj" color="#0000ff">
<!--Navit can write a tracklog in several formats (gpx, nmea or textfile):
<log type="gpx" data="track_%Y%m%d-%i.gpx" flush_size="1000" flush_time="30" />
-->
<vehicle name="Meins" enabled="yes" source="gpsd://localhost" color="#0000ff" follow="1" refresh="1"/>
-->
- <vehicle name="Demo" enabled="no" source="demo://" color="#0000aa"/>
+ <vehicle name="Demo" enabled="no" active="1" follow="1" source="demo://" color="#0000aa"/>
<tracking>
</tracking>
<!--<speech type="cmdline" data="flite -t '%s'" />-->
<!-- If you have the reiseplaner maps installed, set enabled="yes" in the next line -->
- <mapset enabled="no">
- <map type="mg" enabled="yes" data="/opt/reiseplaner/travel/DE.map" />
- <map type="mg" enabled="yes" data="/opt/reiseplaner/travel/DE.map/smp1.smp" />
- <map type="mg" enabled="yes" data="/opt/reiseplaner/travel/DE.map/smp2.smp" />
- <map type="mg" enabled="yes" data="/opt/reiseplaner/travel/DE.map/smp3.smp" />
- <map type="mg" enabled="yes" data="/opt/reiseplaner/travel/DE.map/smp4.smp" />
- <map type="mg" enabled="yes" data="/opt/reiseplaner/travel/DE.map/smp5.smp" />
+ <mapset enabled="yes">
+ <map type="mg" enabled="yes" data="/opt/maps/DIRLAN_GER/DEM.map" />
+ <map type="mg" enabled="yes" data="/opt/maps/DIRLAN_GER/DEM.map/smp3.smp" />
</mapset>
<!-- If you dont want to use the sample map, either set enabled="no" in the next line or remove the xml file from the maps directory -->
- <mapset enabled="yes">
+ <mapset enabled="no">
<xi:include href="$NAVIT_SHAREDIR/maps/*.xml" />
</mapset>
* 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! */
};
/**
* @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;
}
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);
}
}
/**
+ * @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
{
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
#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);
}
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)