|
1 | 1 | from pathlib import Path |
2 | 2 |
|
3 | 3 | from compas.colors import Color |
| 4 | +from compas.geometry import Polyline |
4 | 5 | from compas.datastructures import Mesh |
5 | 6 | from compas_viewer import Viewer |
6 | 7 | from compas_viewer.config import Config |
7 | 8 | from tessagon.adaptors.list_adaptor import ListAdaptor |
8 | | -from tessagon.types.hex_tessagon import HexTessagon |
| 9 | +from tessagon.types.zig_zag_tessagon import ZigZagTessagon |
9 | 10 |
|
10 | 11 | from compas_libigl.mapping import map_mesh |
11 | 12 | from compas_libigl.parametrisation import trimesh_lsc_mapping |
12 | 13 |
|
| 14 | +from compas import json_dump |
| 15 | + |
13 | 16 | # ============================================================================== |
14 | 17 | # Input geometry: 3D Mesh |
15 | 18 | # ============================================================================== |
16 | 19 |
|
17 | | -mesh = Mesh.from_obj(Path(__file__).parent.parent.parent / "data" / "minimal_surface.obj") |
| 20 | +mesh = Mesh.from_off(Path(__file__).parent.parent.parent / "data" / "beetle.off") |
18 | 21 |
|
19 | 22 | for vertex in mesh.vertices(): |
20 | 23 | x, y, z = mesh.vertex_attributes(vertex, "xyz") # type: ignore |
|
32 | 35 | "function": lambda u, v: [u * 1, v * 1, 0], |
33 | 36 | "u_range": [-0.255, 1.33], |
34 | 37 | "v_range": [-0.34, 1.33], |
35 | | - "u_num": 16, |
36 | | - "v_num": 10, |
| 38 | + "u_num": 20, |
| 39 | + "v_num": 20, |
37 | 40 | "u_cyclic": False, |
38 | 41 | "v_cyclic": False, |
39 | 42 | "adaptor_class": ListAdaptor, |
40 | 43 | } |
41 | | -tessagon = HexTessagon(**options) |
| 44 | +tessagon = ZigZagTessagon(**options) |
42 | 45 | tessagon_mesh = tessagon.create_mesh() |
43 | 46 | pv = tessagon_mesh["vert_list"] |
44 | 47 | pf = tessagon_mesh["face_list"] |
45 | 48 |
|
46 | 49 | # ============================================================================== |
47 | 50 | # Mapping: 3D Mesh, 2D Pattern, UV |
| 51 | +# mv - mapped vertices |
| 52 | +# mf - mapped faces |
| 53 | +# mn - mapped normals |
| 54 | +# mg - mapped boundaries (True or False) |
| 55 | +# mb - mapped groups for polygons with holes (list of int) |
48 | 56 | # ============================================================================== |
49 | | - |
50 | | -mv, mf = map_mesh((v, f), (pv, pf)) |
| 57 | +mv, mf, mn, mb, mg = map_mesh((v, f), (pv, pf)) |
51 | 58 | mesh_mapped = Mesh.from_vertices_and_faces(mv, mf) |
52 | 59 |
|
| 60 | +# ============================================================================== |
| 61 | +# Offset mesh by normals, normals are interpolated from the original mesh. |
| 62 | +# ============================================================================== |
| 63 | +mesh_mapped_offset = mesh_mapped.copy() |
| 64 | +for i in range(mesh_mapped.number_of_vertices()): |
| 65 | + mesh_mapped_offset.vertex_attributes(i, "xyz", mesh_mapped.vertex_attributes(i, "xyz") - mn[i]*0.001) |
| 66 | + |
| 67 | +# ============================================================================== |
| 68 | +# Get Boundary Polylines |
| 69 | +# ============================================================================== |
| 70 | +boundaries = [] |
| 71 | +for i in range(len(mb)): |
| 72 | + if not mb[i]: |
| 73 | + continue |
| 74 | + points = [] |
| 75 | + for j in range(len(mf[i])): |
| 76 | + id = mf[i][j] |
| 77 | + points.append(mesh_mapped.vertex_attributes(id, "xyz") + mn[id]*0.002) |
| 78 | + points.append(points[0]) |
| 79 | + polyline = Polyline(points) |
| 80 | + boundaries.append(polyline) |
| 81 | + |
| 82 | + |
53 | 83 | # ============================================================================== |
54 | 84 | # Viewer |
55 | 85 | # ============================================================================== |
|
59 | 89 | config.camera.position = [5, 2, 1.5] |
60 | 90 |
|
61 | 91 | viewer = Viewer(config=config) |
62 | | -viewer.scene.add(mesh, name="mesh", show_faces=False, linecolor=Color.grey(), opacity=0.2) |
| 92 | +# viewer.scene.add(mesh, name="mesh", show_faces=False, linecolor=Color.grey(), opacity=0.2) |
63 | 93 | viewer.scene.add(Mesh.from_vertices_and_faces(pv, pf), name="pattern2d") |
64 | | -viewer.scene.add(mesh_mapped, name="mesh_mapped", facecolor=Color.red()) |
| 94 | +viewer.scene.add(mesh_mapped, name="mesh_mapped", facecolor=Color.pink()) |
| 95 | +viewer.scene.add(mesh_mapped_offset, name="mesh_mapped", facecolor=Color.blue()) |
| 96 | +for boundary in boundaries: |
| 97 | + viewer.scene.add(boundary, name="boundary", linecolor=Color.yellow(), linewidth=3) |
65 | 98 |
|
66 | 99 | # To see where the pattern is mapped: |
67 | 100 | uv = trimesh_lsc_mapping((v, f)) |
68 | 101 | mesh_flattened = mesh.copy() |
69 | 102 | for i in range(mesh.number_of_vertices()): |
70 | 103 | mesh_flattened.vertex_attributes(i, "xyz", [uv[i][0], uv[i][1], 0]) |
71 | 104 |
|
| 105 | +json_dump([Mesh.from_vertices_and_faces(pv, pf), mesh_mapped, mesh_mapped_offset, boundaries, mesh_flattened], "mesh_flattened.json") |
| 106 | + |
72 | 107 | viewer.scene.add(mesh_flattened, name="mesh_flattened") |
73 | 108 | viewer.show() |
0 commit comments