1903 |
} |
} |
1904 |
} |
} |
1905 |
|
|
1906 |
void osm_way_revert(way_t *way) { |
void osm_way_reverse(way_t *way) { |
1907 |
node_chain_t *new = NULL; |
node_chain_t *new = NULL; |
1908 |
|
|
1909 |
/* walk old chain first to last */ |
/* walk old chain first to last */ |
1921 |
way->node_chain = new; |
way->node_chain = new; |
1922 |
} |
} |
1923 |
|
|
1924 |
|
static const char *DS_ONEWAY_FWD = "yes"; |
1925 |
|
static const char *DS_ONEWAY_REV = "-1"; |
1926 |
|
static const char *DS_LEFT_SUFFIX = ":left"; |
1927 |
|
static const char *DS_RIGHT_SUFFIX = ":right"; |
1928 |
|
|
1929 |
|
/* Reverse direction-sensitive tags like "oneway". Marks the way as dirty if |
1930 |
|
* anything is changed, and returns the number of flipped tags. */ |
1931 |
|
|
1932 |
|
guint |
1933 |
|
osm_way_reverse_direction_sensitive_tags (way_t *way) { |
1934 |
|
tag_t *tag = way->tag; |
1935 |
|
guint n_tags_altered = 0; |
1936 |
|
while (tag != NULL) { |
1937 |
|
char *lc_key = g_ascii_strdown(tag->key, -1); |
1938 |
|
char *lc_value = g_ascii_strdown(tag->value, -1); |
1939 |
|
|
1940 |
|
if (strcmp(lc_key, "oneway") == 0) { |
1941 |
|
// oneway={yes/true/1/-1} is unusual. |
1942 |
|
// Favour "yes" and "-1". |
1943 |
|
if ((strcmp(lc_value, DS_ONEWAY_FWD) == 0) || |
1944 |
|
(strcmp(lc_value, "true") == 0) || |
1945 |
|
(strcmp(lc_value, "1") == 0)) { |
1946 |
|
g_free(tag->value); |
1947 |
|
tag->value = g_strdup(DS_ONEWAY_REV); |
1948 |
|
n_tags_altered++; |
1949 |
|
} |
1950 |
|
else if (strcmp(lc_value, DS_ONEWAY_REV) == 0) { |
1951 |
|
g_free(tag->value); |
1952 |
|
tag->value = g_strdup(DS_ONEWAY_FWD); |
1953 |
|
n_tags_altered++; |
1954 |
|
} |
1955 |
|
else { |
1956 |
|
printf("warning: unknown tag: %s=%s\n", tag->key, tag->value); |
1957 |
|
} |
1958 |
|
} |
1959 |
|
|
1960 |
|
// :left and :right suffixes |
1961 |
|
else if (g_str_has_suffix(lc_key, DS_LEFT_SUFFIX)) { |
1962 |
|
char *key_old = tag->key; |
1963 |
|
char *lastcolon = rindex(key_old, ':'); |
1964 |
|
g_assert(lastcolon != NULL); |
1965 |
|
*lastcolon = '\000'; |
1966 |
|
tag->key = g_strconcat(key_old, DS_RIGHT_SUFFIX, NULL); |
1967 |
|
*lastcolon = ':'; |
1968 |
|
g_free(key_old); |
1969 |
|
n_tags_altered++; |
1970 |
|
} |
1971 |
|
else if (g_str_has_suffix(lc_key, DS_RIGHT_SUFFIX)) { |
1972 |
|
char *key_old = tag->key; |
1973 |
|
char *lastcolon = rindex(key_old, ':'); |
1974 |
|
g_assert(lastcolon != NULL); |
1975 |
|
*lastcolon = '\000'; |
1976 |
|
tag->key = g_strconcat(key_old, DS_LEFT_SUFFIX, NULL); |
1977 |
|
*lastcolon = ':'; |
1978 |
|
g_free(key_old); |
1979 |
|
n_tags_altered++; |
1980 |
|
} |
1981 |
|
|
1982 |
|
g_free(lc_key); |
1983 |
|
g_free(lc_value); |
1984 |
|
tag = tag->next; |
1985 |
|
} |
1986 |
|
if (n_tags_altered > 0) { |
1987 |
|
way->flags |= OSM_FLAG_DIRTY; |
1988 |
|
} |
1989 |
|
return n_tags_altered; |
1990 |
|
} |
1991 |
|
|
1992 |
|
/* Reverse a way's role within relations where the role is direction-sensitive. |
1993 |
|
* Returns the number of roles flipped, and marks any relations changed as |
1994 |
|
* dirty. */ |
1995 |
|
|
1996 |
|
static const char *DS_ROUTE_FORWARD = "forward"; |
1997 |
|
static const char *DS_ROUTE_REVERSE = "reverse"; |
1998 |
|
|
1999 |
|
guint |
2000 |
|
osm_way_reverse_direction_sensitive_roles(osm_t *osm, way_t *way) { |
2001 |
|
relation_chain_t *rel_chain0, *rel_chain; |
2002 |
|
rel_chain0 = rel_chain = osm_way_to_relation(osm, way); |
2003 |
|
guint n_roles_flipped = 0; |
2004 |
|
|
2005 |
|
for (; rel_chain != NULL; rel_chain = rel_chain->next) { |
2006 |
|
char *type = osm_tag_get_by_key(rel_chain->relation->tag, "type"); |
2007 |
|
|
2008 |
|
// Route relations; http://wiki.openstreetmap.org/wiki/Relation:route |
2009 |
|
if (strcasecmp(type, "route") == 0) { |
2010 |
|
|
2011 |
|
// First find the member corresponding to our way: |
2012 |
|
member_t *member = rel_chain->relation->member; |
2013 |
|
for (; member != NULL; member = member->next) { |
2014 |
|
if (member->type == WAY) { |
2015 |
|
if (member->way == way) |
2016 |
|
break; |
2017 |
|
} |
2018 |
|
if (member->type == WAY_ID) { |
2019 |
|
if (member->id == way->id) |
2020 |
|
break; |
2021 |
|
} |
2022 |
|
} |
2023 |
|
g_assert(member); // osm_way_to_relation() broken? |
2024 |
|
|
2025 |
|
// Then flip its role if it's one of the direction-sensitive ones |
2026 |
|
if (strcasecmp(member->role, DS_ROUTE_FORWARD) == 0) { |
2027 |
|
g_free(member->role); |
2028 |
|
member->role = g_strdup(DS_ROUTE_REVERSE); |
2029 |
|
rel_chain->relation->flags |= OSM_FLAG_DIRTY; |
2030 |
|
++n_roles_flipped; |
2031 |
|
} |
2032 |
|
else if (strcasecmp(member->role, DS_ROUTE_REVERSE) == 0) { |
2033 |
|
g_free(member->role); |
2034 |
|
member->role = g_strdup(DS_ROUTE_FORWARD); |
2035 |
|
rel_chain->relation->flags |= OSM_FLAG_DIRTY; |
2036 |
|
++n_roles_flipped; |
2037 |
|
} |
2038 |
|
|
2039 |
|
// TODO: what about numbered stops? Guess we ignore them; there's no |
2040 |
|
// consensus about whether they should be placed on the way or to one side |
2041 |
|
// of it. |
2042 |
|
|
2043 |
|
}//if-route |
2044 |
|
|
2045 |
|
|
2046 |
|
} |
2047 |
|
if (rel_chain0) { |
2048 |
|
g_free(rel_chain0); |
2049 |
|
} |
2050 |
|
return n_roles_flipped; |
2051 |
|
} |
2052 |
|
|
2053 |
node_t *osm_way_get_first_node(way_t *way) { |
node_t *osm_way_get_first_node(way_t *way) { |
2054 |
node_chain_t *chain = way->node_chain; |
node_chain_t *chain = way->node_chain; |
2055 |
if(!chain) return NULL; |
if(!chain) return NULL; |