diff options
author | Stefan Wildemann <gta04@metalstrolche.de> | 2019-07-27 11:05:40 +0200 |
---|---|---|
committer | Stefan Wildemann <gta04@metalstrolche.de> | 2019-07-28 12:33:49 +0200 |
commit | f99e5245364d2b7cf9eb1d6c9ad8a09b263f7498 (patch) | |
tree | 2a172137231cb94348ab91ba33bd6d80c75d9862 /navit/maptool | |
parent | 6bc6c0cca6c105450f7cc6f080c72d99f87c173f (diff) | |
download | navit-f99e5245364d2b7cf9eb1d6c9ad8a09b263f7498.tar.gz |
Process multipolygons to mapfile
Diffstat (limited to 'navit/maptool')
-rw-r--r-- | navit/maptool/maptool.c | 24 | ||||
-rw-r--r-- | navit/maptool/maptool.h | 171 | ||||
-rw-r--r-- | navit/maptool/osm.c | 174 |
3 files changed, 287 insertions, 82 deletions
diff --git a/navit/maptool/maptool.c b/navit/maptool/maptool.c index 422bc96bf..b785d14f4 100644 --- a/navit/maptool/maptool.c +++ b/navit/maptool/maptool.c @@ -555,6 +555,7 @@ static void osm_read_input_data(struct maptool_params *p, char *suffix) { p->osm.towns=tempfile(suffix,"towns",1); } if (p->process_ways && p->process_nodes) { + p->osm.multipolygons=tempfile(suffix,"multipolygons",1); p->osm.turn_restrictions=tempfile(suffix,"turn_restrictions",1); p->osm.line2poi=tempfile(suffix,"line2poi",1); p->osm.poly2poi=tempfile(suffix,"poly2poi",1); @@ -599,6 +600,8 @@ static void osm_read_input_data(struct maptool_params *p, char *suffix) { fclose(p->osm.nodes); if (p->osm.turn_restrictions) fclose(p->osm.turn_restrictions); + if (p->osm.multipolygons) + fclose(p->osm.multipolygons); if (p->osm.associated_streets) fclose(p->osm.associated_streets); if (p->osm.house_number_interpolations) @@ -723,6 +726,21 @@ static void osm_process_turn_restrictions(struct maptool_params *p, char *suffix tempfile_unlink(suffix,"turn_restrictions"); } +static void osm_process_multipolygons(struct maptool_params *p, char *suffix) { + FILE *ways_split, *ways_split_index, *relations, *coords; + p->osm.multipolygons=tempfile(suffix,"multipolygons",0); + if(!p->osm.multipolygons) + return; + relations=tempfile(suffix,"relations", 1); + coords=fopen("coords.tmp", "rb"); + ways_split=tempfile(suffix,"ways_split",0); + ways_split_index=tempfile(suffix,"ways_split_index",0); + process_multipolygons(p->osm.multipolygons,coords,ways_split,ways_split_index,relations); + fclose(coords); + fclose(relations); + fclose(p->osm.multipolygons); +} + static void maptool_dump(struct maptool_params *p, char *suffix) { char *files[10]; int i,files_count=0; @@ -822,6 +840,7 @@ static void maptool_assemble_map(struct maptool_params *p, char *suffix, char ** tempfile_unlink(suffix,"ways_split_ref"); tempfile_unlink(suffix,"coastline"); tempfile_unlink(suffix,"turn_restrictions"); + tempfile_unlink(suffix,"multipolygons"); tempfile_unlink(suffix,"graph"); tempfile_unlink(suffix,"tilesdir"); tempfile_unlink(suffix,"boundaries"); @@ -1008,6 +1027,11 @@ int main(int argc, char **argv) { if(!p.keep_tmpfiles) tempfile_unlink(suffix,"ways_split_index"); } + if (start_phase(&p,"generating multipolygons")) { + if(p.process_relations) { + osm_process_multipolygons(&p, suffix); + } + } if (p.process_relations && p.process_ways && p.process_nodes && start_phase(&p,"processing associated street relations")) { struct files_relation_processing *files_relproc = files_relation_processing_new(p.osm.line2poi, suffix); diff --git a/navit/maptool/maptool.h b/navit/maptool/maptool.h index edb2a77ef..aef344031 100644 --- a/navit/maptool/maptool.h +++ b/navit/maptool/maptool.h @@ -35,37 +35,37 @@ #define RELATION_MEMBER_PARSE_FORMAT "%d:"LONGLONG_FMT":%n" struct tile_data { - char buffer[1024]; - int tile_depth; - struct rect item_bbox; - struct rect tile_bbox; + char buffer[1024]; + int tile_depth; + struct rect item_bbox; + struct rect tile_bbox; }; struct tile_parameter { - int min; - int max; - int overlap; - enum attr_type attr_to_copy; + int min; + int max; + int overlap; + enum attr_type attr_to_copy; }; struct tile_info { - int write; - int maxlen; - char *suffix; - GList **tiles_list; - FILE *tilesdir_out; + int write; + int maxlen; + char *suffix; + GList **tiles_list; + FILE *tilesdir_out; }; extern struct tile_head { - int num_subtiles; - int total_size; - char *name; - char *zip_data; - int total_size_used; - int zipnum; - int process; - struct tile_head *next; - // char subtiles[0]; + int num_subtiles; + int total_size; + char *name; + char *zip_data; + int total_size_used; + int zipnum; + int process; + struct tile_head *next; + // char subtiles[0]; } *tile_head_root; @@ -80,12 +80,12 @@ extern struct tile_head { * @see struct attr_bin */ struct item_bin { - /** Length of this item (not including this length field) in 32-bit ints. */ - int len; - /** Item type. */ - enum item_type type; - /** Length of the following coordinate array in 32-bit ints. */ - int clen; + /** Length of this item (not including this length field) in 32-bit ints. */ + int len; + /** Item type. */ + enum item_type type; + /** Length of the following coordinate array in 32-bit ints. */ + int clen; }; /** @@ -96,27 +96,28 @@ struct item_bin { * @see struct item_bin */ struct attr_bin { - /** Length of this attribute (not including this length field) in 32-bit ints. */ - int len; - /** Attribute type. */ - enum attr_type type; + /** Length of this attribute (not including this length field) in 32-bit ints. */ + int len; + /** Attribute type. */ + enum attr_type type; }; struct item_bin_sink_func { - int (*func)(struct item_bin_sink_func *func, struct item_bin *ib, struct tile_data *tile_data); - void *priv_data[8]; + int (*func)(struct item_bin_sink_func *func, struct item_bin *ib, struct tile_data *tile_data); + void *priv_data[8]; }; struct item_bin_sink { - void *priv_data[8]; - GList *sink_funcs; + void *priv_data[8]; + GList *sink_funcs; }; #define NODE_ID_BITS 56 struct node_item { - struct coord c; - unsigned long long int nd_id:NODE_ID_BITS; - char ref_way; + struct coord c; +unsigned long long int nd_id: + NODE_ID_BITS; + char ref_way; }; struct zip_info; @@ -132,24 +133,24 @@ typedef unsigned long long int osmid; /** Files needed for processing a relation. */ struct files_relation_processing { - FILE *ways_in; - FILE *ways_out; - FILE *nodes_in; - FILE *nodes_out; - FILE *nodes2_in; - FILE *nodes2_out; + FILE *ways_in; + FILE *ways_out; + FILE *nodes_in; + FILE *nodes_out; + FILE *nodes2_in; + FILE *nodes2_out; }; /* boundaries.c */ struct boundary { - struct item_bin *ib; - struct country_table *country; - char *iso2; - GList *segments,*sorted_segments; - GList *children; - struct rect r; - osmid admin_centre; + struct item_bin *ib; + struct country_table *country; + char *iso2; + GList *segments,*sorted_segments; + GList *children; + struct rect r; + osmid admin_centre; }; char *osm_tag_value(struct item_bin *ib, char *key); @@ -166,14 +167,14 @@ void free_boundaries(GList *l); /** A buffer that can be grown as needed. */ struct buffer { - /** Number of bytes to extend the buffer by when it must grow. */ - int malloced_step; - /** Current allocated size (bytes). */ - long long malloced; - /** Base address of this buffer. */ - unsigned char *base; - /** Size of currently used part of the buffer. */ - long long size; + /** Number of bytes to extend the buffer by when it must grow. */ + int malloced_step; + /** Current allocated size (bytes). */ + long long malloced; + /** Base address of this buffer. */ + unsigned char *base; + /** Size of currently used part of the buffer. */ + long long size; }; void save_buffer(char *filename, struct buffer *b, long long offset); @@ -270,23 +271,24 @@ int item_order_by_type(enum item_type type); /* osm.c */ struct maptool_osm { - FILE *boundaries; - FILE *turn_restrictions; - FILE *associated_streets; - FILE *house_number_interpolations; - FILE *nodes; - FILE *ways; - FILE *line2poi; - FILE *poly2poi; - FILE *towns; + FILE *boundaries; + FILE *multipolygons; + FILE *turn_restrictions; + FILE *associated_streets; + FILE *house_number_interpolations; + FILE *nodes; + FILE *ways; + FILE *line2poi; + FILE *poly2poi; + FILE *towns; }; /** Type of a relation member. */ enum relation_member_type { - UNUSED, - rel_member_node, - rel_member_way, - rel_member_relation, + UNUSED, + rel_member_node, + rel_member_way, + rel_member_relation, }; void osm_warning(char *type, osmid id, int cont, char *fmt, ...); @@ -305,6 +307,7 @@ void flush_nodes(int final); void sort_countries(int keep_tmpfiles); void process_associated_streets(FILE *in, struct files_relation_processing *files_relproc); void process_house_number_interpolations(FILE *in, struct files_relation_processing *files_relproc); +void process_multipolygons(FILE *in, FILE *coords, FILE *ways, FILE *ways_index, FILE *out); void process_turn_restrictions(FILE *in, FILE *coords, FILE *ways, FILE *ways_index, FILE *out); void process_turn_restrictions_old(FILE *in, FILE *coords, FILE *ways, FILE *ways_index, FILE *out); void clear_node_item_buffer(void); @@ -314,7 +317,8 @@ unsigned long long item_bin_get_nodeid(struct item_bin *ib); unsigned long long item_bin_get_wayid(struct item_bin *ib); unsigned long long item_bin_get_relationid(struct item_bin *ib); void process_way2poi(FILE *in, FILE *out, int type); -int map_resolve_coords_and_split_at_intersections(FILE *in, FILE *out, FILE *out_index, FILE *out_graph, FILE *out_coastline, int final); +int map_resolve_coords_and_split_at_intersections(FILE *in, FILE *out, FILE *out_index, FILE *out_graph, + FILE *out_coastline, int final); void write_countrydir(struct zip_info *zip_info, int max_index_size); void osm_process_towns(FILE *in, FILE *boundaries, FILE *ways, char *suffix); void load_countries(void); @@ -334,8 +338,10 @@ int osm_protobufdb_load(FILE *in, char *dir); /* osm_relations.c */ struct relations * relations_new(void); -struct relations_func *relations_func_new(void (*func)(void *func_priv, void *relation_priv, struct item_bin *member, void *member_priv), void *func_priv); -void relations_add_relation_member_entry(struct relations *rel, struct relations_func *func, void *relation_priv, void *member_priv, enum relation_member_type type, osmid id); +struct relations_func *relations_func_new(void (*func)(void *func_priv, void *relation_priv, struct item_bin *member, + void *member_priv), void *func_priv); +void relations_add_relation_member_entry(struct relations *rel, struct relations_func *func, void *relation_priv, + void *member_priv, enum relation_member_type type, osmid id); void relations_add_relation_default_entry(struct relations *rel, struct relations_func *func); void relations_process(struct relations *rel, FILE *nodes, FILE *ways); void relations_destroy(struct relations *rel); @@ -350,7 +356,8 @@ int map_collect_data_osm(FILE *in, struct maptool_osm *osm); /* sourcesink.c */ struct item_bin_sink *item_bin_sink_new(void); -struct item_bin_sink_func *item_bin_sink_func_new(int (*func)(struct item_bin_sink_func *func, struct item_bin *ib, struct tile_data *tile_data)); +struct item_bin_sink_func *item_bin_sink_func_new(int (*func)(struct item_bin_sink_func *func, struct item_bin *ib, + struct tile_data *tile_data)); void item_bin_sink_func_destroy(struct item_bin_sink_func *func); void item_bin_sink_add_func(struct item_bin_sink *sink, struct item_bin_sink_func *func); void item_bin_sink_destroy(struct item_bin_sink *sink); @@ -374,9 +381,9 @@ void tempfile_rename(char *suffix, char *from, char *to); extern GHashTable *tile_hash,*tile_hash2; struct aux_tile { - char *name; - char *filename; - int size; + char *name; + char *filename; + int size; }; extern GList *aux_tile_list; @@ -415,4 +422,6 @@ void zip_close(struct zip_info *info); void zip_destroy(struct zip_info *info); /* Break compilation on 32 bit architectures, as we're going to cast osmid's to gpointer to use them as keys to GHashTable's */ -struct maptool_force_64 {char s[sizeof(gpointer)<sizeof(osmid)?-1:1];}; +struct maptool_force_64 { + char s[sizeof(gpointer)<sizeof(osmid)?-1:1]; +}; diff --git a/navit/maptool/osm.c b/navit/maptool/osm.c index f640c8674..00257129b 100644 --- a/navit/maptool/osm.c +++ b/navit/maptool/osm.c @@ -1616,8 +1616,23 @@ void osm_end_relation(struct maptool_osm *osm) { if(attr_longest_match(attr_mapping_rel2poly_place, attr_mapping_rel2poly_place_count, &type, 1)) { tmp_item_bin->type=type; - } else + } else { type=type_none; + tmp_item_bin->type=type; + } + + fprintf(stderr,"relation_type=%s\n", relation_type); + if ((!g_strcmp0(relation_type, "multipolygon")) && (!boundary)) { + item_bin_write(tmp_item_bin, osm->multipolygons); + } + + /*TODO: check if this was a bug: Previously attr_longest_match always failed, because + * item_is_poly_place never matched causing attr_mapping_rel2poly_place to be empty. + * Since I don't know what happenes if type suddenly is != type_none, I force the + * old behaviour here */ + type=type_none; + tmp_item_bin->type=type; + if ((!g_strcmp0(relation_type, "multipolygon") || !g_strcmp0(relation_type, "boundary")) && (boundary || type!=type_none)) { @@ -2643,6 +2658,163 @@ void process_house_number_interpolations(FILE *in, struct files_relation_process g_list_free(fp.allocations); } +#define MEMBER_MAX 20 +struct multipolygon { + osmid relid; + struct item_bin * rel; + int inner_count; + int outer_count; + struct item_bin ** inner; + struct item_bin ** outer; + int order; +}; + +static void process_multipolygons_finish(GList *tr, FILE *out) { + GList *l=tr; + fprintf(stderr,"process_multipolygons_finish\n"); + while(l) { + int a; + struct multipolygon *multipolygon=l->data; + struct rect bbox; + /* combine outer to full loops */ + + /* combine inner to full loops */ + + /* calculate bounding box */ + + /* write out */ + int order; + char tilebuf[20]=""; + struct item_bin* ib=tmp_item_bin; + item_bin_init(ib,multipolygon->rel->type); + item_bin_copy_coord(ib,multipolygon->outer[0],1); + item_bin_copy_attr(ib,multipolygon->rel,attr_osm_relationid); + + for(a = 0; a < multipolygon->inner_count; a ++) { + int hole_len; + char * buffer; + int used =0; + osmid * id; + hole_len = multipolygon->inner[a]->clen *4; + hole_len+=4 + 8; + buffer=g_alloca(hole_len); + id = (osmid *) item_bin_get_attr(multipolygon->inner[a], attr_osm_wayid, NULL); + if(id !=NULL) + memcpy(&(buffer[used]), id, sizeof(id)); + used += sizeof(id); + memcpy(&(buffer[used]), &(multipolygon->inner[a]->clen), hole_len - used); + item_bin_add_attr_data(ib, attr_poly_hole, buffer, hole_len); + } + + order=tile(&bbox,"",tilebuf,sizeof(tilebuf)-1,overlap,NULL); + if(order > multipolygon->order) + order=multipolygon->order; + + item_bin_add_attr_range(ib,attr_order,0,order); + item_bin_write(ib, out); + + /* clean up this item */ + for (a=0; a < multipolygon->inner_count; a ++) + g_free(multipolygon->inner[a]); + g_free(multipolygon->inner); + for (a=0; a < multipolygon->outer_count; a ++) + g_free(multipolygon->outer[a]); + g_free(multipolygon->outer); + g_free(multipolygon->rel); + g_free(multipolygon); + /* next item */ + l = g_list_next(l); + } + /* done with that list. All items referred should be deleted already. */ + g_list_free(tr); +} + +static void process_multipolygons_member(void *func_priv, void *relation_priv, struct item_bin *member, + void *member_priv) { + int type=(long)member_priv; + int i; + struct multipolygon *multipolygon=relation_priv; + fprintf(stderr,"process_multipolygons_member id %lld, %s, outer %d, inner %d\n", multipolygon->relid, + (type)?"inner": "outer", multipolygon->outer_count, multipolygon->inner_count); + /* we remeber the whole binary item, as we may want to have the attributes later on finalize */ + if(type) { + /* copy the member as inner */ + multipolygon->inner=(struct item_bin**) g_realloc(multipolygon->inner, + sizeof(struct item_bin *) * (multipolygon->inner_count +1)); + multipolygon->inner[multipolygon->inner_count]=item_bin_dup(member); + multipolygon->inner_count ++; + } else { + /* copy the member as outer */ + multipolygon->outer=(struct item_bin**) g_realloc(multipolygon->outer, + sizeof(struct item_bin *) * (multipolygon->outer_count +1)); + multipolygon->outer[multipolygon->outer_count]=item_bin_dup(member); + multipolygon->outer_count ++; + } + i=item_order_by_type(member->type); + if(i<multipolygon->order) + multipolygon->order=i; + +} + +static GList *process_multipolygons_setup(FILE *in, struct relations *relations) { + struct relation_member outer[MEMBER_MAX]; + int outer_count=0; + struct relation_member inner[MEMBER_MAX]; + int inner_count=0; + long long relid; + struct item_bin *ib; + struct relations_func *relations_func; + int min_count; + GList *multipolygons=NULL; + + fseek(in, 0, SEEK_SET); + relations_func=relations_func_new(process_multipolygons_member, NULL); + while ((ib=read_item(in))) { + int a; + struct multipolygon *p_multipolygon; + relid=item_bin_get_relationid(ib); + min_count=0; + while((outer_count < MEMBER_MAX) && (search_relation_member(ib, "outer",&(outer[outer_count]),&min_count))) { + if(outer[outer_count].type != rel_member_way) + osm_warning("relation",relid,0,"multipolygon: wrong type for outer member "); + outer_count ++; + } + min_count=0; + while((inner_count < MEMBER_MAX) && (search_relation_member(ib, "inner",&(inner[inner_count]),&min_count))) { + if(inner[inner_count].type != rel_member_way) + osm_warning("relation",relid,0,"multipolygon: wrong type for inner member "); + inner_count ++; + } + fprintf(stderr,"Relid %lld: Got %d outer and %d inner\n", relid, outer_count, inner_count); + if(outer == 0) { + osm_warning("relation",relid,0,"multipolygon: missing outer member "); + continue; + } + p_multipolygon=g_new0(struct multipolygon, 1); + p_multipolygon->relid=relid; + p_multipolygon->order=255; + p_multipolygon->rel=item_bin_dup(ib); + for (a = 0; a < outer_count; a ++) + relations_add_relation_member_entry(relations, relations_func, p_multipolygon, (gpointer) 0, outer[a].type, + outer[a].id); + for (a = 0; a < inner_count; a ++) + relations_add_relation_member_entry(relations, relations_func, p_multipolygon, (gpointer) 1, inner[a].type, + inner[a].id); + multipolygons=g_list_append(multipolygons, p_multipolygon); + } + return multipolygons; +} + +void process_multipolygons(FILE *in, FILE *coords, FILE *ways, FILE *ways_index, FILE *out) { + struct relations *relations=relations_new(); + GList *multipolygons; + fseek(in, 0, SEEK_SET); + multipolygons=process_multipolygons_setup(in, relations); + relations_process(relations, coords, ways); + process_multipolygons_finish(multipolygons, out); + relations_destroy(relations); +} + struct turn_restriction { osmid relid; enum item_type type; |