def get_osm_buildings_and_barrier_ways(code_departement, code_commune): """ Retourne un objet Osm contenant tout les ways de la commune correspondant au buildings et au barrier.""" merge_osm = Osm({}) input_osms = [ open_osm_ways_commune(code_departement, code_commune, "building", nodes=True), open_osm_multipolygon_s_ways_commune(code_departement, code_commune, "building", nodes=True), open_osm_ways_commune(code_departement, code_commune, "barrier", nodes=True), ] for osm in input_osms: for id,node in osm.nodes.iteritems(): if not id in merge_osm.nodes: merge_osm.add_node(node) for id, way in osm.ways.iteritems(): if any([nid not in osm.nodes for nid in way.nodes]): # Il manque des nodes à ce way, ça arrive parfois # dans les résultats d'overpass, je ne sais pas pourquoi # mais cela ferait bugger l'utilisation de ce way # donc on le zap: continue if not id in merge_osm.ways: merge_osm.add_way(way) for id, rel in osm.ways.iteritems(): if not id in merge_osm.relations: merge_osm.add_relation(rel) return merge_osm
def get_osm_buildings_and_barrier_ways(code_departement, code_commune): """ Retourne un objet Osm contenant tout les ways de la commune correspondant au buildings et au barrier.""" merge_osm = Osm({}) input_osms = [ open_osm_ways_commune(code_departement, code_commune, "building", nodes=True), open_osm_multipolygon_s_ways_commune(code_departement, code_commune, "building", nodes=True), open_osm_ways_commune(code_departement, code_commune, "barrier", nodes=True), ] for osm in input_osms: for id, node in osm.nodes.iteritems(): if not id in merge_osm.nodes: merge_osm.add_node(node) for id, way in osm.ways.iteritems(): if any([nid not in osm.nodes for nid in way.nodes]): # Il manque des nodes à ce way, ça arrive parfois # dans les résultats d'overpass, je ne sais pas pourquoi # mais cela ferait bugger l'utilisation de ce way # donc on le zap: continue if not id in merge_osm.ways: merge_osm.add_way(way) for id, rel in osm.ways.iteritems(): if not id in merge_osm.relations: merge_osm.add_relation(rel) return merge_osm
def partitionnement_osm_associatedStreet_zip(osm, zip_filename, subdir=""): """ partitionnement du fichier osm: - par rue pour les numéros associés à une seule rue - par k-moyenne pour les numéros orphelins, ambigus ou les quartiers. """ filename_osm_map = {} if subdir: subdir += "/" # FIXME: le découpage fait ici ne marche qu'avec les restriction suposée # sur le fichier d'entrée, cad avec que: # - des nouveau node addr:housenumber ou place # - des nouvelle relations type=associatedStreet # - des ways extraits d'osm potentiellement modifiés # - des node extraits d'osm non modifiés # Cherche la relation associatedStreet de chaque nouveau node # addr:housenumber: associatedStreet_of_housenumber_node = {} for n in osm.nodes.itervalues(): if n.id() < 0 : if "addr:housenumber" in n.tags: associatedStreet_of_housenumber_node[n.id()] = [] else: assert(("place" in n.tags) or ("highway" in n.tags)) else: # le code actuel ne sait partitionner que des neuds addr:housenumber que l'on a # créé nous même (id<0) # les autres on vas les zapper donc on vérifie qu'il # s'agit bien d'un noeuds déjà existant dans OSM (id >=0) et # non modifié (pas d'attribut action) assert(n.id() >= 0 and "action" not in n.attrs) for r in osm.relations.itervalues(): if r.id() < 0 and r.tags.get("type") == "associatedStreet": for mtype,mref,mrole in r.itermembers(): if mtype == 'node': associatedStreet_of_housenumber_node[mref].append(r) else: # le code actuel ne sait partitionner que les relation # associatedStreet que l'on a créé nous même (id<0) # les autres on vas les zapper donc on vérifie qu'il # s'agit bien de relation déjà existantt dans OSM (id >=0) et # non modifié (pas d'attribut action) assert(r.id() >= 0 and "action" not in r.attrs) # Cree un fichier par relation associatedStreet: for r in osm.relations.itervalues(): if r.id() < 0 and r.tags.get('type') == "associatedStreet": street_osm = Osm({}) street_relation = Relation(r.attrs.copy(), r.tags.copy()) street_osm.add_relation(street_relation) for mtype,mref,mrole in r.itermembers(): if mrole == 'house': assert(mtype == 'node') if len(associatedStreet_of_housenumber_node[mref]) == 1: node = osm.nodes[mref] street_osm.add_node(node) street_relation.add_member(node, mrole) else: street_relation.add_member_type_ref_role(mtype, mref, mrole) filename = subdir + to_ascii(r.tags['name']) + ".osm" filename_osm_map[filename] = street_osm # Partitionne les noeuds ambigus noeuds_ambigus = [osm.nodes[i] for i in associatedStreet_of_housenumber_node.iterkeys() if len(associatedStreet_of_housenumber_node[i]) > 1] filename_osm_map.update(partitionnement_osm_nodes_filename_map(noeuds_ambigus, subdir + "_AMBIGUS_")) # Partitionne les noeuds orphelins noeuds_orphelins = [osm.nodes[i] for i in associatedStreet_of_housenumber_node.iterkeys() if len(associatedStreet_of_housenumber_node[i]) == 0] filename_osm_map.update(partitionnement_osm_nodes_filename_map(noeuds_orphelins, subdir + "_ORPHELINS_")) # Partitionne les noeuds de quartiers (place=neighbourhood): noeuds_quartiers = [n for n in osm.nodes.itervalues() if (n.id()<0) and ("place" in n.tags)] osms_quartiers = partitionnement_osm_nodes_filename_map(noeuds_quartiers, subdir + "_QUARTIERS_") filename_osm_map.update(osms_quartiers) # Partitionne les noeuds de rue (highway=): noeuds_rues = [n for n in osm.nodes.itervalues() if (n.id()<0) and ("highway" in n.tags)] osms_rues = partitionnement_osm_nodes_filename_map(noeuds_rues, subdir + "_ADRESSES_RESSEMBLANTS_NOM_DE_RUE_") for filename, new_osm in osms_rues.iteritems(): new_osm.attrs["upload"] = "false" filename_osm_map.update(osms_rues) # Avec l'intégration des addr:housenumber au buildings, le fichier d'entrée # contiens peut-être aussi des way issue d'OSM qui ont été modifiés. # On vas donc essayer de répartir ces ways dans le partitionnement, mais # cela est possible que si le way est utilisé dans une seule partition (un # seul fichier). filenames_of_new_nodes = {} for filename, new_osm in filename_osm_map.iteritems(): for n in new_osm.nodes.itervalues(): if n.id() < 0: if not n.id() in filenames_of_new_nodes: filenames_of_new_nodes[n.id()] = set() filenames_of_new_nodes[n.id()].add(filename) for way in osm.ways.itervalues(): assert(way.id() >= 0) if "action" in way.attrs: filenames_of_way = set() for nid in way.nodes: if nid < 0: filenames_of_way.update(filenames_of_new_nodes[nid]) if len(filenames_of_way) == 1: # Ajoute le way dans le seul fichier: way_new_osm = filename_osm_map[filenames_of_way.pop()] for nid in way.nodes: if not nid in way_new_osm.nodes: node = osm.nodes[nid] way_new_osm.add_node(node) way_new_osm.add_way(way) elif len(filenames_of_way) > 1: # On ne duplique pas la version modifié du way # On rajoute donc un fixme vers ses neuds pour indiquer # qu'il faudrait les intégrer au way manuellement: for nid in way.nodes: if nid<0: node = osm.nodes[nid] if "fixme" in node.tags: node.tags["fixme"] += " et " + FIXME_JOINDRE_NOEUD_AU_WAY else: node.tags["fixme"] = FIXME_JOINDRE_NOEUD_AU_WAY zip_output = zipfile.ZipFile(zip_filename,"w", zipfile.ZIP_DEFLATED) for filename, osm in filename_osm_map.iteritems(): s = StringIO() OsmWriter(osm).write_to_stream(s) zip_output.writestr(filename, s.getvalue()) zip_output.close()
def generate_osm_adresses(parcelles, numeros_restant, transform): osm = Osm({'upload':'false'}) # Numéros dont on a pas trouvé la parcelle associée (et donc la rue) for n in numeros_restant: if n: num, position, angle = n node = osm_add_point(osm, position, transform) node.tags['fixme'] = u"à vérifier et associer à la bonne rue" node.tags['addr:housenumber'] = num node.tags['source'] = SOURCE_TAG node.angle = angle node.limite_parcelle = None associatedStreets = {} # Adresse des parcelles: for parcelle in parcelles.itervalues(): for num in parcelle.positions_numeros.keys(): for i in range(len(parcelle.addrs_numeros[num])): #nom_parcelle = parcelle.fid[5:10].lstrip('0') + " " + parcelle.fid[10:].lstrip('0') num_parcelle = parcelle.fid[10:].lstrip('0') fixme = [] if len(parcelle.positions_numeros[num]) > i: position, angle = parcelle.positions_numeros[num][i] # le numéro est souvent dessiné en dehors des limites # de la parcelle, si c'est le cas et qu'il est proche des limites, # on le déplace sur la limite: if hasattr(parcelle,'limite') and \ (parcelle.limite != None) and \ (not position.within(parcelle.limite)) and \ (position.distance(parcelle.limite) < 2): boundary = parcelle.limite.boundary position = boundary.interpolate(boundary.project(position)) else: # on ne connait pas la position du numéro # de cette adresse de la parcelle. # on la fixe sur le label de la parcelle: position = Point(parcelle.libellex, parcelle.libelley) # Pour les petites parcelles, le label est parfois en dehors # de la parcelle, si c'est le cas on le déplace # au centre de la parcelle: if not position.within(parcelle.box): position = parcelle.box.centroid fixme.append(u"position à preciser, parcelle associée: n°" + num_parcelle) angle = None node = osm_add_point(osm, position, transform) node.angle = angle if hasattr(parcelle,'limite'): node.limite_parcelle = parcelle.limite else: node.limite_parcelle = None node.tags['addr:housenumber'] = num node.tags['source'] = SOURCE_TAG rues = [addr[len(num)+1:].strip() for addr in parcelle.addrs_numeros[num]] for rue in rues: if not associatedStreets.has_key(rue): rel = Relation({}) rel.tags['type'] = 'associatedStreet' rel.tags['name'] = rue osm.add_relation(rel) associatedStreets[rue] = rel associatedStreets[rue].add_member(node, 'house') if len(rues) > 1: fixme.append(u"choisir la bonne rue: " + " ou ".join(rues)) if hasattr(parcelle,'limite') and parcelle.limite != None: limite = parcelle.limite else: limite = parcelle.box distance = position.distance(limite) if distance > 10: fixme.append(str(int(distance)) + u" m de la parcelle n°" + num_parcelle + u": vérifier la position et/ou la rue associée") fixme.reverse() if fixme: node.tags['fixme'] = " et ".join(fixme) # Cherche les nom de lieus: toutes les adresse sans numéro qui ne sont pas des nom de rue: positions_des_lieus = {} for parcelle in parcelles.itervalues(): for addr in parcelle.adresses: numero_match = RE_NUMERO_CADASTRE.match(addr) if addr and (not numero_match) and (not associatedStreets.has_key(addr)): if not positions_des_lieus.has_key(addr): positions_des_lieus[addr] = [] if hasattr(parcelle,'limite') and parcelle.limite != None: centroid = parcelle.limite.centroid if centroid.wkt == 'GEOMETRYCOLLECTION EMPTY': # Pour la ville de Kingersheim (68), il existe une limite de parcelle # aplatie (sur une ligne, donc d'area nulle) ce qui lui donne # un centroid vide. # On utilise alors le centre des points composant sa limite exteieur centroid = parcelle.limite.exterior.centroid positions_des_lieus[addr].append(centroid) else: positions_des_lieus[addr].append(parcelle.box.centroid) for lieu, positions in positions_des_lieus.iteritems(): centre = MultiPoint(positions).centroid node = osm_add_point(osm, centre, transform) node.tags['name'] = lieu node.tags['source'] = SOURCE_TAG if lieu.lower().startswith("hameau "): node.tags['place'] = 'hamlet' else: node.tags['place'] = 'neighbourhood' node.tags['fixme'] = u"à vérifier: lieu créé automatiquement à partir des adresses du coin" return osm
def partitionnement_osm_associatedStreet_zip(osm, zip_filename, subdir=""): """ partitionnement du fichier osm: - par rue pour les numéros associés à une seule rue - par k-moyenne pour les numéros orphelins, ambigus ou les quartiers. """ filename_osm_map = {} if subdir: subdir += "/" # FIXME: le découpage fait ici ne marche qu'avec les restriction suposée # sur le fichier d'entrée, cad avec que: # - des nouveau node addr:housenumber ou place # - des nouvelle relations type=associatedStreet # - des ways extraits d'osm potentiellement modifiés # - des node extraits d'osm non modifiés # Cherche la relation associatedStreet de chaque nouveau node # addr:housenumber: associatedStreet_of_housenumber_node = {} for n in osm.nodes.itervalues(): if n.id() < 0: if "addr:housenumber" in n.tags: associatedStreet_of_housenumber_node[n.id()] = [] else: assert (("place" in n.tags) or ("highway" in n.tags)) else: # le code actuel ne sait partitionner que des neuds addr:housenumber que l'on a # créé nous même (id<0) # les autres on vas les zapper donc on vérifie qu'il # s'agit bien d'un noeuds déjà existant dans OSM (id >=0) et # non modifié (pas d'attribut action) assert (n.id() >= 0 and "action" not in n.attrs) for r in osm.relations.itervalues(): if r.id() < 0 and r.tags.get("type") == "associatedStreet": for mtype, mref, mrole in r.itermembers(): if mtype == 'node': associatedStreet_of_housenumber_node[mref].append(r) else: # le code actuel ne sait partitionner que les relation # associatedStreet que l'on a créé nous même (id<0) # les autres on vas les zapper donc on vérifie qu'il # s'agit bien de relation déjà existantt dans OSM (id >=0) et # non modifié (pas d'attribut action) assert (r.id() >= 0 and "action" not in r.attrs) # Cree un fichier par relation associatedStreet: for r in osm.relations.itervalues(): if r.id() < 0 and r.tags.get('type') == "associatedStreet": street_osm = Osm({}) street_relation = Relation(r.attrs.copy(), r.tags.copy()) street_osm.add_relation(street_relation) for mtype, mref, mrole in r.itermembers(): if mrole == 'house': assert (mtype == 'node') if len(associatedStreet_of_housenumber_node[mref]) == 1: node = osm.nodes[mref] street_osm.add_node(node) street_relation.add_member(node, mrole) else: street_relation.add_member_type_ref_role( mtype, mref, mrole) filename = subdir + to_ascii(r.tags['name']) + ".osm" filename_osm_map[filename] = street_osm # Partitionne les noeuds ambigus noeuds_ambigus = [ osm.nodes[i] for i in associatedStreet_of_housenumber_node.iterkeys() if len(associatedStreet_of_housenumber_node[i]) > 1 ] filename_osm_map.update( partitionnement_osm_nodes_filename_map(noeuds_ambigus, subdir + "_AMBIGUS_")) # Partitionne les noeuds orphelins noeuds_orphelins = [ osm.nodes[i] for i in associatedStreet_of_housenumber_node.iterkeys() if len(associatedStreet_of_housenumber_node[i]) == 0 ] filename_osm_map.update( partitionnement_osm_nodes_filename_map(noeuds_orphelins, subdir + "_ORPHELINS_")) # Partitionne les noeuds de quartiers (place=neighbourhood): noeuds_quartiers = [ n for n in osm.nodes.itervalues() if (n.id() < 0) and ("place" in n.tags) ] osms_quartiers = partitionnement_osm_nodes_filename_map( noeuds_quartiers, subdir + "_QUARTIERS_") filename_osm_map.update(osms_quartiers) # Partitionne les noeuds de rue (highway=): noeuds_rues = [ n for n in osm.nodes.itervalues() if (n.id() < 0) and ("highway" in n.tags) ] osms_rues = partitionnement_osm_nodes_filename_map( noeuds_rues, subdir + "_ADRESSES_RESSEMBLANTS_NOM_DE_RUE_") for filename, new_osm in osms_rues.iteritems(): new_osm.attrs["upload"] = "false" filename_osm_map.update(osms_rues) # Avec l'intégration des addr:housenumber au buildings, le fichier d'entrée # contiens peut-être aussi des way issue d'OSM qui ont été modifiés. # On vas donc essayer de répartir ces ways dans le partitionnement, mais # cela est possible que si le way est utilisé dans une seule partition (un # seul fichier). filenames_of_new_nodes = {} for filename, new_osm in filename_osm_map.iteritems(): for n in new_osm.nodes.itervalues(): if n.id() < 0: if not n.id() in filenames_of_new_nodes: filenames_of_new_nodes[n.id()] = set() filenames_of_new_nodes[n.id()].add(filename) for way in osm.ways.itervalues(): assert (way.id() >= 0) if "action" in way.attrs: filenames_of_way = set() for nid in way.nodes: if nid < 0: filenames_of_way.update(filenames_of_new_nodes[nid]) if len(filenames_of_way) == 1: # Ajoute le way dans le seul fichier: way_new_osm = filename_osm_map[filenames_of_way.pop()] for nid in way.nodes: if not nid in way_new_osm.nodes: node = osm.nodes[nid] way_new_osm.add_node(node) way_new_osm.add_way(way) elif len(filenames_of_way) > 1: # On ne duplique pas la version modifié du way # On rajoute donc un fixme vers ses neuds pour indiquer # qu'il faudrait les intégrer au way manuellement: for nid in way.nodes: if nid < 0: node = osm.nodes[nid] if "fixme" in node.tags: node.tags[ "fixme"] += " et " + FIXME_JOINDRE_NOEUD_AU_WAY else: node.tags["fixme"] = FIXME_JOINDRE_NOEUD_AU_WAY zip_output = zipfile.ZipFile(zip_filename, "w", zipfile.ZIP_DEFLATED) for filename, osm in filename_osm_map.iteritems(): s = StringIO() OsmWriter(osm).write_to_stream(s) zip_output.writestr(filename, s.getvalue()) zip_output.close()
def generate_osm_adresses(parcelles, numeros_restant, transform): osm = Osm({'upload': 'false'}) # Numéros dont on a pas trouvé la parcelle associée (et donc la rue) for n in numeros_restant: if n: num, position, angle = n node = osm_add_point(osm, position, transform) node.tags['fixme'] = u"à vérifier et associer à la bonne rue" node.tags['addr:housenumber'] = num node.tags['source'] = SOURCE_TAG node.angle = angle node.limite_parcelle = None associatedStreets = {} # Adresse des parcelles: for parcelle in parcelles.itervalues(): for num in parcelle.positions_numeros.keys(): for i in range(len(parcelle.addrs_numeros[num])): #nom_parcelle = parcelle.fid[5:10].lstrip('0') + " " + parcelle.fid[10:].lstrip('0') num_parcelle = parcelle.fid[10:].lstrip('0') fixme = [] if len(parcelle.positions_numeros[num]) > i: position, angle = parcelle.positions_numeros[num][i] # le numéro est souvent dessiné en dehors des limites # de la parcelle, si c'est le cas et qu'il est proche des limites, # on le déplace sur la limite: if hasattr(parcelle,'limite') and \ (parcelle.limite != None) and \ (not position.within(parcelle.limite)) and \ (position.distance(parcelle.limite) < 2): boundary = parcelle.limite.boundary position = boundary.interpolate( boundary.project(position)) else: # on ne connait pas la position du numéro # de cette adresse de la parcelle. # on la fixe sur le label de la parcelle: position = Point(parcelle.libellex, parcelle.libelley) # Pour les petites parcelles, le label est parfois en dehors # de la parcelle, si c'est le cas on le déplace # au centre de la parcelle: if not position.within(parcelle.box): position = parcelle.box.centroid fixme.append( u"position à preciser, parcelle associée: n°" + num_parcelle) angle = None node = osm_add_point(osm, position, transform) node.angle = angle if hasattr(parcelle, 'limite'): node.limite_parcelle = parcelle.limite else: node.limite_parcelle = None node.tags['addr:housenumber'] = num node.tags['source'] = SOURCE_TAG rues = [ addr[len(num) + 1:].strip() for addr in parcelle.addrs_numeros[num] ] for rue in rues: if not associatedStreets.has_key(rue): rel = Relation({}) rel.tags['type'] = 'associatedStreet' rel.tags['name'] = rue osm.add_relation(rel) associatedStreets[rue] = rel associatedStreets[rue].add_member(node, 'house') if len(rues) > 1: fixme.append(u"choisir la bonne rue: " + " ou ".join(rues)) if hasattr(parcelle, 'limite') and parcelle.limite != None: limite = parcelle.limite else: limite = parcelle.box distance = position.distance(limite) if distance > 10: fixme.append( str(int(distance)) + u" m de la parcelle n°" + num_parcelle + u": vérifier la position et/ou la rue associée") fixme.reverse() if fixme: node.tags['fixme'] = " et ".join(fixme) # Cherche les nom de lieus: toutes les adresse sans numéro qui ne sont pas des nom de rue: positions_des_lieus = {} for parcelle in parcelles.itervalues(): for addr in parcelle.adresses: numero_match = RE_NUMERO_CADASTRE.match(addr) if addr and (not numero_match) and ( not associatedStreets.has_key(addr)): if not positions_des_lieus.has_key(addr): positions_des_lieus[addr] = [] if hasattr(parcelle, 'limite') and parcelle.limite != None: centroid = parcelle.limite.centroid if centroid.wkt == 'GEOMETRYCOLLECTION EMPTY': # Pour la ville de Kingersheim (68), il existe une limite de parcelle # aplatie (sur une ligne, donc d'area nulle) ce qui lui donne # un centroid vide. # On utilise alors le centre des points composant sa limite exteieur centroid = parcelle.limite.exterior.centroid positions_des_lieus[addr].append(centroid) else: positions_des_lieus[addr].append(parcelle.box.centroid) for lieu, positions in positions_des_lieus.iteritems(): centre = MultiPoint(positions).centroid node = osm_add_point(osm, centre, transform) node.tags['name'] = lieu node.tags['source'] = SOURCE_TAG if lieu.lower().startswith("hameau "): node.tags['place'] = 'hamlet' else: node.tags['place'] = 'neighbourhood' node.tags[ 'fixme'] = u"à vérifier: lieu créé automatiquement à partir des adresses du coin" return osm