1065 |
|
|
1066 |
#include <sys/time.h> |
#include <sys/time.h> |
1067 |
|
|
1068 |
osm_t *osm_parse(char *filename) { |
osm_t *osm_parse(char *path, char *filename) { |
1069 |
|
|
1070 |
struct timeval start; |
struct timeval start; |
1071 |
gettimeofday(&start, NULL); |
gettimeofday(&start, NULL); |
1073 |
LIBXML_TEST_VERSION; |
LIBXML_TEST_VERSION; |
1074 |
|
|
1075 |
// use stream parser |
// use stream parser |
1076 |
osm_t *osm = process_file(filename); |
osm_t *osm = NULL; |
1077 |
|
if(filename[0] == '/') |
1078 |
|
osm = process_file(filename); |
1079 |
|
else { |
1080 |
|
char *full = g_strjoin(NULL, path, filename, NULL); |
1081 |
|
osm = process_file(full); |
1082 |
|
g_free(full); |
1083 |
|
} |
1084 |
|
|
1085 |
xmlCleanupParser(); |
xmlCleanupParser(); |
1086 |
|
|
1087 |
struct timeval end; |
struct timeval end; |
1177 |
tag_t *tag = node->tag; |
tag_t *tag = node->tag; |
1178 |
|
|
1179 |
/* created_by tags don't count as real tags */ |
/* created_by tags don't count as real tags */ |
1180 |
if(tag && strcasecmp(tag->key, "created_by") == 0) |
if(tag && osm_is_creator_tag(tag)) |
1181 |
tag = tag->next; |
tag = tag->next; |
1182 |
|
|
1183 |
return tag != NULL; |
return tag != NULL; |
1223 |
|
|
1224 |
xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0"); |
xmlDocPtr doc = xmlNewDoc(BAD_CAST "1.0"); |
1225 |
xmlNodePtr root_node = xmlNewNode(NULL, BAD_CAST "osm"); |
xmlNodePtr root_node = xmlNewNode(NULL, BAD_CAST "osm"); |
|
#ifndef API06 |
|
|
xmlNewProp(root_node, BAD_CAST "version", BAD_CAST "0.5"); |
|
|
xmlNewProp(root_node, BAD_CAST "generator", BAD_CAST PACKAGE " v" VERSION); |
|
|
#endif |
|
1226 |
xmlDocSetRootElement(doc, root_node); |
xmlDocSetRootElement(doc, root_node); |
1227 |
|
|
1228 |
switch(type) { |
switch(type) { |
1236 |
snprintf(str, sizeof(str), "%u", (unsigned)node->id); |
snprintf(str, sizeof(str), "%u", (unsigned)node->id); |
1237 |
xmlNewProp(node_node, BAD_CAST "id", BAD_CAST str); |
xmlNewProp(node_node, BAD_CAST "id", BAD_CAST str); |
1238 |
} |
} |
|
#ifdef API06 |
|
1239 |
snprintf(str, sizeof(str), "%u", (unsigned)node->version); |
snprintf(str, sizeof(str), "%u", (unsigned)node->version); |
1240 |
xmlNewProp(node_node, BAD_CAST "version", BAD_CAST str); |
xmlNewProp(node_node, BAD_CAST "version", BAD_CAST str); |
1241 |
snprintf(str, sizeof(str), "%u", (unsigned)changeset); |
snprintf(str, sizeof(str), "%u", (unsigned)changeset); |
1242 |
xmlNewProp(node_node, BAD_CAST "changeset", BAD_CAST str); |
xmlNewProp(node_node, BAD_CAST "changeset", BAD_CAST str); |
|
#endif |
|
1243 |
g_ascii_formatd(str, sizeof(str), LL_FORMAT, node->pos.lat); |
g_ascii_formatd(str, sizeof(str), LL_FORMAT, node->pos.lat); |
1244 |
xmlNewProp(node_node, BAD_CAST "lat", BAD_CAST str); |
xmlNewProp(node_node, BAD_CAST "lat", BAD_CAST str); |
1245 |
g_ascii_formatd(str, sizeof(str), LL_FORMAT, node->pos.lon); |
g_ascii_formatd(str, sizeof(str), LL_FORMAT, node->pos.lon); |
1254 |
xmlNodePtr way_node = xmlNewChild(root_node, NULL, BAD_CAST "way", NULL); |
xmlNodePtr way_node = xmlNewChild(root_node, NULL, BAD_CAST "way", NULL); |
1255 |
snprintf(str, sizeof(str), "%u", (unsigned)way->id); |
snprintf(str, sizeof(str), "%u", (unsigned)way->id); |
1256 |
xmlNewProp(way_node, BAD_CAST "id", BAD_CAST str); |
xmlNewProp(way_node, BAD_CAST "id", BAD_CAST str); |
|
#ifdef API06 |
|
1257 |
snprintf(str, sizeof(str), "%u", (unsigned)way->version); |
snprintf(str, sizeof(str), "%u", (unsigned)way->version); |
1258 |
xmlNewProp(way_node, BAD_CAST "version", BAD_CAST str); |
xmlNewProp(way_node, BAD_CAST "version", BAD_CAST str); |
1259 |
snprintf(str, sizeof(str), "%u", (unsigned)changeset); |
snprintf(str, sizeof(str), "%u", (unsigned)changeset); |
1260 |
xmlNewProp(way_node, BAD_CAST "changeset", BAD_CAST str); |
xmlNewProp(way_node, BAD_CAST "changeset", BAD_CAST str); |
|
#endif |
|
1261 |
|
|
1262 |
node_chain_t *node_chain = way->node_chain; |
node_chain_t *node_chain = way->node_chain; |
1263 |
while(node_chain) { |
while(node_chain) { |
1279 |
BAD_CAST "relation", NULL); |
BAD_CAST "relation", NULL); |
1280 |
snprintf(str, sizeof(str), "%u", (unsigned)relation->id); |
snprintf(str, sizeof(str), "%u", (unsigned)relation->id); |
1281 |
xmlNewProp(rel_node, BAD_CAST "id", BAD_CAST str); |
xmlNewProp(rel_node, BAD_CAST "id", BAD_CAST str); |
|
#ifdef API06 |
|
1282 |
snprintf(str, sizeof(str), "%u", (unsigned)relation->version); |
snprintf(str, sizeof(str), "%u", (unsigned)relation->version); |
1283 |
xmlNewProp(rel_node, BAD_CAST "version", BAD_CAST str); |
xmlNewProp(rel_node, BAD_CAST "version", BAD_CAST str); |
1284 |
snprintf(str, sizeof(str), "%u", (unsigned)changeset); |
snprintf(str, sizeof(str), "%u", (unsigned)changeset); |
1285 |
xmlNewProp(rel_node, BAD_CAST "changeset", BAD_CAST str); |
xmlNewProp(rel_node, BAD_CAST "changeset", BAD_CAST str); |
|
#endif |
|
1286 |
|
|
1287 |
member_t *member = relation->member; |
member_t *member = relation->member; |
1288 |
while(member) { |
while(member) { |
1529 |
node->visible = TRUE; |
node->visible = TRUE; |
1530 |
node->time = time(NULL); |
node->time = time(NULL); |
1531 |
|
|
|
#ifndef API06 |
|
|
/* add created_by tag */ |
|
|
node->tag = g_new0(tag_t, 1); |
|
|
node->tag->key = g_strdup("created_by"); |
|
|
node->tag->value = g_strdup(PACKAGE " v" VERSION); |
|
|
#endif |
|
|
|
|
1532 |
/* convert screen position back to ll */ |
/* convert screen position back to ll */ |
1533 |
lpos2pos(osm->bounds, &node->lpos, &node->pos); |
lpos2pos(osm->bounds, &node->lpos, &node->pos); |
1534 |
|
|
1569 |
way->flags = OSM_FLAG_NEW; |
way->flags = OSM_FLAG_NEW; |
1570 |
way->time = time(NULL); |
way->time = time(NULL); |
1571 |
|
|
|
#ifndef API06 |
|
|
/* add created_by tag */ |
|
|
way->tag = g_new0(tag_t, 1); |
|
|
way->tag->key = g_strdup("created_by"); |
|
|
way->tag->value = g_strdup(PACKAGE " v" VERSION); |
|
|
#endif |
|
|
|
|
1572 |
return way; |
return way; |
1573 |
} |
} |
1574 |
|
|
1746 |
return rel_chain; |
return rel_chain; |
1747 |
} |
} |
1748 |
|
|
1749 |
|
/* return all relations a relation is in */ |
1750 |
|
relation_chain_t *osm_relation_to_relation(osm_t *osm, relation_t *rel) { |
1751 |
|
relation_chain_t *rel_chain = NULL, **cur_rel_chain = &rel_chain; |
1752 |
|
|
1753 |
|
relation_t *relation = osm->relation; |
1754 |
|
while(relation) { |
1755 |
|
gboolean is_member = FALSE; |
1756 |
|
|
1757 |
|
member_t *member = relation->member; |
1758 |
|
while(member) { |
1759 |
|
switch(member->object.type) { |
1760 |
|
case RELATION: { |
1761 |
|
/* relations can be check directly */ |
1762 |
|
if(member->object.relation == rel) |
1763 |
|
is_member = TRUE; |
1764 |
|
} break; |
1765 |
|
|
1766 |
|
default: |
1767 |
|
break; |
1768 |
|
} |
1769 |
|
member = member->next; |
1770 |
|
} |
1771 |
|
|
1772 |
|
/* way is a member of this relation, so move it to the member chain */ |
1773 |
|
if(is_member) { |
1774 |
|
*cur_rel_chain = g_new0(relation_chain_t, 1); |
1775 |
|
(*cur_rel_chain)->relation = relation; |
1776 |
|
cur_rel_chain = &((*cur_rel_chain)->next); |
1777 |
|
} |
1778 |
|
|
1779 |
|
relation = relation->next; |
1780 |
|
} |
1781 |
|
|
1782 |
|
return rel_chain; |
1783 |
|
} |
1784 |
|
|
1785 |
|
/* return all relations an object is in */ |
1786 |
|
relation_chain_t *osm_object_to_relation(osm_t *osm, object_t *object) { |
1787 |
|
relation_chain_t *rel_chain = NULL; |
1788 |
|
|
1789 |
|
switch(object->type) { |
1790 |
|
case NODE: |
1791 |
|
rel_chain = osm_node_to_relation(osm, object->node); |
1792 |
|
break; |
1793 |
|
|
1794 |
|
case WAY: |
1795 |
|
rel_chain = osm_way_to_relation(osm, object->way); |
1796 |
|
break; |
1797 |
|
|
1798 |
|
case RELATION: |
1799 |
|
rel_chain = osm_relation_to_relation(osm, object->relation); |
1800 |
|
break; |
1801 |
|
|
1802 |
|
default: |
1803 |
|
break; |
1804 |
|
} |
1805 |
|
|
1806 |
|
return rel_chain; |
1807 |
|
} |
1808 |
|
|
1809 |
|
void osm_relation_chain_free(relation_chain_t *rchain) { |
1810 |
|
while(rchain) { |
1811 |
|
relation_chain_t *next = rchain->next; |
1812 |
|
g_free(rchain); |
1813 |
|
rchain = next; |
1814 |
|
} |
1815 |
|
} |
1816 |
|
|
1817 |
/* return all ways a node is in */ |
/* return all ways a node is in */ |
1818 |
way_chain_t *osm_node_to_way(osm_t *osm, node_t *node) { |
way_chain_t *osm_node_to_way(osm_t *osm, node_t *node) { |
1819 |
way_chain_t *chain = NULL, **cur_chain = &chain; |
way_chain_t *chain = NULL, **cur_chain = &chain; |
1909 |
relation->flags = OSM_FLAG_NEW; |
relation->flags = OSM_FLAG_NEW; |
1910 |
relation->time = time(NULL); |
relation->time = time(NULL); |
1911 |
|
|
|
#ifndef API06 |
|
|
/* add created_by tag */ |
|
|
relation->tag = g_new0(tag_t, 1); |
|
|
relation->tag->key = g_strdup("created_by"); |
|
|
relation->tag->value = g_strdup(PACKAGE " v" VERSION); |
|
|
#endif |
|
|
|
|
1912 |
return relation; |
return relation; |
1913 |
} |
} |
1914 |
|
|
2214 |
} |
} |
2215 |
} |
} |
2216 |
|
|
2217 |
tag_t *osm_tags_copy(tag_t *src_tag, gboolean update_creator) { |
tag_t *osm_tags_copy(tag_t *src_tag) { |
2218 |
tag_t *new_tags = NULL; |
tag_t *new_tags = NULL; |
2219 |
tag_t **dst_tag = &new_tags; |
tag_t **dst_tag = &new_tags; |
2220 |
|
|
2221 |
while(src_tag) { |
while(src_tag) { |
2222 |
*dst_tag = g_new0(tag_t, 1); |
if(!osm_is_creator_tag(src_tag)) { |
2223 |
(*dst_tag)->key = g_strdup(src_tag->key); |
*dst_tag = g_new0(tag_t, 1); |
2224 |
if(update_creator && (strcasecmp(src_tag->key, "created_by") == 0)) |
(*dst_tag)->key = g_strdup(src_tag->key); |
|
(*dst_tag)->value = g_strdup(PACKAGE " v" VERSION); |
|
|
else |
|
2225 |
(*dst_tag)->value = g_strdup(src_tag->value); |
(*dst_tag)->value = g_strdup(src_tag->value); |
2226 |
|
dst_tag = &(*dst_tag)->next; |
2227 |
dst_tag = &(*dst_tag)->next; |
} |
2228 |
src_tag = src_tag->next; |
src_tag = src_tag->next; |
2229 |
} |
} |
2230 |
|
|
2231 |
return new_tags; |
return new_tags; |
2232 |
} |
} |
2233 |
|
|
2236 |
const struct { type_t type; char *name; } types[] = { |
const struct { type_t type; char *name; } types[] = { |
2237 |
{ ILLEGAL, "illegal" }, |
{ ILLEGAL, "illegal" }, |
2238 |
{ NODE, "node" }, |
{ NODE, "node" }, |
2239 |
{ WAY, "way" }, |
{ WAY, "way/area" }, |
2240 |
{ RELATION, "relation" }, |
{ RELATION, "relation" }, |
2241 |
{ NODE_ID, "node id" }, |
{ NODE_ID, "node id" }, |
2242 |
{ WAY_ID, "way id" }, |
{ WAY_ID, "way/area id" }, |
2243 |
{ RELATION_ID, "relation id" }, |
{ RELATION_ID, "relation id" }, |
2244 |
{ 0, NULL } |
{ 0, NULL } |
2245 |
}; |
}; |
2252 |
return NULL; |
return NULL; |
2253 |
} |
} |
2254 |
|
|
2255 |
|
char *osm_object_get_name(object_t *object) { |
2256 |
|
tag_t *tags = osm_object_get_tags(object); |
2257 |
|
|
2258 |
|
if(!tags) return NULL; |
2259 |
|
return osm_tag_get_by_key(tags, "name"); |
2260 |
|
} |
2261 |
|
|
2262 |
|
/* try to get an as "speaking" description of the object as possible */ |
2263 |
|
char *osm_object_get_speaking_name(object_t *object) { |
2264 |
|
char *ret = NULL; |
2265 |
|
tag_t *tags = osm_object_get_tags(object); |
2266 |
|
|
2267 |
|
/* worst case: we have no tags at all. return techincal info then */ |
2268 |
|
if(!tags) |
2269 |
|
return g_strdup_printf("unspecified %s", osm_object_type_string(object)); |
2270 |
|
|
2271 |
|
/* try to figure out _what_ this is */ |
2272 |
|
|
2273 |
|
char *name = osm_tag_get_by_key(tags, "name"); |
2274 |
|
if(!name) name = osm_tag_get_by_key(tags, "ref"); |
2275 |
|
if(!name) name = osm_tag_get_by_key(tags, "note"); |
2276 |
|
if(!name) name = osm_tag_get_by_key(tags, "fix" "me"); |
2277 |
|
if(!name) name = osm_tag_get_by_key(tags, "sport"); |
2278 |
|
|
2279 |
|
/* search for some kind of "type" */ |
2280 |
|
gboolean free_type = FALSE; |
2281 |
|
char *type = osm_tag_get_by_key(tags, "amenity"); |
2282 |
|
if(!type) type = osm_tag_get_by_key(tags, "place"); |
2283 |
|
if(!type) type = osm_tag_get_by_key(tags, "historic"); |
2284 |
|
if(!type) type = osm_tag_get_by_key(tags, "leisure"); |
2285 |
|
if(!type) type = osm_tag_get_by_key(tags, "tourism"); |
2286 |
|
if(!type) type = osm_tag_get_by_key(tags, "landuse"); |
2287 |
|
if(!type) type = osm_tag_get_by_key(tags, "waterway"); |
2288 |
|
if(!type) type = osm_tag_get_by_key(tags, "railway"); |
2289 |
|
if(!type) type = osm_tag_get_by_key(tags, "natural"); |
2290 |
|
if(!type && osm_tag_get_by_key(tags, "building")) type = "building"; |
2291 |
|
|
2292 |
|
/* highways are a little bit difficult */ |
2293 |
|
char *highway = osm_tag_get_by_key(tags, "highway"); |
2294 |
|
if(highway) { |
2295 |
|
if((!strcmp(highway, "primary")) || |
2296 |
|
(!strcmp(highway, "secondary")) || |
2297 |
|
(!strcmp(highway, "tertiary")) || |
2298 |
|
(!strcmp(highway, "unclassified")) || |
2299 |
|
(!strcmp(highway, "residential")) || |
2300 |
|
(!strcmp(highway, "service"))) { |
2301 |
|
type = g_strdup_printf("%s road", highway); |
2302 |
|
free_type = TRUE; |
2303 |
|
} |
2304 |
|
|
2305 |
|
else if(!strcmp(highway, "pedestrian")) { |
2306 |
|
type = g_strdup_printf("%s way/area", highway); |
2307 |
|
free_type = TRUE; |
2308 |
|
} |
2309 |
|
|
2310 |
|
else if(!strcmp(highway, "construction")) { |
2311 |
|
type = g_strdup_printf("road/street under %s", highway); |
2312 |
|
free_type = TRUE; |
2313 |
|
} |
2314 |
|
|
2315 |
|
else |
2316 |
|
type = highway; |
2317 |
|
} |
2318 |
|
|
2319 |
|
if(type && name) |
2320 |
|
ret = g_strdup_printf("%s: \"%s\"", type, name); |
2321 |
|
else if(type && !name) |
2322 |
|
ret = g_strdup(type); |
2323 |
|
else if(name && !type) |
2324 |
|
ret = g_strdup_printf("%s: \"%s\"", |
2325 |
|
osm_object_type_string(object), name); |
2326 |
|
else |
2327 |
|
ret = g_strdup_printf("unspecified %s", osm_object_type_string(object)); |
2328 |
|
|
2329 |
|
if(free_type) |
2330 |
|
g_free(type); |
2331 |
|
|
2332 |
|
/* remove underscores from string and replace them by spaces as this is */ |
2333 |
|
/* usually nicer */ |
2334 |
|
char *p = ret; |
2335 |
|
while(*p) { |
2336 |
|
if(*p == '_') |
2337 |
|
*p = ' '; |
2338 |
|
p++; |
2339 |
|
} |
2340 |
|
|
2341 |
|
return ret; |
2342 |
|
} |
2343 |
|
|
2344 |
char *osm_object_string(object_t *object) { |
char *osm_object_string(object_t *object) { |
2345 |
char *type_str = osm_object_type_string(object); |
char *type_str = osm_object_type_string(object); |
2346 |
|
|