## Sesc Av. Paulista # Ilustração com mapas, dados georeferenciados e programação - Aula 2 ### `hackmd.io/@sesc-av-paulista/ilustra-mapas-2025-a2` - [índice](https://hackmd.io/@sesc-av-paulista/ilustra-mapas-2025) - Funções da biblioteca `osmnx` https://osmnx.readthedocs.io/en/stable/user-reference.html#module-osmnx.features - Tags no OpenStreetMap https://wiki.openstreetmap.org/wiki/Map_features ```python= import py5 # biblioteca de desenho import osmnx as ox # para pegar dados do OSM # Obter tupla (lat, long) de um endereço (geocofing) sé = ox.geocode('Praça da Sé, São Paulo, SP, Brasil') # Obter GeoDataFrame de um local (place) municipio = ox.geocode_to_gdf('São Paulo, Brasil') # municipio.geometry[0] shapely.Polygon def setup(): py5.size(600, 600) # Calculo para caber na tela usando .total_bounds do GDF x_min, y_min, x_max, y_max = municipio.total_bounds map_w, map_h = (x_max - x_min), (y_max - y_min) x_scale = y_scale = py5.height / map_h # Aplicar uma tranformação (encolher pra caber na tela) inverte Y translate_and_scale_gdf(municipio, -x_min, -y_min, x_scale, -y_scale) # Desenhar na tela forma = municipio.geometry[0] py5.shape(forma, 0, 600) # conversão implícita de shapely.Polygon em Py5Shape # Salvar um PNG # py5.save_frame('são paulo.png') def translate_and_scale_gdf(gdf, x, y, x_scale, y_scale): gdf['geometry'] = gdf.geometry.translate(x, y) gdf['geometry'] = gdf.geometry.scale( xfact=x_scale, yfact=y_scale, origin=(0, 0)) py5.run_sketch(block=False) ``` # Águas ```python= import py5 # biblioteca de desenho import osmnx as ox # para pegar dados do OSM em geopandas.GeoDatFrama import shapely # biblioteca de geometria usada pelo geopandas ox.settings.log_console = True # Obter tupla (lat, long) de um endereço (geocofing) sé = ox.geocode('Praça da Sé, São Paulo, SP, Brasil') # Obter GeoDataFrame de um local (place) municipio = ox.geocode_to_gdf('São Paulo, Brasil') # muciopio.geometry[0] shapely.Polygon aguas = ox.features.features_from_place( 'São Paulo, Brasil', tags={'water': True} ) def setup(): py5.size(600, 600) # Calculo para caber na tela usando .total_bounds do GDF x_min, y_min, x_max, y_max = municipio.total_bounds map_w, map_h = (x_max - x_min), (y_max - y_min) x_scale = y_scale = py5.height / map_h # Aplicar uma tranformação (encolher pra caber na tela) inverte Y translate_and_scale_gdf(municipio, -x_min, -y_min, x_scale, -y_scale) translate_and_scale_gdf(aguas, -x_min, -y_min, x_scale, -y_scale) # Desenhar na tela py5.no_stroke() forma = municipio.geometry[0] # pegando a primeira geometria py5.fill(240) py5.shape(forma, 0, py5.height) # conversão implícita de shapely.Polygon em Py5Shape py5.fill(0, 0, 100) # azul escuro geometrias = shapely.GeometryCollection(list(aguas.geometry)) py5.shape(geometrias, 0, py5.height) # Salvar um PNG # py5.save_frame('são paulo.png') def translate_and_scale_gdf(gdf, x, y, x_scale, y_scale): gdf['geometry'] = gdf.geometry.translate(x, y) gdf['geometry'] = gdf.geometry.scale( xfact=x_scale, yfact=y_scale, origin=(0, 0)) py5.run_sketch(block=False) ``` ## Prédios no entorno do Pátio do Colégio Ruas não ficaram legais ```python= import py5 # biblioteca de desenho import osmnx as ox # para pegar dados do OSM em geopandas.GeoDatFrama import shapely # biblioteca de geometria usada pelo geopandas ox.settings.log_console = True # Obter tupla (lat, long) de um endereço (geocofing) ponto = ox.geocode('Patío do Colégio, São Paulo, SP, Brasil') # Obter GeoDataFrame de um local (place) # muciopio.geometry[0] shapely.Polygon predios = ox.features.features_from_point( ponto, # tupla de cooedenadas tags={'building': True}, dist=1000 ) aguas = ox.features.features_from_point( ponto, # tupla de cooedenadas tags={'water': True}, dist=1000 ) ruas = ox.features.features_from_point( ponto, # tupla de cooedenadas tags={'streets': True}, dist=1000 ) def setup(): py5.size(800, 800) # Calculo para caber na tela usando .total_bounds do GDF x_min, y_min, x_max, y_max = predios.total_bounds map_w, map_h = (x_max - x_min), (y_max - y_min) x_scale = y_scale = py5.height / map_h # Aplicar uma tranformação (encolher pra caber na tela) inverte Y translate_and_scale_gdf(predios, -x_min, -y_min, x_scale, -y_scale) translate_and_scale_gdf(ruas, -x_min, -y_min, x_scale, -y_scale) translate_and_scale_gdf(aguas, -x_min, -y_min, x_scale, -y_scale) # Desenhar na tela predios py5.stroke_weight(0.5) py5.stroke(0) # cor do traço py5.fill(100) # cinza escuro geometria_predios = shapely.GeometryCollection(list(predios.geometry)) py5.shape(geometria_predios, 0, py5.height) # desenhar começando na parte de baixo da tela # Desenhar ruas py5.no_stroke() py5.fill(240) # cinza escuro geometria_ruas = shapely.GeometryCollection(list(ruas.geometry)) py5.shape(geometria_ruas, 0, py5.height) # desenhar começando na parte de baixo da tela # Desenhar aguas py5.no_stroke() py5.fill(0, 0, 200) # cinza escuro geometria_aguas = shapely.GeometryCollection(list(aguas.geometry)) py5.shape(geometria_aguas, 0, py5.height) # desenhar começando na parte de baixo da tela def translate_and_scale_gdf(gdf, x, y, x_scale, y_scale): gdf['geometry'] = gdf.geometry.translate(x, y) gdf['geometry'] = gdf.geometry.scale( xfact=x_scale, yfact=y_scale, origin=(0, 0)) py5.run_sketch(block=False) # tirar block=False no MacOS ``` ### Usando grafo dos caminhos - predios com cores ```python= import py5 # biblioteca de desenho import osmnx as ox # para pegar dados do OSM em geopandas.GeoDatFrama import shapely # biblioteca de geometria usada pelo geopandas DIST = 1000 ox.settings.log_console = True # Obter tupla (lat, long) de um endereço (geocofing) ponto = ox.geocode('Patío do Colégio, São Paulo, SP, Brasil') # Obter GeoDataFrame de um local (place) predios = ox.features.features_from_point( ponto, # tupla de cooedenadas tags={'building': True}, dist=DIST ) aguas = ox.features.features_from_point( ponto, # tupla de cooedenadas tags={'water': True}, dist=DIST ) graph = ox.graph_from_point( ponto, network_type='all', dist=DIST ) gdf_nodes, caminhos = ox.graph_to_gdfs( graph, nodes=True, edges=True, node_geometry=True, fill_edge_geometry=False ) def setup(): py5.size(800, 800) py5.begin_record(py5.PDF, 'mapa.pdf') py5.background(0) # branco # Calculo para caber na tela usando .total_bounds do GDF x_min, y_min, x_max, y_max = predios.total_bounds map_w, map_h = (x_max - x_min), (y_max - y_min) x_scale = y_scale = py5.height / map_h # Aplicar uma tranformação (encolher pra caber na tela) inverte Y translate_and_scale_gdf(predios, -x_min, -y_min, x_scale, -y_scale) translate_and_scale_gdf(caminhos, -x_min, -y_min, x_scale, -y_scale) translate_and_scale_gdf(aguas, -x_min, -y_min, x_scale, -y_scale) # Desenhar na tela predios py5.stroke_weight(0.1) py5.stroke(0) # cor do traço py5.fill(100) # cinza escuro grupo_predios = py5.create_shape(py5.GROUP) for geometria_predio in predios.geometry: py5.fill(py5.random(255), py5.random(255), py5.random(255)) grupo_predios.add_child(py5.convert_shape(geometria_predio)) py5.shape(grupo_predios, 0, py5.height) # desenhar começando na parte de baixo da tela # Desenhar ruas py5.stroke('#96E9CD') # cor de traço das ruas py5.stroke_weight(1.5) py5.fill(240) # cinza escuro geometria_caminhos = shapely.GeometryCollection(list(caminhos.geometry)) py5.shape(geometria_caminhos, 0, py5.height) # desenhar começando na parte de baixo da tela # Desenhar aguas py5.no_stroke() py5.fill(0, 0, 200) # azul escuro R, G, B de 0 a 255 geometria_aguas = shapely.GeometryCollection(list(aguas.geometry)) py5.shape(geometria_aguas, 0, py5.height) # desenhar começando na parte de baixo da tela py5.end_record() def translate_and_scale_gdf(gdf, x, y, x_scale, y_scale): gdf['geometry'] = gdf.geometry.translate(x, y) gdf['geometry'] = gdf.geometry.scale( xfact=x_scale, yfact=y_scale, origin=(0, 0)) py5.run_sketch(block=False) # tirar block=False no MacOS ``` ### Coloridão Saturado ```python= import py5 # biblioteca de desenho import osmnx as ox # para pegar dados do OSM em geopandas.GeoDatFrama import shapely # biblioteca de geometria usada pelo geopandas DIST = 1000 ox.settings.log_console = True # Obter tupla (lat, long) de um endereço (geocofing) ponto = ox.geocode('Patío do Colégio, São Paulo, SP, Brasil') # Obter GeoDataFrame de um local (place) predios = ox.features.features_from_point( ponto, # tupla de cooedenadas tags={'building': True}, dist=DIST ) aguas = ox.features.features_from_point( ponto, # tupla de cooedenadas tags={'water': True}, dist=DIST ) graph = ox.graph_from_point( ponto, network_type='all', dist=DIST ) gdf_nodes, caminhos = ox.graph_to_gdfs( graph, nodes=True, edges=True, node_geometry=True, fill_edge_geometry=False ) def setup(): py5.size(800, 800) py5.begin_record(py5.PDF, 'mapa.pdf') py5.color_mode(py5.HSB) # Hue (Matiz), Saturation, Brightness py5.background(0) # preto # Calculo para caber na tela usando .total_bounds do GDF x_min, y_min, x_max, y_max = predios.total_bounds map_w, map_h = (x_max - x_min), (y_max - y_min) x_scale = y_scale = py5.height / map_h # Aplicar uma tranformação (encolher pra caber na tela) inverte Y translate_and_scale_gdf(predios, -x_min, -y_min, x_scale, -y_scale) translate_and_scale_gdf(caminhos, -x_min, -y_min, x_scale, -y_scale) translate_and_scale_gdf(aguas, -x_min, -y_min, x_scale, -y_scale) # Desenhar na tela predios py5.stroke_weight(0.1) py5.stroke(0) # cor do traço py5.fill(100) # cinza escuro grupo_predios = py5.create_shape(py5.GROUP) for geometria_predio in predios.geometry: py5.fill(py5.random(255), 255, 255) # Hue, Sat, Bri grupo_predios.add_child(py5.convert_shape(geometria_predio)) py5.shape(grupo_predios, 0, py5.height) # desenhar começando na parte de baixo da tela # Desenhar ruas py5.stroke(255) # cor de traço das ruas py5.stroke_weight(1.5) py5.fill(240) # cinza escuro geometria_caminhos = shapely.GeometryCollection(list(caminhos.geometry)) py5.shape(geometria_caminhos, 0, py5.height) # desenhar começando na parte de baixo da tela # Desenhar aguas py5.no_stroke() py5.fill(0, 0, 200) # cinza 200 geometria_aguas = shapely.GeometryCollection(list(aguas.geometry)) py5.shape(geometria_aguas, 0, py5.height) # desenhar começando na parte de baixo da tela py5.end_record() def translate_and_scale_gdf(gdf, x, y, x_scale, y_scale): gdf['geometry'] = gdf.geometry.translate(x, y) gdf['geometry'] = gdf.geometry.scale( xfact=x_scale, yfact=y_scale, origin=(0, 0)) py5.run_sketch(block=False) # tirar block=False no MacOS ``` ### Brasília ```python= import py5 # biblioteca de desenho import osmnx as ox # para pegar dados do OSM em geopandas.GeoDataFrame import shapely # biblioteca de geometria usada pelo geopandas DIST = 7000 ox.settings.log_console = True # Obter tupla (lat, long) de um endereço (geocoding) ponto = ox.geocode('Brasília, DF, Brasil') # Obter GeoDataFrame de um local (place) predios = ox.features.features_from_point( ponto, # tupla de cooredenadas tags={'building': True}, dist=DIST ) aguas = ox.features.features_from_point( ponto, # tupla de cooedenadas tags={'water': True}, dist=DIST ) graph = ox.graph_from_point( ponto, network_type='walk', dist=DIST ) gdf_nodes, caminhos = ox.graph_to_gdfs( graph, nodes=True, edges=True, node_geometry=True, fill_edge_geometry=False ) def setup(): py5.size(800, 800) # começa a gravar um pdf py5.begin_record(py5.PDF, 'mapa-bsb.pdf') py5.color_mode(py5.HSB) # Hue (Matiz), Saturation, Brightness py5.background(0) # preto # Calculo para caber na tela usando .total_bounds do GDF x_min, y_min, x_max, y_max = caminhos.total_bounds map_w, map_h = (x_max - x_min), (y_max - y_min) x_scale = y_scale = py5.height / map_h # Aplicar tranformação nos GDFs (encolher pra caber na tela) inverte Y translate_and_scale_gdf(predios, -x_min, -y_min, x_scale, -y_scale) translate_and_scale_gdf(caminhos, -x_min, -y_min, x_scale, -y_scale) translate_and_scale_gdf(aguas, -x_min, -y_min, x_scale, -y_scale) # Desenhar aguas py5.no_stroke() py5.fill(0, 0, 200) # cinza 200 geometria_aguas = aguas.geometry.union_all() py5.shape(geometria_aguas, 0, py5.height) # desenhar começando na parte de baixo da tela # Desenhar na tela predios py5.stroke_weight(0.1) py5.stroke(0) # cor do traço grupo_predios = py5.create_shape(py5.GROUP) for geometria_predio in predios.geometry: py5.fill(py5.random(255), 255, 255) # Matiz/Hue aleatório, Sat max, Brilho max grupo_predios.add_child(py5.convert_shape(geometria_predio)) py5.shape(grupo_predios, 0, py5.height) # desenhar começando na parte de baixo da tela # Desenhar ruas py5.stroke(255) # cor de traço das ruas py5.stroke_weight(0.5) geometria_caminhos = caminhos.geometry.union_all() py5.shape(geometria_caminhos, 0, py5.height) # desenhar começando na parte de baixo da tela # termina de gravar o PDF py5.end_record() def translate_and_scale_gdf(gdf, x, y, x_scale, y_scale): gdf['geometry'] = gdf.geometry.translate(x, y) gdf['geometry'] = gdf.geometry.scale( xfact=x_scale, yfact=y_scale, origin=(0, 0)) py5.run_sketch(block=False) # remove block=False if on MacOS ``` ![image](https://hackmd.io/_uploads/ryQ-S3Qe-g.png)