"""2025-12-02
Mapas v2: Origem
Mapa do bairro da Mooca, São Paulo, SP, Brasil
ericof.com|Poly data (c) OpenStreetMap contributors|https://www.openstreetmap.org/copyright
png
Sketch,py5,CreativeCoding
"""
from collections import deque
from sketches.utils.draw import canvas
from sketches.utils.draw.cores.paletas import gera_paleta
from sketches.utils.helpers import sketches as helpers
from sketches.utils.mapas import v2 as mv2
import py5
sketch = helpers.info_for_sketch(__file__, __doc__)
FORMA: py5.Py5Shape | None = None
FUNDO = None
zpt = {"x": -37, "y": 1089, "scale": 1, "amount": 0} # zoom & pan transformation values
def escala(geodata: mv2.t.GeoDataV2) -> tuple[float, float, float, float, float, float]:
x_min, y_min, x_max, y_max = geodata.boundary
map_w, map_h = (x_max - x_min), (y_max - y_min)
x_scale, y_scale = py5.width / map_w, py5.height / map_h
return x_min, y_min, x_max, y_max, x_scale, y_scale
def cria_forma(geodata: mv2.t.GeoDataV2, camadas: dict, caminhos: dict) -> py5.Py5Shape:
x_min, y_min, x_max, y_max, x_scale, y_scale = escala(geodata)
forma = py5.create_shape(py5.GROUP)
for name, camada in camadas.items():
feature = geodata.features[name]
gdf = feature.gdf
paleta = camada["paleta"]
mv2.translate_and_scale_gdf(gdf, -x_min, -y_min, x_scale, -y_scale)
for g in gdf.geometry:
cor = paleta[0]
py5.fill(cor)
py5.no_stroke()
forma.add_child(py5.convert_shape(g))
paleta.rotate(1)
for name, camada in caminhos.items():
feature = geodata.networks[name]
gdf = feature.gdf
paleta = camada["paleta"]
mv2.translate_and_scale_gdf(gdf, -x_min, -y_min, x_scale, -y_scale)
for g in gdf.geometry:
cor = paleta[0]
py5.no_fill()
py5.stroke(cor)
forma.add_child(py5.convert_shape(g))
paleta.rotate(1)
return forma
def setup():
global FORMA, FUNDO
py5.size(*helpers.DIMENSOES.external, py5.P3D)
paleta = gera_paleta("pastel", True)
FUNDO = paleta.pop()
py5.background(FUNDO)
# Inicializa OSMnx
mv2.d_utils.inicializa_osmnx(log_console=False)
camadas = {
"amenity": {"tag": {"amenity": True}, "paleta": paleta},
"building": {"tag": {"building": True}, "paleta": paleta},
"water": {"tag": {"water": True}, "paleta": deque(["#0000FF"])},
"green": {
"tag": {"leisure": ["pitch", "park", "playground"], "landuse": ["grass"]},
"paleta": deque(["#00AA00"]),
},
}
caminhos = {
"roads": {"tag": {"highway": True}, "paleta": deque(["#CCCCCC"])},
"rail": {"tag": {"railway": True}, "paleta": deque(["#888888"])},
}
limite = "São Paulo, São Paulo, Brazil"
endereco = "Mooca, São Paulo, São Paulo, Brazil"
print(f"Obtendo dados OSMnx para {endereco}...")
geodata = mv2.obtem_dados_osmnx(
pasta=sketch.path,
limite=limite,
endereco=endereco,
distancia=4500,
camadas=camadas,
caminhos=caminhos,
)
print(f"Obtendo dados OSMnx para {endereco}... concluído.")
FORMA = cria_forma(geodata, camadas, caminhos)
def draw():
global FUNDO
if FUNDO and FORMA:
py5.background(FUNDO)
with py5.push():
py5.translate(zpt["x"], zpt["y"], -2)
py5.scale(zpt["scale"])
FORMA.set_stroke_weight(1 / zpt["scale"])
py5.shape(FORMA)
py5.window_title(f"Sketch - Frame {zpt['x'], zpt['y'], zpt['scale']}")
cor_fundo = py5.color(0)
# Credits and go
canvas.sketch_frame(
sketch, cor_fundo, "large_transparent_white", "transparent_white"
)
def key_pressed():
key = py5.key
if key == " ":
save_and_close()
def mouse_wheel(e):
xrd = (py5.mouse_x - zpt["x"]) / zpt["scale"]
yrd = (py5.mouse_y - zpt["y"]) / zpt["scale"]
zpt["amount"] -= e.get_count()
zpt["scale"] = 1.1 ** zpt["amount"]
zpt["x"] = int(py5.mouse_x - xrd * zpt["scale"])
zpt["y"] = int(py5.mouse_y - yrd * zpt["scale"])
def mouse_dragged():
zpt["x"] += py5.mouse_x - py5.pmouse_x
zpt["y"] += py5.mouse_y - py5.pmouse_y
def save_and_close():
py5.no_loop()
canvas.save_sketch_image(sketch)
py5.exit_sketch()
if __name__ == "__main__":
py5.run_sketch()