/*** * Part of the SWITCH Project * Author: Nathan Coisne, code inspired from Patrick Taillandier * Tags: gis, OSM data ***/ model switch_utilities_gis /* * Genere les fichiers buildings.shp et roads.shp pour la ville de Marseille * * Données requises pour générer les fichiers buildings.shp et roads.shp d'une ville quelconque : * https://download.geofabrik.de/europe/france.html pour le shp 'initial' des builings * https://geoservices.ign.fr/documentation/diffusion/telechargement-donnees-libres.html#bd-topo pour le shapefile à partir duquel on extrait les attributs qu'on donne aux buildings initiaux * Les frontières de la zone considérée * */ global { string dataset_path <- "../includes/Marseille/"; //define the bounds of the studied area file data_file <-shape_file(dataset_path + "boundary_Marseille.shp"); //define the initial building shapefile, extracted from OSM database file shape_file_buildings <- shape_file(dataset_path + "buildings_marseille.shp"); //define the OSM points of interest buildings, for more types file shape_file_pois <- shape_file("../includes/Marseille/points_of_interest.shp"); //define the building shapefile with many types, extracted from IGN database file ign_file <- shape_file(dataset_path + "buildings_ign.shp"); //define the initial building shapefile, extracted from OSM database file shape_file_roads <- shape_file(dataset_path + "roads_marseille.shp"); list<string> shop_places <- ["commercial", "kiosk", "chapel", "church", "service", "Commercial et services", "Religieux", "religious"]; list<string> sport_places <- ["Sportif"]; float min_area_buildings <- 20.0; int nb_for_building_shapefile_split <- 50000; int nb_for_road_shapefile_split <- 20000; list<string> living_places <- ["house", "apartments", "dormitory", "hotel", "residential", "Résidentiel"]; list<string> work_places <- ["industrial", "office", "construction", "garages", "hospital"]; list<string> study_places <- ["university", "college", "school"]; list<string> leisure_places <- ["commercial", "kiosk", "chapel", "church", "service", "Sportif", "Commercial et services", "Religieux", "religious"]; bool parallel <- true; bool buildings <- true; bool roads <- false; geometry shape <- envelope(data_file); graph the_graph; map<road,float> road_weights; init { write "Start the pre-processing process"; list<int> list_of_id; if buildings{ create Building from: shape_file_buildings with: [type::get ("type"), id::int(get("osm_id"))]{ if not (self overlaps world) { do die; } list_of_id << id; if (type != nil and type != ""){ types << type; } } write "Number of buildings created : "+ length(Building); ask Building where (each.shape.area < min_area_buildings) { do die; } write "Small building removed"; create Building_ign from: ign_file { if not (self overlaps world) { do die; } } write "Number of buildings ign created : "+ length(Building_ign); ask Building parallel: parallel { list<Building_ign> neigh <- Building_ign overlapping self; if not empty(neigh) { Building_ign bestCand; if (length(neigh) = 1) { bestCand <- first(neigh); } else { bestCand <- neigh with_max_of (each inter self).area; if (bestCand = nil) { bestCand <- neigh with_min_of (each.location distance_to location); } if (bestCand = nil){ write("aucun building correspondant a ce building ign"); } } if (bestCand.USAGE1 != nil and bestCand.USAGE1 != ""){ types << bestCand.USAGE1; } else if (bestCand.USAGE2 != nil and bestCand.USAGE2 != ""){ types << bestCand.USAGE2; } if (bestCand.HAUTEUR != nil and bestCand.HAUTEUR > 0){ height <- bestCand.HAUTEUR; } } } create Building from: shape_file_pois with: [id::int(read("osm_id")), type::read("fclass")]{ if not (self overlaps world){ do die; } if not (id in list_of_id){ list_of_id << id; types_str <- type; types << type; } else{ // fclass devient le type du bâtiment déjà existant Building real_building <- Building first_with (each.id = self.id); real_building.type <- type; real_building.types << type; real_building.types_str <- type + "," + real_building.types_str; do die; } } ask Building where empty(each.types){ do die; } ask Building parallel: parallel { type <- first(types); //si le building a déjà un type dans le shapefile initial : on le garde en position 1. Sinon on prend celui de building_ign (USAGE1 ou USAGE2) types_str <- type; if (length(types) > 1) { loop i from: 1 to: length(types) - 1 { types_str <-types_str + "," + types[i] ; } } } ask Building_ign{ do die; } write("All buildings created and typed. Start cleaning roads"); } if roads{ write("cleaning roads"); list<geometry> clean_lines <- clean_network(shape_file_roads.contents,3.0 , true, true); write("road shapefile cleaned"); create road from: clean_lines with: [id::int(get("osm_id")), fclass::get("fclass"), maxspeed::int(get("maxspeed"))]{ if not (self overlaps world) { do die; } } write "Number of roads created : "+ length(road); } if buildings{ write("Saving buildings"); save Building to: dataset_path + "buildings.shp" type: shp attributes: ["id"::id,"type"::type, "types_str"::types_str ,"height"::height]; } if roads{ write("Saving roads"); save road to: dataset_path + "roads.shp" type: shp attributes: ["id"::id,"fclass"::fclass, "maxspeed"::maxspeed]; } } } species Building_ign { /*nature du bati; valeurs possibles: * Indifférenciée | Arc de triomphe | Arène ou théâtre antique | Industriel, agricole ou commercial | Chapelle | Château | Eglise | Fort, blockhaus, casemate | Monument | Serre | Silo | Tour, donjon | Tribune | Moulin à vent */ string NATURE; /* * Usage du bati; valeurs possibles: Agricole | Annexe | Commercial et services | Industriel | Religieux | Sportif | Résidentiel | Indifférencié */ string USAGE1; //usage principale string USAGE2; //usage secondaire int NB_LOGTS; //nombre de logements; int NB_ETAGES;// nombre d'étages float HAUTEUR; } species Building { string type; list<string> types; string types_str; float height; int id; } species road { int id; int maxspeed; string fclass; aspect base { draw shape color: color width: 2; } } experiment generateGISdata type: gui { }