From f99e5245364d2b7cf9eb1d6c9ad8a09b263f7498 Mon Sep 17 00:00:00 2001 From: Stefan Wildemann Date: Sat, 27 Jul 2019 11:05:40 +0200 Subject: Process multipolygons to mapfile --- navit/maptool/maptool.c | 24 +++++++ navit/maptool/maptool.h | 171 +++++++++++++++++++++++++---------------------- navit/maptool/osm.c | 174 +++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 287 insertions(+), 82 deletions(-) (limited to 'navit/maptool') 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)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(iorder) + 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; -- cgit v1.2.1 From 7661afa5369c6e11da9995b551546fe16a0e0ed7 Mon Sep 17 00:00:00 2001 From: Stefan Wildemann Date: Sun, 28 Jul 2019 01:10:30 +0200 Subject: Fix coord count on attr_poly_hole. Forward name to multipolygons. --- navit/maptool/osm.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'navit/maptool') diff --git a/navit/maptool/osm.c b/navit/maptool/osm.c index 00257129b..166f57e31 100644 --- a/navit/maptool/osm.c +++ b/navit/maptool/osm.c @@ -1623,6 +1623,7 @@ void osm_end_relation(struct maptool_osm *osm) { fprintf(stderr,"relation_type=%s\n", relation_type); if ((!g_strcmp0(relation_type, "multipolygon")) && (!boundary)) { + item_bin_add_attr_string(tmp_item_bin, attr_label, attr_strings[attr_string_label]); item_bin_write(tmp_item_bin, osm->multipolygons); } @@ -1681,6 +1682,8 @@ static void relation_add_tag(char *k, char *v) { } } else if (!g_strcmp0(k,"ISO3166-1") || !g_strcmp0(k,"ISO3166-1:alpha2")) { g_strlcpy(iso_code, v, sizeof(iso_code)); + } else if (! g_strcmp0(k,"name")) { + attr_strings_save(attr_string_label, v); } if (add_tag) { char *tag; @@ -2689,6 +2692,7 @@ static void process_multipolygons_finish(GList *tr, FILE *out) { 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); + item_bin_copy_attr(ib,multipolygon->rel,attr_label); for(a = 0; a < multipolygon->inner_count; a ++) { int hole_len; @@ -2702,6 +2706,9 @@ static void process_multipolygons_finish(GList *tr, FILE *out) { if(id !=NULL) memcpy(&(buffer[used]), id, sizeof(id)); used += sizeof(id); + /* item_bin gives the coordinate count in 32bit values. We want to have it in + * number of coordinates. So divide by 2. Then we can memcopy*/ + multipolygon->inner[a]->clen /= 2; memcpy(&(buffer[used]), &(multipolygon->inner[a]->clen), hole_len - used); item_bin_add_attr_data(ib, attr_poly_hole, buffer, hole_len); } -- cgit v1.2.1 From 4ba1bc591aa2f58e652c598e31ccbb1e626ada0d Mon Sep 17 00:00:00 2001 From: Stefan Wildemann Date: Mon, 29 Jul 2019 00:42:26 +0200 Subject: Fix multipolygon assignment. --- navit/maptool/osm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'navit/maptool') diff --git a/navit/maptool/osm.c b/navit/maptool/osm.c index 166f57e31..4db532947 100644 --- a/navit/maptool/osm.c +++ b/navit/maptool/osm.c @@ -2764,11 +2764,6 @@ static void process_multipolygons_member(void *func_priv, void *relation_priv, s } 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; @@ -2777,6 +2772,11 @@ static GList *process_multipolygons_setup(FILE *in, struct relations *relations) fseek(in, 0, SEEK_SET); relations_func=relations_func_new(process_multipolygons_member, NULL); while ((ib=read_item(in))) { + struct relation_member outer[MEMBER_MAX]; + int outer_count=0; + struct relation_member inner[MEMBER_MAX]; + int inner_count=0; + long long relid; int a; struct multipolygon *p_multipolygon; relid=item_bin_get_relationid(ib); -- cgit v1.2.1 From d5580652b5daf829f3874b9f96e7d191b288a74d Mon Sep 17 00:00:00 2001 From: Wildemann Stefan Date: Mon, 29 Jul 2019 16:32:33 +0200 Subject: Fix memory handling in maptool. --- navit/maptool/osm.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'navit/maptool') diff --git a/navit/maptool/osm.c b/navit/maptool/osm.c index 4db532947..38ba1c351 100644 --- a/navit/maptool/osm.c +++ b/navit/maptool/osm.c @@ -1569,6 +1569,7 @@ int boundary; void osm_add_relation(osmid id) { osmid_attr_value=id; in_relation=1; + attr_strings_clear(); debug_attr_buffer[0]='\0'; relation_type[0]='\0'; iso_code[0]='\0'; @@ -2689,6 +2690,12 @@ static void process_multipolygons_finish(GList *tr, FILE *out) { int order; char tilebuf[20]=""; struct item_bin* ib=tmp_item_bin; + if(multipolygon->outer_count == 0 || multipolygon->outer[0] == NULL) { + fprintf(stderr,"unresolved outer %lld\n", multipolygon->relid); + /* seems this polygons "outer" could not be resolved. Skip it */ + l = g_list_next(l); + continue; + } 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); @@ -2704,8 +2711,8 @@ static void process_multipolygons_finish(GList *tr, FILE *out) { 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]), id, sizeof(*id)); + used += sizeof(*id); /* item_bin gives the coordinate count in 32bit values. We want to have it in * number of coordinates. So divide by 2. Then we can memcopy*/ multipolygon->inner[a]->clen /= 2; -- cgit v1.2.1 From 6eb13d10d6c1e024f91904fa4b4c43c563091921 Mon Sep 17 00:00:00 2001 From: Wildemann Stefan Date: Tue, 30 Jul 2019 18:12:42 +0200 Subject: Start converting multi polygon chunks to closed loops --- navit/maptool/osm.c | 256 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 216 insertions(+), 40 deletions(-) (limited to 'navit/maptool') diff --git a/navit/maptool/osm.c b/navit/maptool/osm.c index 38ba1c351..9ea38cdd2 100644 --- a/navit/maptool/osm.c +++ b/navit/maptool/osm.c @@ -2673,60 +2673,236 @@ struct multipolygon { int order; }; +/** + * @brief find the nect matching polygon segment + * This can be used to find the next matching "line" to form a polygon. + * @param coord find lines starting (or ending) at this coordinate + * @param in_count number of lines passed in parts + * @parts array of item_bin pointers giving the single parts + * @parts used int array, one for each part, indicating wheather the part was already used. This + * function sets the usage for the mathcing part if one is found. Usage is 0: not used, + * 1: used forward 2: used reverse + * @returns: index of matching part, -1 if none matches or all are consumed already. + */ +static int process_multipolygon_find_match(struct coord* coord, int in_count, struct item_bin **parts, int*used) { + int i; + for(i=0; i < in_count; i ++) { + if(!used[i]) { + int have_match = 0; + struct coord *try_first, *try_last; + + if(parts[i]->clen < 2) { + fprintf(stderr,"skipping single point"); + used[i] = 1; + continue; + } + + try_first=(struct coord *)(parts[i] +1); + try_last=(struct coord *)(parts[i] +1); + try_last+=(parts[i]->clen / 2) - 1; + //fprintf(stderr, "try_first[%d] 0x%x,0x%x, try_last[%d] 0x%x,0x%x\n",i,try_first->x, try_first->y, i, try_last->x, + // try_last->y); + + if((coord->x == try_first->x) && (coord->y == try_first->y)) { + /* forward match */ + //fprintf(stderr,"forward match\n"); + have_match=1; + } else if((coord->x == try_last->x) && (coord->y == try_last->y)) { + fprintf(stderr,"reverse match\n"); + /* reverse match */ + have_match=2; + /* copy first to last foor loop check */ + try_last = try_first; + } + /* add match to sequence */ + if(have_match) { + used[i]=have_match; + return i; + } + } + } + return -1; +} + +static int process_multipolygon_find_loop(int in_count, struct item_bin ** parts, int **scount, int *** sequences) { + int done=0; + int loop_count=0; + int *used; + if((in_count == 0) || (parts == NULL) || (sequences == NULL) || (scount == NULL)) + return 0; + /* start with nothing */ + *sequences = NULL; + *scount = NULL; + used=g_malloc0(in_count * sizeof(int)); + fprintf(stderr,"find loops in %d parts\n",in_count); + while(!done) { + int a; + int done_loop=0; + int have_loop=0; + int part_count=0; + int *sequence; + /* find first unused part to begin */ + for(a=0; a < in_count; a ++) { + if(!used[a]) + break; + } + /* chech if actually one was found */ + if(!(a < in_count)) { + done = 1; + } else { + sequence=g_malloc0(in_count * sizeof(int)); + } + + /* consume this, and start sequence */ + used[a] = 1; /** always start keeping order */ + sequence[part_count] = a; + /* will increase part_count later */ + + + while((!have_loop) && (!done_loop) && (!done)) { + struct coord *first, *last; + /*get the actual starting coordinate of the sequence*/ + first=(struct coord *)(parts[sequence[0]] +1); + /*get the actual ending coordinate of the sequence*/ + last=(struct coord *)(parts[sequence[part_count]] +1); + if(used[sequence[part_count]] == 1) { + /* was a standard match. Need last coordinate */ + last+=((parts[sequence[part_count]]->clen) / 2) - 1; + } + //fprintf(stderr, "first 0x%x,0x%x, last[%d] 0x%x,0x%x\n",first->x, first->y, sequence[part_count], last->x, last->y); + + /* check if this is a loop already */ + if((first->x == last->x) && (first->y == last->y)) + have_loop=1; + + /* No loop yet, try to find the next matching part */ + sequence[part_count +1] = process_multipolygon_find_match(last, in_count, parts, used); + /*process_multipolygon_find_match coped for "used" already*/ + if(sequence[part_count +1] >= 0) { + /* matching part found */ + part_count ++; + /*next iteration will check for loop*/ + } else { + done_loop=1; + } + + } + if(have_loop) { + /* add the first entry to count */ + part_count ++; + /* copy over the found loop sequence*/ + /* increase memory for count array */ + (*scount)=(int*) g_realloc((*scount), (loop_count +1) * sizeof(int)); + /* increase memory for sequences array */ + (*sequences)=(int**) g_realloc((*sequences), (loop_count +1) * sizeof(int*)); + /* link the sequence */ + (*scount)[loop_count]=part_count; + (*sequences)[loop_count]=sequence; + /* count loop */ + loop_count ++; + /* do not delete sequence, as we added it to *sequences */ + } else if(!done) { + int i; + fprintf(stderr,"Throw away sequence which is no loop :"); + for(i=0; i < part_count; i ++) + fprintf(stderr, "%d ", sequence[i]); + fprintf(stderr, "\n"); + g_free(sequence); + } + } + fprintf(stderr,"found %d loops\n", loop_count); + g_free(used); + return loop_count; +} +static inline void dump_sequence(const char * string, int loop_count, int*scount, int**sequences) { + int i; + int j; + for(j=0; jdata; struct rect bbox; + int inner_loop_count; + int *inner_scount=NULL; + int **inner_sequences=NULL; + int outer_loop_count=NULL; + int *outer_scount=NULL; + int **outer_sequences=NULL; /* combine outer to full loops */ + outer_loop_count = process_multipolygon_find_loop(multipolygon->outer_count,multipolygon->outer, &outer_scount, + &outer_sequences); /* combine inner to full loops */ + inner_loop_count = process_multipolygon_find_loop(multipolygon->inner_count,multipolygon->inner, &inner_scount, + &inner_sequences); + + dump_sequence("outer",outer_loop_count, outer_scount, outer_sequences); + dump_sequence("inner",inner_loop_count, inner_scount, inner_sequences); /* calculate bounding box */ - /* write out */ - int order; - char tilebuf[20]=""; - struct item_bin* ib=tmp_item_bin; - if(multipolygon->outer_count == 0 || multipolygon->outer[0] == NULL) { - fprintf(stderr,"unresolved outer %lld\n", multipolygon->relid); - /* seems this polygons "outer" could not be resolved. Skip it */ - l = g_list_next(l); - continue; - } - 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); - item_bin_copy_attr(ib,multipolygon->rel,attr_label); - - 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); - /* item_bin gives the coordinate count in 32bit values. We want to have it in - * number of coordinates. So divide by 2. Then we can memcopy*/ - multipolygon->inner[a]->clen /= 2; - 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); + for(b=0; bouter_count == 0 || multipolygon->outer[0] == NULL) { + fprintf(stderr,"unresolved outer %lld\n", multipolygon->relid); + /* seems this polygons "outer" could not be resolved. Skip it */ + l = g_list_next(l); + continue; + } + 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); + item_bin_copy_attr(ib,multipolygon->rel,attr_label); + + 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); + /* item_bin gives the coordinate count in 32bit values. We want to have it in + * number of coordinates. So divide by 2. Then we can memcopy*/ + multipolygon->inner[a]->clen /= 2; + 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 the sequences */ + for(a=0; a < outer_loop_count; a ++) + g_free (outer_sequences[a]); + g_free(outer_sequences); + g_free(outer_scount); + for(a=0; a < inner_loop_count; a ++) + g_free (inner_sequences[a]); + g_free(inner_sequences); + g_free(inner_scount); /* clean up this item */ for (a=0; a < multipolygon->inner_count; a ++) g_free(multipolygon->inner[a]); -- cgit v1.2.1 From 69bdf87531a7c29cd72818f9b762e6fbc51bc58d Mon Sep 17 00:00:00 2001 From: Stefan Wildemann Date: Wed, 31 Jul 2019 00:33:36 +0200 Subject: Convert parts to polygons. Partly working --- navit/maptool/osm.c | 179 +++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 135 insertions(+), 44 deletions(-) (limited to 'navit/maptool') diff --git a/navit/maptool/osm.c b/navit/maptool/osm.c index 9ea38cdd2..fc8f79851 100644 --- a/navit/maptool/osm.c +++ b/navit/maptool/osm.c @@ -2684,7 +2684,7 @@ struct multipolygon { * 1: used forward 2: used reverse * @returns: index of matching part, -1 if none matches or all are consumed already. */ -static int process_multipolygon_find_match(struct coord* coord, int in_count, struct item_bin **parts, int*used) { +static int process_multipolygons_find_match(struct coord* coord, int in_count, struct item_bin **parts, int*used) { int i; for(i=0; i < in_count; i ++) { if(!used[i]) { @@ -2724,17 +2724,48 @@ static int process_multipolygon_find_match(struct coord* coord, int in_count, s return -1; } -static int process_multipolygon_find_loop(int in_count, struct item_bin ** parts, int **scount, int *** sequences) { +static int process_multipolygons_find_loop(int in_count, struct item_bin ** parts, int **scount, int *** sequences, + int **direction) { int done=0; int loop_count=0; int *used; if((in_count == 0) || (parts == NULL) || (sequences == NULL) || (scount == NULL)) return 0; + fprintf(stderr,"find loops in %d parts\n",in_count); /* start with nothing */ *sequences = NULL; *scount = NULL; + *direction = NULL; + /* allocate the usage and direction array.*/ used=g_malloc0(in_count * sizeof(int)); - fprintf(stderr,"find loops in %d parts\n",in_count); +#if 0 + while (! done) { + int a; + /* search for a new loop */ + /* find first unused part to begin */ + for(a=0; a < in_count; a ++) { + if(!used[a]) + break; + } + if(!(a < in_count)) { + /* got no unused part */ + done=1; + } else { + char * sequence; + int part_count = 0; + int done_loop = 0; + /* start a new sequence */ + sequence=g_malloc0(in_count * sizeof(int)); + /* consume the first item */ + used[a] = 1; + /* add to sequence */ + sequence[part_count]=a; + part_count ++; + while ((part_count < in_count) || (done_loop)) { + } + } + } +#else while(!done) { int a; int done_loop=0; @@ -2749,16 +2780,15 @@ static int process_multipolygon_find_loop(int in_count, struct item_bin ** parts /* chech if actually one was found */ if(!(a < in_count)) { done = 1; - } else { + } + if(! done) { sequence=g_malloc0(in_count * sizeof(int)); + /* consume this, and start sequence */ + used[a] = 1; /** always start keeping order */ + sequence[part_count] = a; + /* will increase part_count later */ } - /* consume this, and start sequence */ - used[a] = 1; /** always start keeping order */ - sequence[part_count] = a; - /* will increase part_count later */ - - while((!have_loop) && (!done_loop) && (!done)) { struct coord *first, *last; /*get the actual starting coordinate of the sequence*/ @@ -2774,17 +2804,19 @@ static int process_multipolygon_find_loop(int in_count, struct item_bin ** parts /* check if this is a loop already */ if((first->x == last->x) && (first->y == last->y)) have_loop=1; - - /* No loop yet, try to find the next matching part */ - sequence[part_count +1] = process_multipolygon_find_match(last, in_count, parts, used); - /*process_multipolygon_find_match coped for "used" already*/ - if(sequence[part_count +1] >= 0) { - /* matching part found */ - part_count ++; - /*next iteration will check for loop*/ - } else { - done_loop=1; - } + if((!have_loop) && (part_count + 1 < in_count)) { + /* No loop yet, try to find the next matching part */ + sequence[part_count +1] = process_multipolygons_find_match(last, in_count, parts, used); + /*process_multipolygon_find_match coped for "used" already*/ + if(sequence[part_count +1] >= 0) { + /* matching part found */ + part_count ++; + /*next iteration will check for loop*/ + } else { + done_loop=1; + } + } else + done=1; } if(have_loop) { @@ -2810,10 +2842,57 @@ static int process_multipolygon_find_loop(int in_count, struct item_bin ** parts g_free(sequence); } } +#endif fprintf(stderr,"found %d loops\n", loop_count); - g_free(used); + *direction = used; return loop_count; } + +static int process_multipolygons_loop_dump(struct item_bin** bin, int scount, int*sequence, int*direction, + struct coord * buffer) { + int points = 0; + int a; + + if((bin == NULL) || (scount <= 0) || (sequence == NULL)) + return 0; + + for(a=0; a < scount; a++) { + int pcount; + struct coord * c; + c= (struct coord *) (bin[sequence[a]] + 1); + pcount= bin[sequence[a]]->clen / 2; + /* cut the duplicate on all than the first one */ + if(a!=0) + pcount --; + + if((buffer != NULL) && (direction !=NULL)) { + if(direction[a] == 1) { + memcpy(&(buffer[points]), c, pcount * sizeof(struct coord)); + } else { + int b; + struct coord * target = &(buffer[points]); + for (b=0; b < pcount; b ++) { + target[b] = c[(bin[sequence[a]]->clen / 2) - pcount -1]; + } + } + } + points += pcount; + } + return points; +} + +/** + * @brief get number of coordinates inside a sequence calculated by process_multipolygon_find_loop + * + * @param bin the array of all raw members of this multipolygon + * @param scount number of members inside this sequence + * @param sequence sequence calculated by process_multipolygon_find_loop + * @returns number of coords + */ +static int process_multipolygons_loop_count(struct item_bin** bin, int scount, int*sequence) { + return process_multipolygons_loop_dump(bin,scount,sequence,NULL,NULL); +} + static inline void dump_sequence(const char * string, int loop_count, int*scount, int**sequences) { int i; int j; @@ -2833,19 +2912,21 @@ static void process_multipolygons_finish(GList *tr, FILE *out) { int b; struct multipolygon *multipolygon=l->data; struct rect bbox; - int inner_loop_count; + int inner_loop_count=0; int *inner_scount=NULL; + int *inner_direction=NULL; int **inner_sequences=NULL; - int outer_loop_count=NULL; + int outer_loop_count=0; int *outer_scount=NULL; + int *outer_direction=NULL; int **outer_sequences=NULL; /* combine outer to full loops */ - outer_loop_count = process_multipolygon_find_loop(multipolygon->outer_count,multipolygon->outer, &outer_scount, - &outer_sequences); + outer_loop_count = process_multipolygons_find_loop(multipolygon->outer_count,multipolygon->outer, &outer_scount, + &outer_sequences, &outer_direction); /* combine inner to full loops */ - inner_loop_count = process_multipolygon_find_loop(multipolygon->inner_count,multipolygon->inner, &inner_scount, - &inner_sequences); + inner_loop_count = process_multipolygons_find_loop(multipolygon->inner_count,multipolygon->inner, &inner_scount, + &inner_sequences, &inner_direction); dump_sequence("outer",outer_loop_count, outer_scount, outer_sequences); dump_sequence("inner",inner_loop_count, inner_scount, inner_sequences); @@ -2857,34 +2938,42 @@ static void process_multipolygons_finish(GList *tr, FILE *out) { int order; char tilebuf[20]=""; struct item_bin* ib=tmp_item_bin; - if(multipolygon->outer_count == 0 || multipolygon->outer[0] == NULL) { + int outer_length; + struct coord * outer_buffer; + if(outer_loop_count == 0) { fprintf(stderr,"unresolved outer %lld\n", multipolygon->relid); /* seems this polygons "outer" could not be resolved. Skip it */ l = g_list_next(l); continue; } + outer_length = process_multipolygons_loop_count(multipolygon->outer, outer_scount[b], + outer_sequences[b]) * sizeof(struct coord); + outer_buffer = (struct coord *) g_malloc0(outer_length); + outer_length = process_multipolygons_loop_dump(multipolygon->outer, outer_scount[b], outer_sequences[b], + outer_direction, outer_buffer); item_bin_init(ib,multipolygon->rel->type); - item_bin_copy_coord(ib,multipolygon->outer[0],1); + item_bin_add_coord(ib, outer_buffer, outer_length); + g_free(outer_buffer); item_bin_copy_attr(ib,multipolygon->rel,attr_osm_relationid); item_bin_copy_attr(ib,multipolygon->rel,attr_label); - for(a = 0; a < multipolygon->inner_count; a ++) { + for(a = 0; a < inner_loop_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); - /* item_bin gives the coordinate count in 32bit values. We want to have it in - * number of coordinates. So divide by 2. Then we can memcopy*/ - multipolygon->inner[a]->clen /= 2; - memcpy(&(buffer[used]), &(multipolygon->inner[a]->clen), hole_len - used); - item_bin_add_attr_data(ib, attr_poly_hole, buffer, hole_len); + int inner_len =0; + hole_len = process_multipolygons_loop_count(multipolygon->inner, inner_scount[a], inner_sequences[a]); + inner_len = (hole_len * sizeof(struct coord)); + inner_len+=4; + buffer=g_malloc0(inner_len); + memcpy(&(buffer[used]), &(hole_len), sizeof(int)); + used += sizeof(int); + fprintf(stderr,"hole_len %d, used %d\n", hole_len, used); + used += process_multipolygons_loop_dump(multipolygon->inner, inner_scount[a], inner_sequences[a], inner_direction, + (struct coord *)&(buffer[used])) * sizeof(struct coord); + fprintf(stderr,"hole_len %d, used %d\n", hole_len, used); + item_bin_add_attr_data(ib, attr_poly_hole, buffer, inner_len); + g_free(buffer); } order=tile(&bbox,"",tilebuf,sizeof(tilebuf)-1,overlap,NULL); @@ -2899,10 +2988,12 @@ static void process_multipolygons_finish(GList *tr, FILE *out) { g_free (outer_sequences[a]); g_free(outer_sequences); g_free(outer_scount); + g_free(outer_direction); for(a=0; a < inner_loop_count; a ++) g_free (inner_sequences[a]); g_free(inner_sequences); g_free(inner_scount); + g_free(inner_direction); /* clean up this item */ for (a=0; a < multipolygon->inner_count; a ++) g_free(multipolygon->inner[a]); -- cgit v1.2.1 From 8061e9b1e4a82368d8acf626179f9e657fea4664 Mon Sep 17 00:00:00 2001 From: Wildemann Stefan Date: Wed, 31 Jul 2019 17:36:03 +0200 Subject: Fix/refactor polygon reassembly. We're getting close. Finally processed map of Oberbayern, Germany without any issues. Renders nicely on Qt5. Nedds still some hacks in maptool as I did not understan everything properly. Parts of maptool are rather hacky, aren't they? --- navit/maptool/osm.c | 250 +++++++++++++++++++++++++++------------------------- 1 file changed, 128 insertions(+), 122 deletions(-) (limited to 'navit/maptool') diff --git a/navit/maptool/osm.c b/navit/maptool/osm.c index fc8f79851..6eab6a903 100644 --- a/navit/maptool/osm.c +++ b/navit/maptool/osm.c @@ -2662,7 +2662,6 @@ 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; @@ -2676,7 +2675,8 @@ struct multipolygon { /** * @brief find the nect matching polygon segment * This can be used to find the next matching "line" to form a polygon. - * @param coord find lines starting (or ending) at this coordinate + * @param part current line part + * @param part_used how this part was used * @param in_count number of lines passed in parts * @parts array of item_bin pointers giving the single parts * @parts used int array, one for each part, indicating wheather the part was already used. This @@ -2684,8 +2684,16 @@ struct multipolygon { * 1: used forward 2: used reverse * @returns: index of matching part, -1 if none matches or all are consumed already. */ -static int process_multipolygons_find_match(struct coord* coord, int in_count, struct item_bin **parts, int*used) { +static int process_multipolygons_find_match(struct item_bin* part,int part_used, int in_count, struct item_bin **parts, + int*used) { int i; + struct coord * coord; + /*get the actual ending coordinate of the sequence*/ + coord=(struct coord *)(part +1); + if(part_used == 1) { + /* was a standard match. Need last coordinate */ + coord+=(part->clen / 2) - 1; + } for(i=0; i < in_count; i ++) { if(!used[i]) { int have_match = 0; @@ -2700,8 +2708,9 @@ static int process_multipolygons_find_match(struct coord* coord, int in_count, try_first=(struct coord *)(parts[i] +1); try_last=(struct coord *)(parts[i] +1); try_last+=(parts[i]->clen / 2) - 1; - //fprintf(stderr, "try_first[%d] 0x%x,0x%x, try_last[%d] 0x%x,0x%x\n",i,try_first->x, try_first->y, i, try_last->x, - // try_last->y); + fprintf(stderr, "0x%x,0x%x try_first[%d] 0x%x,0x%x try_last[%d] 0x%x,0x%x\n",coord->x, coord->y,i,try_first->x, + try_first->y, i, try_last->x, + try_last->y); if((coord->x == try_first->x) && (coord->y == try_first->y)) { /* forward match */ @@ -2724,7 +2733,68 @@ static int process_multipolygons_find_match(struct coord* coord, int in_count, return -1; } -static int process_multipolygons_find_loop(int in_count, struct item_bin ** parts, int **scount, int *** sequences, +static int is_loop (struct item_bin * start_part, int start_used, struct item_bin * end_part, int end_used) { + struct coord *first, *last; + /*get the actual starting coordinate of the sequence*/ + first=(struct coord *)(start_part +1); + if(start_used != 1) { + /* was a reverse match. Need first coordinate */ + first+=(start_part->clen / 2) - 1; + } + + /*get the actual ending coordinate of the sequence*/ + last=(struct coord *)(end_part +1); + if(end_used == 1) { + /* was a standard match. Need last coordinate */ + last+=(end_part->clen / 2) - 1; + } + if((first->x == last->x) && (first->y == last->y)) + return 1; + return 0; +} + +static int process_multipolygons_find_loop(int in_count, struct item_bin ** parts, int* sequence, int * used) { + int a; + int sequence_count=0; + /* assume we already have the sequence array*/ + + /* to start find a unused part */ + for(a=0; a < in_count; a ++) { + if(!used[a]) + break; + } + if(!(a < in_count)) { + /* got no unused part. indicate no more loops possible */ + return -1; + } + /* consume this part */ + used[a] = 1; + sequence[sequence_count]=a; + sequence_count ++; + + /* check all parts until no more matches, or a loop is found */ + while(!is_loop (parts[sequence[0]], used[sequence[0]], parts[sequence[sequence_count-1]], + used[sequence[sequence_count-1]])) { + int match; + /* get new mathching part */ + match=process_multipolygons_find_match(parts[sequence[sequence_count-1]],used[sequence[sequence_count-1]], in_count, + parts, used); + if(match >= 0) { + sequence[sequence_count]=match; + sequence_count ++; + } else { + break; + } + } + + /* check if this is a loop already */ + if(is_loop (parts[sequence[0]], used[sequence[0]], parts[sequence[sequence_count-1]], used[sequence[sequence_count-1]])) + return sequence_count; + else + return 0; +} + +static int process_multipolygons_find_loops(int in_count, struct item_bin ** parts, int **scount, int *** sequences, int **direction) { int done=0; int loop_count=0; @@ -2738,111 +2808,26 @@ static int process_multipolygons_find_loop(int in_count, struct item_bin ** part *direction = NULL; /* allocate the usage and direction array.*/ used=g_malloc0(in_count * sizeof(int)); -#if 0 - while (! done) { - int a; - /* search for a new loop */ - /* find first unused part to begin */ - for(a=0; a < in_count; a ++) { - if(!used[a]) - break; - } - if(!(a < in_count)) { - /* got no unused part */ - done=1; - } else { - char * sequence; - int part_count = 0; - int done_loop = 0; - /* start a new sequence */ - sequence=g_malloc0(in_count * sizeof(int)); - /* consume the first item */ - used[a] = 1; - /* add to sequence */ - sequence[part_count]=a; - part_count ++; - while ((part_count < in_count) || (done_loop)) { - } - } - } -#else - while(!done) { - int a; - int done_loop=0; - int have_loop=0; - int part_count=0; - int *sequence; - /* find first unused part to begin */ - for(a=0; a < in_count; a ++) { - if(!used[a]) - break; - } - /* chech if actually one was found */ - if(!(a < in_count)) { + do { + int sequence_count; + int * sequence = g_malloc0(in_count * sizeof(int)); + sequence_count = process_multipolygons_find_loop(in_count, parts, sequence, used); + if(sequence_count < 0) { done = 1; - } - if(! done) { - sequence=g_malloc0(in_count * sizeof(int)); - /* consume this, and start sequence */ - used[a] = 1; /** always start keeping order */ - sequence[part_count] = a; - /* will increase part_count later */ - } - - while((!have_loop) && (!done_loop) && (!done)) { - struct coord *first, *last; - /*get the actual starting coordinate of the sequence*/ - first=(struct coord *)(parts[sequence[0]] +1); - /*get the actual ending coordinate of the sequence*/ - last=(struct coord *)(parts[sequence[part_count]] +1); - if(used[sequence[part_count]] == 1) { - /* was a standard match. Need last coordinate */ - last+=((parts[sequence[part_count]]->clen) / 2) - 1; - } - //fprintf(stderr, "first 0x%x,0x%x, last[%d] 0x%x,0x%x\n",first->x, first->y, sequence[part_count], last->x, last->y); - - /* check if this is a loop already */ - if((first->x == last->x) && (first->y == last->y)) - have_loop=1; - if((!have_loop) && (part_count + 1 < in_count)) { - /* No loop yet, try to find the next matching part */ - sequence[part_count +1] = process_multipolygons_find_match(last, in_count, parts, used); - /*process_multipolygon_find_match coped for "used" already*/ - if(sequence[part_count +1] >= 0) { - /* matching part found */ - part_count ++; - /*next iteration will check for loop*/ - } else { - done_loop=1; - } - } else - done=1; - - } - if(have_loop) { - /* add the first entry to count */ - part_count ++; - /* copy over the found loop sequence*/ - /* increase memory for count array */ + } else if(sequence_count == 0) { + fprintf(stderr,"skipping nonclosed sequence\n"); + /* skip empty sequence */ + g_free(sequence); + } else { + /* increase space for sequences */ (*scount)=(int*) g_realloc((*scount), (loop_count +1) * sizeof(int)); - /* increase memory for sequences array */ (*sequences)=(int**) g_realloc((*sequences), (loop_count +1) * sizeof(int*)); - /* link the sequence */ - (*scount)[loop_count]=part_count; - (*sequences)[loop_count]=sequence; - /* count loop */ + /* hook it in */ + (*scount)[loop_count] = sequence_count; + (*sequences)[loop_count] = sequence; loop_count ++; - /* do not delete sequence, as we added it to *sequences */ - } else if(!done) { - int i; - fprintf(stderr,"Throw away sequence which is no loop :"); - for(i=0; i < part_count; i ++) - fprintf(stderr, "%d ", sequence[i]); - fprintf(stderr, "\n"); - g_free(sequence); } - } -#endif + } while (!done); fprintf(stderr,"found %d loops\n", loop_count); *direction = used; return loop_count; @@ -2861,10 +2846,10 @@ static int process_multipolygons_loop_dump(struct item_bin** bin, int scount, in struct coord * c; c= (struct coord *) (bin[sequence[a]] + 1); pcount= bin[sequence[a]]->clen / 2; - /* cut the duplicate on all than the first one */ + + /* remove the duplicate point if not the first one */ if(a!=0) pcount --; - if((buffer != NULL) && (direction !=NULL)) { if(direction[a] == 1) { memcpy(&(buffer[points]), c, pcount * sizeof(struct coord)); @@ -2872,7 +2857,7 @@ static int process_multipolygons_loop_dump(struct item_bin** bin, int scount, in int b; struct coord * target = &(buffer[points]); for (b=0; b < pcount; b ++) { - target[b] = c[(bin[sequence[a]]->clen / 2) - pcount -1]; + target[b] = c[(bin[sequence[a]]->clen / 2) - b -1]; } } } @@ -2911,7 +2896,6 @@ static void process_multipolygons_finish(GList *tr, FILE *out) { int a; int b; struct multipolygon *multipolygon=l->data; - struct rect bbox; int inner_loop_count=0; int *inner_scount=NULL; int *inner_direction=NULL; @@ -2921,19 +2905,19 @@ static void process_multipolygons_finish(GList *tr, FILE *out) { int *outer_direction=NULL; int **outer_sequences=NULL; /* combine outer to full loops */ - outer_loop_count = process_multipolygons_find_loop(multipolygon->outer_count,multipolygon->outer, &outer_scount, + outer_loop_count = process_multipolygons_find_loops(multipolygon->outer_count,multipolygon->outer, &outer_scount, &outer_sequences, &outer_direction); /* combine inner to full loops */ - inner_loop_count = process_multipolygons_find_loop(multipolygon->inner_count,multipolygon->inner, &inner_scount, + inner_loop_count = process_multipolygons_find_loops(multipolygon->inner_count,multipolygon->inner, &inner_scount, &inner_sequences, &inner_direction); dump_sequence("outer",outer_loop_count, outer_scount, outer_sequences); dump_sequence("inner",inner_loop_count, inner_scount, inner_sequences); - /* calculate bounding box */ for(b=0; brel); + fprintf(stderr,"process %lld\n", relid); outer_length = process_multipolygons_loop_count(multipolygon->outer, outer_scount[b], outer_sequences[b]) * sizeof(struct coord); outer_buffer = (struct coord *) g_malloc0(outer_length); @@ -2956,27 +2942,37 @@ static void process_multipolygons_finish(GList *tr, FILE *out) { g_free(outer_buffer); item_bin_copy_attr(ib,multipolygon->rel,attr_osm_relationid); item_bin_copy_attr(ib,multipolygon->rel,attr_label); + /*calculate bbox*/ + bbox((struct coord*)(ib +1), (ib->clen/2), &outer_bbox); for(a = 0; a < inner_loop_count; a ++) { + int d; int hole_len; char * buffer; int used =0; int inner_len =0; + int inside = 0; + struct coord *hole_coord; hole_len = process_multipolygons_loop_count(multipolygon->inner, inner_scount[a], inner_sequences[a]); inner_len = (hole_len * sizeof(struct coord)); inner_len+=4; buffer=g_malloc0(inner_len); memcpy(&(buffer[used]), &(hole_len), sizeof(int)); used += sizeof(int); - fprintf(stderr,"hole_len %d, used %d\n", hole_len, used); + hole_coord = (struct coord*) &(buffer[used]); used += process_multipolygons_loop_dump(multipolygon->inner, inner_scount[a], inner_sequences[a], inner_direction, (struct coord *)&(buffer[used])) * sizeof(struct coord); - fprintf(stderr,"hole_len %d, used %d\n", hole_len, used); - item_bin_add_attr_data(ib, attr_poly_hole, buffer, inner_len); + /* check if at least one point is inside the outer */ + for(d=0; d < hole_len; d++) + if(bbox_contains_coord(&outer_bbox,hole_coord)) + inside=1; + + if(inside) + item_bin_add_attr_data(ib, attr_poly_hole, buffer, inner_len); g_free(buffer); } - order=tile(&bbox,"",tilebuf,sizeof(tilebuf)-1,overlap,NULL); + order=tile(&outer_bbox,"",tilebuf,sizeof(tilebuf)-1,overlap,NULL); if(order > multipolygon->order) order=multipolygon->order; @@ -3046,28 +3042,35 @@ static GList *process_multipolygons_setup(FILE *in, struct relations *relations) fseek(in, 0, SEEK_SET); relations_func=relations_func_new(process_multipolygons_member, NULL); while ((ib=read_item(in))) { - struct relation_member outer[MEMBER_MAX]; + struct relation_member *outer=NULL; int outer_count=0; - struct relation_member inner[MEMBER_MAX]; + struct relation_member *inner=NULL;; int inner_count=0; long long relid; 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))) { + /* allocate a slot for inner and outer */ + outer = g_malloc0(sizeof(struct relation_member)); + inner = g_malloc0(sizeof(struct relation_member)); + while(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 ++; + /*realloc outer to make space for next */ + outer = g_realloc(outer, sizeof(struct relation_member) * (outer_count +1)); } min_count=0; - while((inner_count < MEMBER_MAX) && (search_relation_member(ib, "inner",&(inner[inner_count]),&min_count))) { + while(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 ++; + /*realloc inner to make space for next */ + inner = g_realloc(inner, sizeof(struct relation_member) * (inner_count +1)); } fprintf(stderr,"Relid %lld: Got %d outer and %d inner\n", relid, outer_count, inner_count); - if(outer == 0) { + if(outer_count == 0) { osm_warning("relation",relid,0,"multipolygon: missing outer member "); continue; } @@ -3082,6 +3085,9 @@ static GList *process_multipolygons_setup(FILE *in, struct relations *relations) 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); + /* clean up*/ + g_free(inner); + g_free(outer); } return multipolygons; } -- cgit v1.2.1 From fa45f14cde72efe75a2c43cccbcb773e8fd3f2cc Mon Sep 17 00:00:00 2001 From: Stefan Wildemann Date: Thu, 1 Aug 2019 00:32:04 +0200 Subject: Move multipolygons to own tempfile, simplify filtering Note: the simpler filtering results in bigger disk space required. But we cannot filter unknown streets early anymore, as they may be required for polygon processing --- navit/maptool/maptool.c | 18 ++++++++++++++---- navit/maptool/misc.c | 12 ++++++++++++ navit/maptool/osm.c | 31 ++++++++++++++----------------- 3 files changed, 40 insertions(+), 21 deletions(-) (limited to 'navit/maptool') diff --git a/navit/maptool/maptool.c b/navit/maptool/maptool.c index b785d14f4..4594c4528 100644 --- a/navit/maptool/maptool.c +++ b/navit/maptool/maptool.c @@ -731,14 +731,18 @@ static void osm_process_multipolygons(struct maptool_params *p, char *suffix) { p->osm.multipolygons=tempfile(suffix,"multipolygons",0); if(!p->osm.multipolygons) return; - relations=tempfile(suffix,"relations", 1); + relations=tempfile(suffix,"multipolygons_out", 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(ways_split_index); + fclose(ways_split); fclose(coords); fclose(relations); fclose(p->osm.multipolygons); + if(!p->keep_tmpfiles) + tempfile_unlink(suffix,"multipolygons"); } static void maptool_dump(struct maptool_params *p, char *suffix) { @@ -748,8 +752,10 @@ static void maptool_dump(struct maptool_params *p, char *suffix) { files[files_count++]="nodes"; if (p->process_ways) files[files_count++]="ways_split"; - if (p->process_relations) + if (p->process_relations) { files[files_count++]="relations"; + files[files_count++]="multipolygons_out"; + } for (i = 0 ; i < files_count ; i++) { FILE *f=tempfile(suffix,files[i],0); if (f) { @@ -833,6 +839,7 @@ static void maptool_assemble_map(struct maptool_params *p, char *suffix, char ** } if(!p->keep_tmpfiles) { tempfile_unlink(suffix,"relations"); + tempfile_unlink(suffix,"multipolygons_out"); tempfile_unlink(suffix,"nodes"); tempfile_unlink(suffix,"ways_split"); tempfile_unlink(suffix,"poly2poi_resolved"); @@ -1024,14 +1031,15 @@ int main(int argc, char **argv) { if (p.process_relations) { osm_process_turn_restrictions(&p, suffix); } - 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.keep_tmpfiles) + tempfile_unlink(suffix,"ways_split_index"); + 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); @@ -1068,6 +1076,8 @@ int main(int argc, char **argv) { exit(0); } if (p.process_relations) { + filenames[filename_count]="multipolygons_out"; + referencenames[filename_count++]=NULL; filenames[filename_count]="relations"; referencenames[filename_count++]=NULL; filenames[filename_count]="towns_poly"; diff --git a/navit/maptool/misc.c b/navit/maptool/misc.c index 1c30b94f7..9b1c72da2 100644 --- a/navit/maptool/misc.c +++ b/navit/maptool/misc.c @@ -213,12 +213,20 @@ int item_order_by_type(enum item_type type) { return max; } +static inline int filter_unknown(struct item_bin * ib) { + if(ignore_unknown && (ib->type==type_point_unkn || ib->type==type_street_unkn || ib->type==type_none)) + return 1; + return 0; +} + static void phase34_process_file(struct tile_info *info, FILE *in, FILE *reference) { struct item_bin *ib; struct attr_bin *a; int max; while ((ib=read_item(in))) { + if(filter_unknown(ib)) + continue; if (ib->type < 0x80000000) processed_nodes++; else @@ -239,6 +247,8 @@ static void phase34_process_file_range(struct tile_info *info, FILE *in, FILE *r int min,max; while ((ib=read_item_range(in, &min, &max))) { + if(filter_unknown(ib)) + continue; if (ib->type < 0x80000000) processed_nodes++; else @@ -278,6 +288,8 @@ static int phase34(struct tile_info *info, struct zip_info *zip_info, FILE **in, void dump(FILE *in) { struct item_bin *ib; while ((ib=read_item(in))) { + if(filter_unknown(ib)) + continue; dump_itembin(ib); } } diff --git a/navit/maptool/osm.c b/navit/maptool/osm.c index 6eab6a903..fa5bde9b1 100644 --- a/navit/maptool/osm.c +++ b/navit/maptool/osm.c @@ -1615,27 +1615,28 @@ void osm_end_relation(struct maptool_osm *osm) { in_relation=0; - if(attr_longest_match(attr_mapping_rel2poly_place, attr_mapping_rel2poly_place_count, &type, 1)) { - tmp_item_bin->type=type; + fprintf(stderr,"relation_type=%s\n", relation_type); + if((!g_strcmp0(relation_type, "multipolygon")) && (!boundary)) { + if(attr_longest_match(attr_mapping_way, attr_mapping_way_count, &type, 1)) { + tmp_item_bin->type = type; + } else { + type=type_none; + tmp_item_bin->type=type; + } } else { - type=type_none; - tmp_item_bin->type=type; + if(attr_longest_match(attr_mapping_rel2poly_place, attr_mapping_rel2poly_place_count, &type, 1)) { + tmp_item_bin->type=type; + } 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_add_attr_string(tmp_item_bin, attr_label, attr_strings[attr_string_label]); 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)) { item_bin_write(tmp_item_bin, osm->boundaries); @@ -1758,8 +1759,6 @@ void osm_end_way(struct maptool_osm *osm) { add_flags=0; if (types[i] == type_none) continue; - if (ignore_unknown && (types[i] == type_street_unkn || types[i] == type_point_unkn)) - continue; if (types[i] != type_street_unkn) { if(types[i] Date: Thu, 1 Aug 2019 01:03:16 +0200 Subject: Fix turn restriction processing --- navit/maptool/osm.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'navit/maptool') diff --git a/navit/maptool/osm.c b/navit/maptool/osm.c index fa5bde9b1..588879d66 100644 --- a/navit/maptool/osm.c +++ b/navit/maptool/osm.c @@ -1621,14 +1621,18 @@ void osm_end_relation(struct maptool_osm *osm) { tmp_item_bin->type = type; } else { type=type_none; - tmp_item_bin->type=type; + /* do not touch tmp_item_bin->type in this case, as it may be already set! For example + * indicating the turn restrictions */ + //tmp_item_bin->type=type; } } else { if(attr_longest_match(attr_mapping_rel2poly_place, attr_mapping_rel2poly_place_count, &type, 1)) { tmp_item_bin->type=type; } else { type=type_none; - tmp_item_bin->type=type; + /* do not touch tmp_item_bin->type in this case, as it may be already set! For example + * indicating the turn restrictions */ + //tmp_item_bin->type=type; } } -- cgit v1.2.1 From c77275205078616e81b1b9324dcc8c5035592d74 Mon Sep 17 00:00:00 2001 From: Stefan Wildemann Date: Thu, 1 Aug 2019 01:16:16 +0200 Subject: Correctly sort multipolygons from boundaries --- navit/maptool/osm.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) (limited to 'navit/maptool') diff --git a/navit/maptool/osm.c b/navit/maptool/osm.c index 588879d66..85bd4b484 100644 --- a/navit/maptool/osm.c +++ b/navit/maptool/osm.c @@ -1625,6 +1625,8 @@ void osm_end_relation(struct maptool_osm *osm) { * indicating the turn restrictions */ //tmp_item_bin->type=type; } + item_bin_add_attr_string(tmp_item_bin, attr_label, attr_strings[attr_string_label]); + item_bin_write(tmp_item_bin, osm->multipolygons); } else { if(attr_longest_match(attr_mapping_rel2poly_place, attr_mapping_rel2poly_place_count, &type, 1)) { tmp_item_bin->type=type; @@ -1634,17 +1636,13 @@ void osm_end_relation(struct maptool_osm *osm) { * indicating the turn restrictions */ //tmp_item_bin->type=type; } + if ((!g_strcmp0(relation_type, "multipolygon") || !g_strcmp0(relation_type, "boundary")) + && (boundary || type!=type_none)) { + item_bin_write(tmp_item_bin, osm->boundaries); + } } - if ((!g_strcmp0(relation_type, "multipolygon")) && (!boundary)) { - item_bin_add_attr_string(tmp_item_bin, attr_label, attr_strings[attr_string_label]); - item_bin_write(tmp_item_bin, osm->multipolygons); - } - if ((!g_strcmp0(relation_type, "multipolygon") || !g_strcmp0(relation_type, "boundary")) - && (boundary || type!=type_none)) { - item_bin_write(tmp_item_bin, osm->boundaries); - } if (!g_strcmp0(relation_type, "restriction") && (tmp_item_bin->type == type_street_turn_restriction_no || tmp_item_bin->type == type_street_turn_restriction_only)) -- cgit v1.2.1 From ef80e7b53bf26f895a5a0a546bd0c02e89517bad Mon Sep 17 00:00:00 2001 From: Wildemann Stefan Date: Thu, 1 Aug 2019 14:33:45 +0200 Subject: fix finding loops in road parts. Remove output --- navit/maptool/osm.c | 65 ++++++++++++++++++++++++++++++----------------------- 1 file changed, 37 insertions(+), 28 deletions(-) (limited to 'navit/maptool') diff --git a/navit/maptool/osm.c b/navit/maptool/osm.c index 85bd4b484..442e44877 100644 --- a/navit/maptool/osm.c +++ b/navit/maptool/osm.c @@ -1615,7 +1615,6 @@ void osm_end_relation(struct maptool_osm *osm) { in_relation=0; - fprintf(stderr,"relation_type=%s\n", relation_type); if((!g_strcmp0(relation_type, "multipolygon")) && (!boundary)) { if(attr_longest_match(attr_mapping_way, attr_mapping_way_count, &type, 1)) { tmp_item_bin->type = type; @@ -2699,7 +2698,7 @@ static int process_multipolygons_find_match(struct item_bin* part,int part_used struct coord *try_first, *try_last; if(parts[i]->clen < 2) { - fprintf(stderr,"skipping single point"); + //fprintf(stderr,"skipping single point"); used[i] = 1; continue; } @@ -2707,20 +2706,16 @@ static int process_multipolygons_find_match(struct item_bin* part,int part_used try_first=(struct coord *)(parts[i] +1); try_last=(struct coord *)(parts[i] +1); try_last+=(parts[i]->clen / 2) - 1; - fprintf(stderr, "0x%x,0x%x try_first[%d] 0x%x,0x%x try_last[%d] 0x%x,0x%x\n",coord->x, coord->y,i,try_first->x, - try_first->y, i, try_last->x, - try_last->y); + //fprintf(stderr, "0x%x,0x%x try_first[%d] 0x%x,0x%x try_last[%d] 0x%x,0x%x\n",coord->x, coord->y,i,try_first->x, + // try_first->y, i, try_last->x, + // try_last->y); if((coord->x == try_first->x) && (coord->y == try_first->y)) { /* forward match */ - //fprintf(stderr,"forward match\n"); have_match=1; } else if((coord->x == try_last->x) && (coord->y == try_last->y)) { - fprintf(stderr,"reverse match\n"); /* reverse match */ have_match=2; - /* copy first to last foor loop check */ - try_last = try_first; } /* add match to sequence */ if(have_match) { @@ -2793,14 +2788,15 @@ static int process_multipolygons_find_loop(int in_count, struct item_bin ** part return 0; } -static int process_multipolygons_find_loops(int in_count, struct item_bin ** parts, int **scount, int *** sequences, +static int process_multipolygons_find_loops(osmid relid, int in_count, struct item_bin ** parts, int **scount, + int *** sequences, int **direction) { int done=0; int loop_count=0; int *used; if((in_count == 0) || (parts == NULL) || (sequences == NULL) || (scount == NULL)) return 0; - fprintf(stderr,"find loops in %d parts\n",in_count); + //fprintf(stderr,"find loops in %d parts\n",in_count); /* start with nothing */ *sequences = NULL; *scount = NULL; @@ -2814,7 +2810,7 @@ static int process_multipolygons_find_loops(int in_count, struct item_bin ** par if(sequence_count < 0) { done = 1; } else if(sequence_count == 0) { - fprintf(stderr,"skipping nonclosed sequence\n"); + osm_warning("relation",relid,0,"multipolygon: skipping non loop sequence\n"); /* skip empty sequence */ g_free(sequence); } else { @@ -2827,7 +2823,7 @@ static int process_multipolygons_find_loops(int in_count, struct item_bin ** par loop_count ++; } } while (!done); - fprintf(stderr,"found %d loops\n", loop_count); + //fprintf(stderr,"found %d loops\n", loop_count); *direction = used; return loop_count; } @@ -2850,16 +2846,20 @@ static int process_multipolygons_loop_dump(struct item_bin** bin, int scount, in if(a!=0) pcount --; if((buffer != NULL) && (direction !=NULL)) { - if(direction[a] == 1) { + if(direction[sequence[a]] == 1) { memcpy(&(buffer[points]), c, pcount * sizeof(struct coord)); } else { int b; struct coord * target = &(buffer[points]); + //fprintf(stderr,"R:"); for (b=0; b < pcount; b ++) { target[b] = c[(bin[sequence[a]]->clen / 2) - b -1]; } } } + //if(buffer !=NULL) { + // fprintf(stderr, "%d (%x, %x)-%d-(%x, %x)\n",sequence[a], buffer[points].x, buffer[points].y, pcount, buffer[points+pcount-1].x, buffer[points+pcount-1].y); + //} points += pcount; } return points; @@ -2877,15 +2877,19 @@ static int process_multipolygons_loop_count(struct item_bin** bin, int scount, i return process_multipolygons_loop_dump(bin,scount,sequence,NULL,NULL); } -static inline void dump_sequence(const char * string, int loop_count, int*scount, int**sequences) { +static inline void dump_sequence(const char * string, int loop_count, int*scount, int**sequences, int*direction) { +#if 0 int i; int j; for(j=0; jouter_count,multipolygon->outer, &outer_scount, + outer_loop_count = process_multipolygons_find_loops(multipolygon->relid, multipolygon->outer_count,multipolygon->outer, + &outer_scount, &outer_sequences, &outer_direction); /* combine inner to full loops */ - inner_loop_count = process_multipolygons_find_loops(multipolygon->inner_count,multipolygon->inner, &inner_scount, + inner_loop_count = process_multipolygons_find_loops(multipolygon->relid, multipolygon->inner_count,multipolygon->inner, + &inner_scount, &inner_sequences, &inner_direction); - dump_sequence("outer",outer_loop_count, outer_scount, outer_sequences); - dump_sequence("inner",inner_loop_count, inner_scount, inner_sequences); + dump_sequence("outer",outer_loop_count, outer_scount, outer_sequences, outer_direction); + dump_sequence("inner",inner_loop_count, inner_scount, inner_sequences, inner_direction); for(b=0; brel); - fprintf(stderr,"process %lld\n", relid); + //long long relid=item_bin_get_relationid(multipolygon->rel); + //fprintf(stderr,"process %lld\n", relid); outer_length = process_multipolygons_loop_count(multipolygon->outer, outer_scount[b], outer_sequences[b]) * sizeof(struct coord); outer_buffer = (struct coord *) g_malloc0(outer_length); @@ -2978,6 +2984,8 @@ static void process_multipolygons_finish(GList *tr, FILE *out) { item_bin_add_attr_range(ib,attr_order,0,order); item_bin_write(ib, out); } + /* just for fun...*/ + processed_relations ++; /* clean up the sequences */ for(a=0; a < outer_loop_count; a ++) g_free (outer_sequences[a]); @@ -3010,8 +3018,8 @@ static void process_multipolygons_member(void *func_priv, void *relation_priv, s 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); + //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 */ @@ -3055,7 +3063,7 @@ static GList *process_multipolygons_setup(FILE *in, struct relations *relations) inner = g_malloc0(sizeof(struct relation_member)); while(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 "); + osm_warning("relation",relid,0,"multipolygon: wrong type for outer member\n"); outer_count ++; /*realloc outer to make space for next */ outer = g_realloc(outer, sizeof(struct relation_member) * (outer_count +1)); @@ -3063,14 +3071,15 @@ static GList *process_multipolygons_setup(FILE *in, struct relations *relations) min_count=0; while(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 "); + osm_warning("relation",relid,0,"multipolygon: wrong type for inner member\n"); inner_count ++; /*realloc inner to make space for next */ inner = g_realloc(inner, sizeof(struct relation_member) * (inner_count +1)); } - fprintf(stderr,"Relid %lld: Got %d outer and %d inner\n", relid, outer_count, inner_count); + //fprintf(stderr,"Relid %lld: Got %d outer and %d inner\n", relid, outer_count, inner_count); if(outer_count == 0) { - osm_warning("relation",relid,0,"multipolygon: missing outer member "); + osm_warning("relation",relid,0,"multipolygon: missing outer member\n"); + continue; } p_multipolygon=g_new0(struct multipolygon, 1); -- cgit v1.2.1 From 8d3e102787aa021027cbe99d240bd81e721b9c27 Mon Sep 17 00:00:00 2001 From: Wildemann Stefan Date: Fri, 2 Aug 2019 17:17:55 +0200 Subject: Remove duplicates from multipolygon processing --- navit/maptool/osm.c | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'navit/maptool') diff --git a/navit/maptool/osm.c b/navit/maptool/osm.c index 442e44877..27bd32cfb 100644 --- a/navit/maptool/osm.c +++ b/navit/maptool/osm.c @@ -3017,7 +3017,13 @@ static void process_multipolygons_member(void *func_priv, void *relation_priv, s void *member_priv) { int type=(long)member_priv; int i; + int * dup; struct multipolygon *multipolygon=relation_priv; + dup=item_bin_get_attr(member,attr_duplicate,NULL); + if(dup != NULL) { + //fprintf(stderr,"skip duplicate \n"); + return; + } //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 */ -- cgit v1.2.1 From 38cc16079fd9f923da483dbcb0b577830927a9ff Mon Sep 17 00:00:00 2001 From: Stefan Wildemann Date: Sun, 4 Aug 2019 13:48:32 +0200 Subject: Multi thread multi polygon processing. Way faster because a) better cpu usage on multicores and b) multiple but smaller hashes that scale O^2 on inserting. They are just O on reading, so the multiple doesn't count that much. And besides that we save main menory as we can process each hash independent. --- navit/maptool/osm.c | 195 ++++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 167 insertions(+), 28 deletions(-) (limited to 'navit/maptool') diff --git a/navit/maptool/osm.c b/navit/maptool/osm.c index 27bd32cfb..3610e4f25 100644 --- a/navit/maptool/osm.c +++ b/navit/maptool/osm.c @@ -3046,21 +3046,24 @@ static void process_multipolygons_member(void *func_priv, void *relation_priv, s } -static GList *process_multipolygons_setup(FILE *in, struct relations *relations) { - 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))) { +/** + * @brief prepare one multipolygon relation for relattion processing + * + * @param ib the relation + * @param relations the relation processing structure + * @param relations_func function to use for the members + * @param multipolygons write the resulting multipolygons to the list + */ +static void process_multipolygons_setup_one(struct item_bin * ib, struct relations * relations, + struct relations_func * relations_func, GList ** multipolygons) { + if(ib != NULL) { struct relation_member *outer=NULL; int outer_count=0; struct relation_member *inner=NULL;; int inner_count=0; long long relid; int a; + int min_count; struct multipolygon *p_multipolygon; relid=item_bin_get_relationid(ib); min_count=0; @@ -3085,35 +3088,171 @@ static GList *process_multipolygons_setup(FILE *in, struct relations *relations) //fprintf(stderr,"Relid %lld: Got %d outer and %d inner\n", relid, outer_count, inner_count); if(outer_count == 0) { osm_warning("relation",relid,0,"multipolygon: missing outer member\n"); - - continue; + } else { + 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); } - 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); /* clean up*/ g_free(inner); g_free(outer); } +} + +/** + * @brief worker thread private storage + */ +struct process_multipolygon_setup_thread { + int number; + GAsyncQueue * queue; + struct relations * relations; + struct relations_func * relations_func; + GList* multipolygons; + GThread * thread; +}; + +/** + * @brief dummy memory location to pass a end condition to worker threads, as NULL cannot be passed. + */ +static struct item_bin killer; + +/** + * @brief multipolygons setup worker thread. + * + * This thread processes any item passed to it via async queue into it's local relations + * function. + * @param data this threads local storage + */ +static gpointer process_multipolygons_setup_worker (gpointer data) { + struct item_bin * ib; + //long long relid; + struct process_multipolygon_setup_thread * me = (struct process_multipolygon_setup_thread*) data; + fprintf(stderr,"worker %d up\n", me->number); + while((ib=g_async_queue_pop (me->queue)) != &killer) { + //relid=item_bin_get_relationid(ib); + //fprintf(stderr,"worker %d processing %lld\n", me->number, relid); + process_multipolygons_setup_one(ib, me->relations, me->relations_func, &(me->multipolygons)); + /* done with that. Free the item_bin */ + g_free(ib); + } + fprintf(stderr,"worker %d exit\n", me->number); + g_thread_exit(NULL); + return NULL; +} + +/** + * @brief prepare multipolygon way matching + * + * This function reads all multipolygon relations and prepares relations structures + * for later way matching. Since this scales quite ugly, (O^3) i think, we use multiple threads + * creating their own hash each. This way none of the hashes get's that big, and we can utilize + * more cpu power. + * + * @param in file containing the relations + * @param thread_count number of threads to use + * @param relations array of preallocated relations structures. One per thread. + * + * @returns array of GLists. One per thread containing the resulting structures. + */ +static GList ** process_multipolygons_setup(FILE *in, int thread_count, struct relations **relations) { + struct process_multipolygon_setup_thread *sthread; + + struct item_bin *ib; + struct relations_func *relations_func; + int i; + GList **multipolygons=NULL; + /* allocate and reference async queue */ + GAsyncQueue * ib_queue=g_async_queue_new (); + g_async_queue_ref(ib_queue); + /* allocate per thread storage */ + sthread=g_malloc0(sizeof(struct process_multipolygon_setup_thread) * thread_count); + + fseek(in, 0, SEEK_SET); + relations_func=relations_func_new(process_multipolygons_member, NULL); + + /* start the threads */ + for(i=0; i < thread_count; i ++) { + sthread[i].number = i; + sthread[i].queue = ib_queue; + sthread[i].relations_func = relations_func; + sthread[i].relations = relations[i]; + sthread[i].multipolygons = NULL; + sthread[i].thread = g_thread_new ("process_multipolygons_setup_worker", process_multipolygons_setup_worker, + &(sthread[i])); + } + + while ((ib=read_item(in))) { + /* get a duplicate of the returned item, as the one returned shares buffer */ + struct item_bin * dup = item_bin_dup(ib); + //long long relid; + //relid=item_bin_get_relationid(dup); + //fprintf(stderr,"Pushing %lld\n", relid); + /* the dup's will be freed by the thread processing them*/ + g_async_queue_push(ib_queue,dup); + /* limit queue size. This is ugly, but since GAsyncQueue doesn't support + * push to block when the queue reached a decent size, I help myself + * with this ugly hack */ + while(g_async_queue_length(ib_queue) > 1000) + usleep(200); + } + + /* stop iand join all remaining threads */ + for(i = 0; i < thread_count; i ++) + g_async_queue_push(ib_queue,&killer); + for(i=0; i < thread_count; i ++) + g_thread_join(sthread[i].thread); + + /* rescue the resulting glist */ + multipolygons = g_malloc0(sizeof(GList *) * thread_count); + for(i =0; i < thread_count; i ++) + multipolygons[i]=sthread[i].multipolygons; + + /* free the thread storage */ + g_free(sthread); + + /* release the queue */ + g_async_queue_unref(ib_queue); + + /* return the list of multipolygons */ return multipolygons; } void process_multipolygons(FILE *in, FILE *coords, FILE *ways, FILE *ways_index, FILE *out) { - struct relations *relations=relations_new(); - GList *multipolygons; + int thread_count = 4; + int i; + struct relations **relations; + GList **multipolygons = NULL; + + relations = g_malloc0(sizeof(struct relations *) * thread_count); + for(i=0; i < thread_count; i ++) + relations[i] = relations_new(); fseek(in, 0, SEEK_SET); - multipolygons=process_multipolygons_setup(in, relations); - relations_process(relations, coords, ways); - process_multipolygons_finish(multipolygons, out); - relations_destroy(relations); + multipolygons=process_multipolygons_setup(in,thread_count,relations); + /* Here we get an array of resulting relations structures and resultin + * GLists. + * Of course we need to iterate the ways multiple times, but that's fast + * compared to hashing the relations structures + * This even saves a lot of main memory, as we can process every result from + * every thread at once completely. Since we know it's self containing + */ + for( i=0; i < thread_count; i ++) { + if(coords) + fseek(coords, 0,SEEK_SET); + if(ways) + fseek(ways, 0,SEEK_SET); + relations_process(relations[i], coords, ways); + process_multipolygons_finish(multipolygons[i], out); + relations_destroy(relations[i]); + } + g_free(relations); } struct turn_restriction { -- cgit v1.2.1 From 72d975cb9677c96e9316dfe8705a90bff3d50fe6 Mon Sep 17 00:00:00 2001 From: Stefan Wildemann Date: Sun, 4 Aug 2019 20:50:35 +0200 Subject: Add T parameter to maptool commandline. Optimize multipolygon speed --- navit/maptool/maptool.c | 17 ++++++++++++----- navit/maptool/maptool.h | 1 + navit/maptool/osm.c | 7 +++++-- 3 files changed, 18 insertions(+), 7 deletions(-) (limited to 'navit/maptool') diff --git a/navit/maptool/maptool.c b/navit/maptool/maptool.c index 4594c4528..12aa50eda 100644 --- a/navit/maptool/maptool.c +++ b/navit/maptool/maptool.c @@ -52,6 +52,7 @@ long long slice_size=SLIZE_SIZE_DEFAULT_GB*1024ll*1024*1024; int attr_debug_level=1; int ignore_unknown = 0; +int thread_count=8; /* good default even on single cores */ GHashTable *dedupe_ways_hash; int phase; int slices; @@ -301,6 +302,7 @@ static void usage(void) { "-S (--slice-size) : limit memory to use for some large internal buffers, in bytes. Default is %dGB.\n", SLIZE_SIZE_DEFAULT_GB); fprintf(f,"-t (--timestamp) : Set zip timestamp\n"); + fprintf(f,"-T (--threads) : Set number of threads (for some operations)\n"); fprintf(f, "-w (--dedupe-ways) : ensure no duplicate ways or nodes. useful when using several input files\n"); fprintf(f,"-W (--ways-only) : process only ways\n"); @@ -377,6 +379,7 @@ static int parse_option(struct maptool_params *p, char **argv, int argc, int *op {"protobuf", 0, 0, 'P'}, {"start", 1, 0, 's'}, {"timestamp", 1, 0, 't'}, + {"threads", 1, 0, 'T'}, {"input-file", 1, 0, 'i'}, {"rule-file", 1, 0, 'r'}, {"ignore-unknown", 0, 0, 'n'}, @@ -391,7 +394,7 @@ static int parse_option(struct maptool_params *p, char **argv, int argc, int *op #ifdef HAVE_POSTGRESQL "d:" #endif - "e:hi:knm:p:r:s:t:wu:z:Ux:", long_options, option_index); + "e:hi:knm:p:r:s:t:T:wu:z:Ux:", long_options, option_index); if (c == -1) return 1; switch (c) { @@ -493,6 +496,9 @@ static int parse_option(struct maptool_params *p, char **argv, int argc, int *op case 't': p->timestamp=optarg; break; + case 'T': + thread_count=atoi(optarg); + break; case 'w': dedupe_ways_hash=g_hash_table_new(NULL, NULL); break; @@ -727,18 +733,19 @@ static void osm_process_turn_restrictions(struct maptool_params *p, char *suffix } static void osm_process_multipolygons(struct maptool_params *p, char *suffix) { - FILE *ways_split, *ways_split_index, *relations, *coords; + FILE *ways_split, *ways_split_index, *relations/*, *coords*/; p->osm.multipolygons=tempfile(suffix,"multipolygons",0); if(!p->osm.multipolygons) return; relations=tempfile(suffix,"multipolygons_out", 1); - coords=fopen("coords.tmp", "rb"); + /* no coords in multipolygons. */ + //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); + process_multipolygons(p->osm.multipolygons,/*coords*/NULL,ways_split,ways_split_index,relations); fclose(ways_split_index); fclose(ways_split); - fclose(coords); + //fclose(coords); fclose(relations); fclose(p->osm.multipolygons); if(!p->keep_tmpfiles) diff --git a/navit/maptool/maptool.h b/navit/maptool/maptool.h index aef344031..f0aee6fdf 100644 --- a/navit/maptool/maptool.h +++ b/navit/maptool/maptool.h @@ -235,6 +235,7 @@ extern struct item_bin *tmp_item_bin; /* maptool.c */ extern long long slice_size; +extern int thread_count; extern int attr_debug_level; extern char *suffix; extern int ignore_unknown; diff --git a/navit/maptool/osm.c b/navit/maptool/osm.c index 3610e4f25..2ec3ec667 100644 --- a/navit/maptool/osm.c +++ b/navit/maptool/osm.c @@ -2894,7 +2894,7 @@ static inline void dump_sequence(const char * string, int loop_count, int*scount static void process_multipolygons_finish(GList *tr, FILE *out) { GList *l=tr; - fprintf(stderr,"process_multipolygons_finish\n"); + //fprintf(stderr,"process_multipolygons_finish\n"); while(l) { int a; int b; @@ -3226,7 +3226,7 @@ static GList ** process_multipolygons_setup(FILE *in, int thread_count, struct r } void process_multipolygons(FILE *in, FILE *coords, FILE *ways, FILE *ways_index, FILE *out) { - int thread_count = 4; + /* thread count is from maptool.c as commandline parameter */ int i; struct relations **relations; GList **multipolygons = NULL; @@ -3235,6 +3235,7 @@ void process_multipolygons(FILE *in, FILE *coords, FILE *ways, FILE *ways_index, for(i=0; i < thread_count; i ++) relations[i] = relations_new(); fseek(in, 0, SEEK_SET); + fprintf(stderr,"process_multipolygons:setup (threads %d)\n", thread_count); multipolygons=process_multipolygons_setup(in,thread_count,relations); /* Here we get an array of resulting relations structures and resultin * GLists. @@ -3248,7 +3249,9 @@ void process_multipolygons(FILE *in, FILE *coords, FILE *ways, FILE *ways_index, fseek(coords, 0,SEEK_SET); if(ways) fseek(ways, 0,SEEK_SET); + fprintf(stderr,"process_multipolygons:process (thread %d)\n", i); relations_process(relations[i], coords, ways); + fprintf(stderr,"process_multipolygons:finish (thread %d)\n", i); process_multipolygons_finish(multipolygons[i], out); relations_destroy(relations[i]); } -- cgit v1.2.1 From 95d1a69425d3d6d616e7402c58fb6d2869a1a16d Mon Sep 17 00:00:00 2001 From: Stefan Wildemann Date: Sun, 4 Aug 2019 21:17:06 +0200 Subject: Add progress display for multipolygon processing --- navit/maptool/osm.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'navit/maptool') diff --git a/navit/maptool/osm.c b/navit/maptool/osm.c index 2ec3ec667..426236bbc 100644 --- a/navit/maptool/osm.c +++ b/navit/maptool/osm.c @@ -3040,6 +3040,7 @@ static void process_multipolygons_member(void *func_priv, void *relation_priv, s multipolygon->outer[multipolygon->outer_count]=item_bin_dup(member); multipolygon->outer_count ++; } + processed_ways ++; i=item_order_by_type(member->type); if(iorder) multipolygon->order=i; @@ -3137,6 +3138,7 @@ static gpointer process_multipolygons_setup_worker (gpointer data) { struct process_multipolygon_setup_thread * me = (struct process_multipolygon_setup_thread*) data; fprintf(stderr,"worker %d up\n", me->number); while((ib=g_async_queue_pop (me->queue)) != &killer) { + processed_relations ++; //relid=item_bin_get_relationid(ib); //fprintf(stderr,"worker %d processing %lld\n", me->number, relid); process_multipolygons_setup_one(ib, me->relations, me->relations_func, &(me->multipolygons)); @@ -3230,6 +3232,7 @@ void process_multipolygons(FILE *in, FILE *coords, FILE *ways, FILE *ways_index, int i; struct relations **relations; GList **multipolygons = NULL; + sig_alrm(0); relations = g_malloc0(sizeof(struct relations *) * thread_count); for(i=0; i < thread_count; i ++) @@ -3244,6 +3247,10 @@ void process_multipolygons(FILE *in, FILE *coords, FILE *ways, FILE *ways_index, * This even saves a lot of main memory, as we can process every result from * every thread at once completely. Since we know it's self containing */ + sig_alrm(0); + processed_relations=0; + processed_ways=0; + sig_alrm(0); for( i=0; i < thread_count; i ++) { if(coords) fseek(coords, 0,SEEK_SET); @@ -3256,6 +3263,8 @@ void process_multipolygons(FILE *in, FILE *coords, FILE *ways, FILE *ways_index, relations_destroy(relations[i]); } g_free(relations); + sig_alrm(0); + sig_alrm_end(); } struct turn_restriction { -- cgit v1.2.1 From d4f73645a62d9f93cb5ae123fe2cf44c9922df41 Mon Sep 17 00:00:00 2001 From: Wildemann Stefan Date: Tue, 6 Aug 2019 10:23:20 +0200 Subject: Make 64 bit zip default. This is baraindead. Lost days of computing time because getting invalid zip files at the end because of being too big. Make 64 bit zips the default. Neccessary for big maps anyway, and shouldn't hurt on small files. --- navit/maptool/maptool.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'navit/maptool') diff --git a/navit/maptool/maptool.c b/navit/maptool/maptool.c index 12aa50eda..e89726a0b 100644 --- a/navit/maptool/maptool.c +++ b/navit/maptool/maptool.c @@ -279,7 +279,8 @@ static void usage(void) { fprintf(f,"maptool --protobuf -i planet.osm.pbf planet.bin\n"); fprintf(f,"Available switches:\n"); fprintf(f,"-h (--help) : this screen\n"); - fprintf(f,"-6 (--64bit) : set zip 64 bit compression\n"); + fprintf(f,"-3 (--32bit) : set zip 32 bit compression\n"); + fprintf(f,"-6 (--64bit) : set zip 64 bit compression (default)\n"); fprintf(f,"-a (--attr-debug-level) : control which data is included in the debug attribute\n"); fprintf(f,"-c (--dump-coordinates) : dump coordinates after phase 1\n"); #ifdef HAVE_POSTGRESQL @@ -358,6 +359,7 @@ static int parse_option(struct maptool_params *p, char **argv, int argc, int *op int pos,c,i; static struct option long_options[] = { + {"32bit", 0, 0, '3'}, {"64bit", 0, 0, '6'}, {"attr-debug-level", 1, 0, 'a'}, {"binfile", 0, 0, 'b'}, @@ -398,6 +400,9 @@ static int parse_option(struct maptool_params *p, char **argv, int argc, int *op if (c == -1) return 1; switch (c) { + case '3': + p->zip64=0; + break; case '6': p->zip64=1; break; @@ -923,6 +928,7 @@ int main(int argc, char **argv) { linguistics_init(); memset(&p, 0, sizeof(p)); + p.zip64=1; /* default to 64 bit zip */ #ifdef HAVE_ZLIB p.compression_level=9; #endif -- cgit v1.2.1 From c28e1e247350bd97cb6629f751fe15f6901ed5fc Mon Sep 17 00:00:00 2001 From: Wildemann Stefan Date: Tue, 6 Aug 2019 11:30:55 +0200 Subject: Add forgotten new parameter -3 to list of parameters. --- navit/maptool/maptool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'navit/maptool') diff --git a/navit/maptool/maptool.c b/navit/maptool/maptool.c index e89726a0b..9c00a9c13 100644 --- a/navit/maptool/maptool.c +++ b/navit/maptool/maptool.c @@ -392,7 +392,7 @@ static int parse_option(struct maptool_params *p, char **argv, int argc, int *op {"index-size", 0, 0, 'x'}, {0, 0, 0, 0} }; - c = getopt_long (argc, argv, "6B:DEMNO:PS:Wa:bc" + c = getopt_long (argc, argv, "36B:DEMNO:PS:Wa:bc" #ifdef HAVE_POSTGRESQL "d:" #endif -- cgit v1.2.1 From 671040867f1b4208948f90058212af6f567c5efe Mon Sep 17 00:00:00 2001 From: Wildemann Stefan Date: Tue, 6 Aug 2019 11:41:13 +0200 Subject: Remove manual setting of order tag on multipolygons Should not be neccesary. --- navit/maptool/osm.c | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'navit/maptool') diff --git a/navit/maptool/osm.c b/navit/maptool/osm.c index 426236bbc..41a1d2d20 100644 --- a/navit/maptool/osm.c +++ b/navit/maptool/osm.c @@ -2667,7 +2667,6 @@ struct multipolygon { int outer_count; struct item_bin ** inner; struct item_bin ** outer; - int order; }; /** @@ -2924,7 +2923,6 @@ static void process_multipolygons_finish(GList *tr, FILE *out) { for(b=0; b multipolygon->order) - order=multipolygon->order; - - item_bin_add_attr_range(ib,attr_order,0,order); item_bin_write(ib, out); } /* just for fun...*/ @@ -3041,10 +3033,6 @@ static void process_multipolygons_member(void *func_priv, void *relation_priv, s multipolygon->outer_count ++; } processed_ways ++; - i=item_order_by_type(member->type); - if(iorder) - multipolygon->order=i; - } /** @@ -3092,7 +3080,6 @@ static void process_multipolygons_setup_one(struct item_bin * ib, struct relatio } else { 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, -- cgit v1.2.1 From ac1a11af00bc62894b3208dadd0fab0a112da575 Mon Sep 17 00:00:00 2001 From: Wildemann Stefan Date: Tue, 6 Aug 2019 11:44:34 +0200 Subject: Remove unused variables --- navit/maptool/osm.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'navit/maptool') diff --git a/navit/maptool/osm.c b/navit/maptool/osm.c index 41a1d2d20..88d5be859 100644 --- a/navit/maptool/osm.c +++ b/navit/maptool/osm.c @@ -2923,7 +2923,6 @@ static void process_multipolygons_finish(GList *tr, FILE *out) { for(b=0; b Date: Wed, 7 Aug 2019 12:51:59 +0200 Subject: Refactor polygon processing for CodeFactor --- navit/maptool/osm.c | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'navit/maptool') diff --git a/navit/maptool/osm.c b/navit/maptool/osm.c index 88d5be859..9fbc36251 100644 --- a/navit/maptool/osm.c +++ b/navit/maptool/osm.c @@ -1609,39 +1609,40 @@ country_from_iso2(char *iso) { return country_from_countryid(country_id_from_iso2(iso)); } - -void osm_end_relation(struct maptool_osm *osm) { - enum item_type type; - - in_relation=0; - +static inline void osm_end_relation_multipolygon (struct maptool_osm * osm, enum item_type* type) { if((!g_strcmp0(relation_type, "multipolygon")) && (!boundary)) { - if(attr_longest_match(attr_mapping_way, attr_mapping_way_count, &type, 1)) { - tmp_item_bin->type = type; + if(attr_longest_match(attr_mapping_way, attr_mapping_way_count, type, 1)) { + tmp_item_bin->type = *type; } else { - type=type_none; + *type=type_none; /* do not touch tmp_item_bin->type in this case, as it may be already set! For example * indicating the turn restrictions */ - //tmp_item_bin->type=type; + //tmp_item_bin->type=*type; } item_bin_add_attr_string(tmp_item_bin, attr_label, attr_strings[attr_string_label]); item_bin_write(tmp_item_bin, osm->multipolygons); } else { - if(attr_longest_match(attr_mapping_rel2poly_place, attr_mapping_rel2poly_place_count, &type, 1)) { - tmp_item_bin->type=type; + if(attr_longest_match(attr_mapping_rel2poly_place, attr_mapping_rel2poly_place_count, type, 1)) { + tmp_item_bin->type=*type; } else { - type=type_none; + *type=type_none; /* do not touch tmp_item_bin->type in this case, as it may be already set! For example * indicating the turn restrictions */ - //tmp_item_bin->type=type; + //tmp_item_bin->type=*type; } if ((!g_strcmp0(relation_type, "multipolygon") || !g_strcmp0(relation_type, "boundary")) - && (boundary || type!=type_none)) { + && (boundary || *type!=type_none)) { item_bin_write(tmp_item_bin, osm->boundaries); } } +} +void osm_end_relation(struct maptool_osm *osm) { + enum item_type type; + in_relation=0; + /* sets tmp_item_bin type and other fields */ + osm_end_relation_multipolygon (osm, &type); if (!g_strcmp0(relation_type, "restriction") && (tmp_item_bin->type == type_street_turn_restriction_no || tmp_item_bin->type == type_street_turn_restriction_only)) @@ -2055,6 +2056,7 @@ static void osm_process_town_by_boundary_update_attrs(struct item_bin *town, str case 'M': /* Here we patch the boundary itself to convert it to town polygon later*/ b->ib->type=type_poly_place6; + /*fall through*/ case 'm': attr_type=attr_municipality_name; break; -- cgit v1.2.1