## Tutorial Python Brasil 2025 ## Explorando geometrias 2D e 3D com Python ### <i>Python Brazil 2025 Tutorial - exploring 2D and 3D geometries with Python</i> ## `hackmd.io/@py5coding/2d-3d-python` ## Apresentações / Who are we? ## Preparando nosso ambiente de trabalho ***Preparing our work environment*** Vamos usar o Thonny IDE e algumas bibliotecas! (isso facilita as coisas) ### Bibliotecas necessárias / Required libraries * py5 * shapely * trimesh * manifold3d (needed for trimesh boolean operations) * matplotlib * svgpathtools (needed for SVG operations) Se você não quiser usar o Thonny vai preciar ter um JDK para o py5... * install-jdk Use the following code to download and install Java. ```bash python -c "import jdk; print('Java installed to', jdk.install('21'))" ``` ## Configurando o ambiente / Environment set up - [*detailed install instructions*](https://py5coding.org/content/install.html) - Ambiente educacional [Windows Thonny portable + py5/shapely/trimesh pré instalado etc., OU Thonny no Mac e Linux](https://abav.lugaralgum.com/como-instalar-py5/) - - nota importante: Se for usar o Thonny, desative no **menu py5** > *imported mode for py5* (modo para iniciantes) ## Starting with / Começando com `py5` ![image](https://hackmd.io/_uploads/HJ_3P2wRxx.png) - Doc offical py5coding.org - Repo principal com issues e discussions https://github.com/py5coding/py5generator - Exemplos deste tutorial https://github.com/py5coding/python-brasil-2025/ - Material de apoio https://abav.lugaralgum.com/material-aulas - Camisetas https://umapenca.com/villares/ #### O "Hello World" do py5... - `import py5`, `def setup()`, `def draw()`, `py5.run_sketch()` etc. ```python import py5 def setup(): py5.size(200, 200) py5.rect_mode(py5.CENTER) def draw(): py5.rect(py5.mouse_x, py5.mouse_y, 10, 10) py5.run_sketch() ``` ![image](https://hackmd.io/_uploads/HkD3msDRlg.png) ## Starting with / Começando com `shapely` Shapely library is used for working with 2D geometries. Common use cases are cartography and geo-spatial data. ![image](https://hackmd.io/_uploads/Byys4Btagx.png) ![Sem título](https://hackmd.io/_uploads/ByWBtdTpll.png) - Point, LineString, Polygon - Boolean operations ![image](https://hackmd.io/_uploads/Hy4hdiPCxg.png) ```python import py5 import shapely def setup(): py5.size(200, 200) py5.background(0, 150, 150) ca = shapely.Point(100, 100).buffer(50) cb = shapely.affinity.translate(ca, 50, 0) crescente = ca - cb py5.shape(crescente) py5.save('shapely_translate.png') py5.run_sketch() ``` ![image](https://hackmd.io/_uploads/S1ohC9IRle.png) - Geometry operations - `area`, `buffer()`, `centroid`, `boundary`, `convex_hull` - Voronoi - `shp.is_valid` / `shapely.make_valid(shp)` - some geometry operations will not be correct for invalid shapes - https://github.com/py5coding/python-brasil-2025/blob/main/more-examples/tutorial_shapely_5.py - Topology Exceptions - slivers and floating point madness - Voronoi animation demo ![image](https://hackmd.io/_uploads/ryMOaiDCgg.png) ![image](https://hackmd.io/_uploads/Syj8oiDAxl.png) ) https://github.com/py5coding/python-brasil-2025/blob/main/prototypes/animated-voronoi.py ## 3D com `trimesh` Para instalar no seu env com as dependencias opcionais bacanudas: *easy* `python -m pip install trimesh[easy]` - *primitives* ```python import py5 from trimesh.primitives import Box, Capsule, Cylinder, Sphere rot_z = 0 def setup(): global primitives py5.size(350, 350, py5.P3D) py5.stroke_weight(1.5) primitives = py5.create_shape(py5.GROUP) box = py5.convert_shape(Box((80, 120, 70))) box.translate(150, 0, 0) primitives.add_child(box) # NOTE: Trimesh's Capsule `sections` parameter might have a bug capsule = py5.convert_shape(Capsule(70, 40, sections=12)) capsule.translate(0, 150, 0) primitives.add_child(capsule) cylinder = py5.convert_shape(Cylinder(50, 80, sections=12)) cylinder.translate(-150, 0, 0) primitives.add_child(cylinder) sphere = py5.convert_shape(Sphere(75, subdivisions=2)) sphere.translate(0, -150, 0) primitives.add_child(sphere) def draw(): global rot_z rot_z += 1 py5.background(204) py5.translate(py5.width / 2, py5.height / 2) py5.rotate_x(py5.radians(60)) py5.rotate_z(py5.radians(rot_z)) py5.shape(primitives) py5.run_sketch() ``` ![out](https://hackmd.io/_uploads/HJ8CEsU0ee.gif) (Can model 3D objects in other tools like FreeCAD and load exported models into py5 with trimesh) - Operações booleanas ```python #import facets # facets.py code see below import py5 import trimesh box = trimesh.creation.box((25, 25, 25)) sphere = trimesh.creation.icosphere(subdivisions=5, radius=17) composite = box.difference(sphere) def setup(): global shape py5.size(800, 800, py5.P3D) py5.fill(255) py5.stroke(0) py5.stroke_weight(3) shape = py5.convert_shape(composite, min_angle=0.1) def draw(): py5.background(204) py5.lights() py5.translate(py5.width / 2, py5.height / 2, -200) py5.rotate_x(py5.frame_count * 0.01) py5.rotate_y(py5.frame_count * 0.02) py5.rotate_z(py5.frame_count * 0.015) py5.scale(20) py5.shape(shape) py5.run_sketch() ``` - *facets* - facetas são os limites das "faces" num sentido comum, mas para o trimesh, um triângulo é o que ele considera uma face, e as facetas são faces planas adjacentes. - Add [facets.py](https://github.com/py5coding/python-brasil-2025/blob/main/prototypes/facets.py) so that only facets are drawn ## Shapely + Trimesh integrations - Polígonos do `shapely` podem ser extrudados com `trimesh`! ```python import shapely import trimesh def setup(): global malha size(200, 200, P3D) background(150, 0, 150) lights() translate(width / 2, height / 2) rotate_y(radians(45)) c = shapely.Point(0, 0).buffer(50) # buffer com o raio d = shapely.affinity.translate(c, 50, 0) crescente = c - d malha = trimesh.creation.extrude_polygon(crescente, 50) shape(malha) ``` ![image](https://hackmd.io/_uploads/SkigUj8Cgg.png) ```python= import py5 import shapely from shapely import Point, Polygon import trimesh import facets # https://github.com/py5coding/python-brasil-2025/blob/main/prototypes/facets.py def setup(): global resultado py5.size(500, 500, py5.P3D) poly = Polygon(( (-200, -200), (200, -200), (150, 150), (0, 50), (-200, 200), )) poly = poly - poly.buffer(-20) malha = trimesh.creation.extrude_polygon(poly, 200) resultado = py5.convert_shape(malha, min_angle=py5.radians(30)) def draw(): py5.background('#6440C5') py5.translate(py5.width / 2, py5.height / 2) py5.scale(0.7) py5.rotate_y(py5.radians(py5.mouse_x)) py5.shape(resultado) py5.run_sketch(block=False) ``` ![image](https://hackmd.io/_uploads/HkHA4TwAeg.png) - [Exemplo do Alexandre (the rotating box with holes)](https://abav.lugaralgum.com/material-aulas/Processing-Python-py5/shapely-e-trimesh.html#um-exemplo-animado-avan%C3%A7ado) - [Exemplo de tipografia + extrusão](https://github.com/py5coding/python-brasil-2025/blob/main/prototypes/fonts-jim.py) - [*Voronoy Flowers*](https://github.com/py5coding/python-brasil-2025/blob/main/prototypes/extrusion.py) - Atenção: Precisa instalar a biblioteca de Processing `PeasyCam` ```python import py5_tools py5_tools.processing.download_library("PeasyCam") ``` - Check out more at https://github.com/py5coding/python-brasil-2025/tree/main/prototypes ## Extra pointers / Referências extra - General - [py5 documentation](https://py5coding.org/) - Página do material de apoio do Alexandre [material-aulas](https://abav.lugaralgum.com/material-aulas/Processing-Python-py5/shapely-e-trimesh.html) - Shapely - [Shapely documentation](https://shapely.readthedocs.io/en/stable/index.html) - [py5 - Shapely Integration documentation](https://py5coding.org/integrations/shapely.html) - Trimesh - [Trimesh documentation](https://trimesh.org/) - [py5 - Trimesh Integration documentation](https://py5coding.org/integrations/trimesh.html)