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