Skip to content

Commit c040e81

Browse files
author
pv
committed
ADD examples.
1 parent f4492fa commit c040e81

File tree

9 files changed

+336
-56
lines changed

9 files changed

+336
-56
lines changed
80 KB
Loading
105 KB
Loading

docs/examples/example_mapping.py

Lines changed: 4 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1+
from compas.colors import Color
12
from compas.datastructures import Mesh
23
from compas_viewer import Viewer
34
from tessagon.adaptors.list_adaptor import ListAdaptor
45
from tessagon.types.hex_tessagon import HexTessagon
5-
from compas.colors import Color
66

77
import compas_libigl as igl
88

@@ -26,8 +26,8 @@
2626

2727
options = {
2828
"function": lambda u, v: [u, v, 0],
29-
"u_range": [0, 1.0],
30-
"v_range": [0, 1.0],
29+
"u_range": [-0.255, 1.33],
30+
"v_range": [-0.34, 1.33],
3131
"u_num": 16,
3232
"v_num": 10,
3333
"u_cyclic": False,
@@ -39,15 +39,6 @@
3939
pv = tessagon_mesh["vert_list"]
4040
pf = tessagon_mesh["face_list"]
4141

42-
# ==============================================================================
43-
# Place the pattern mesh at the bottom left corner of the mesh
44-
# ==============================================================================
45-
46-
pattern2d = Mesh.from_vertices_and_faces(pv, pf)
47-
c = pattern2d.aabb().corner(0)
48-
pattern2d.translate([-c[0], -c[1], -c[2]])
49-
pv, pf = pattern2d.to_vertices_and_faces()
50-
5142
# ==============================================================================
5243
# Mapping: 3D Mesh, 2D Pattern, UV
5344
# ==============================================================================
@@ -61,7 +52,7 @@
6152

6253
viewer = Viewer()
6354
viewer.scene.add(mesh, name="mesh", show_faces=False, linecolor=Color.grey(), opacity=0.2)
64-
viewer.scene.add(pattern2d, name="pattern2d")
55+
viewer.scene.add(Mesh.from_vertices_and_faces(pv, pf), name="pattern2d")
6556
viewer.scene.add(mesh_mapped, name="mesh_mapped", facecolor=Color.red())
6657

6758
# To see where the pattern is mapped:

docs/examples/example_mapping.rst

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,24 @@
22
Mapping
33
********************************************************************************
44

5+
.. figure:: /_images/example_mapping_patterns.png
6+
:figclass: figure
7+
:class: figure-img img-fluid
8+
9+
.. literalinclude:: example_mapping_patterns.py
10+
:language: python
11+
512
.. figure:: /_images/example_mapping.png
613
:figclass: figure
714
:class: figure-img img-fluid
815

916
.. literalinclude:: example_mapping.py
1017
:language: python
18+
19+
20+
.. figure:: /_images/example_mapping_boundaries.png
21+
:figclass: figure
22+
:class: figure-img img-fluid
23+
24+
.. literalinclude:: example_mapping_boundaries.py
25+
:language: python
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
from math import pi
2+
3+
from compas.colors import Color
4+
from compas.datastructures import Mesh
5+
from compas.geometry import Polygon
6+
from compas_viewer import Viewer
7+
from tessagon.adaptors.list_adaptor import ListAdaptor
8+
from tessagon.types.hex_tessagon import HexTessagon
9+
10+
import compas_libigl as igl
11+
12+
# ==============================================================================
13+
# Input geometry: 3D Mesh
14+
# ==============================================================================
15+
16+
mesh = Mesh.from_obj("data/minimal_surface.obj")
17+
for key, attr in mesh.vertices(True):
18+
y = attr["y"]
19+
attr["y"] = -attr["z"]
20+
attr["z"] = y
21+
mesh.translate([2, 2, 0.5])
22+
23+
v, f = mesh.to_vertices_and_faces()
24+
25+
# ==============================================================================
26+
# Flattening
27+
# ==============================================================================
28+
29+
# To see where the pattern is mapped:
30+
uv = igl.trimesh_lscm((v, f))
31+
mesh_flattened = mesh.copy()
32+
for i in range(mesh.number_of_vertices()):
33+
mesh_flattened.vertex_attributes(i, "xyz", [uv[i][0], uv[i][1], 0])
34+
35+
36+
# ==============================================================================
37+
# Input geometry: 2D Pattern creation using Tessagon library, can be other mesh.
38+
# ==============================================================================
39+
40+
options = {
41+
"function": lambda u, v: [u, v, 0],
42+
"u_range": [-0.255, 1.33],
43+
"v_range": [-0.34, 1.33],
44+
"u_num": 16,
45+
"v_num": 10,
46+
"u_cyclic": False,
47+
"v_cyclic": False,
48+
"adaptor_class": ListAdaptor,
49+
}
50+
tessagon = HexTessagon(**options)
51+
tessagon_mesh = tessagon.create_mesh()
52+
pv = tessagon_mesh["vert_list"]
53+
pf = tessagon_mesh["face_list"]
54+
55+
# rotate the pattern
56+
rotated_mesh = Mesh.from_vertices_and_faces(pv, pf)
57+
rotated_mesh.rotate(0 * pi / 180, [0, 0, 1])
58+
59+
pv, pf = rotated_mesh.to_vertices_and_faces()
60+
61+
# ==============================================================================
62+
# Boundaries
63+
# ==============================================================================
64+
65+
boundaries = igl.trimesh_boundaries(mesh_flattened.to_vertices_and_faces())
66+
67+
polygons = []
68+
for vertices in boundaries:
69+
vertices = list(vertices)
70+
vertices.pop()
71+
vertices.append(vertices[0])
72+
points = mesh_flattened.vertices_attributes("xyz", keys=vertices)
73+
polygons.append(Polygon(points))
74+
75+
# ==============================================================================
76+
# 2D Boolean Intersection using Shapely
77+
# ==============================================================================
78+
79+
polygons_cut = []
80+
for face in pf:
81+
points = []
82+
for vertex in face:
83+
points.append(pv[vertex])
84+
polygon_cut = Polygon(points)
85+
if len(points) > 2:
86+
polygons_cut.append(polygon_cut)
87+
88+
89+
# Polygon.boolean_intersection
90+
intersections = []
91+
for polygon_cut in polygons_cut:
92+
for polygon in polygons:
93+
from compas.geometry import boolean_intersection_polygon_polygon
94+
95+
coords = boolean_intersection_polygon_polygon(polygon, polygon_cut)
96+
if len(coords) > 0:
97+
intersection = Polygon([[x, y, 0] for x, y in coords]) # type: ignore
98+
intersections.append(intersection)
99+
100+
mesh_cropped = Mesh.from_polygons(intersections)
101+
pv, pf = mesh_cropped.to_vertices_and_faces()
102+
103+
104+
# ==============================================================================
105+
# Place the pattern mesh at the bottom left corner of the meshpattern_uv
106+
# ==============================================================================
107+
108+
mv, mf = igl.map_mesh((v, f), (pv, pf))
109+
mesh_mapped = Mesh.from_vertices_and_faces(mv, mf)
110+
111+
# ==============================================================================
112+
# Viewer
113+
# ==============================================================================
114+
115+
viewer = Viewer()
116+
viewer.scene.add(mesh, name="mesh", show_faces=False, linecolor=Color.grey(), opacity=0.2)
117+
viewer.scene.add(mesh_mapped, name="mesh_mapped", facecolor=Color.red())
118+
viewer.scene.add(rotated_mesh, linecolor=Color.red(), linewidth=3)
119+
# viewer.scene.add(polygons, linecolor=Color.red(), linewidth=3)
120+
viewer.scene.add(intersections, linecolor=Color.red(), linewidth=3)
121+
122+
viewer.scene.add(mesh_flattened, name="mesh_flattened0")
123+
viewer.show()
Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
from compas.colors import Color
2+
from compas.datastructures import Mesh
3+
from compas_viewer import Viewer
4+
from compas_viewer.config import Config
5+
from tessagon.adaptors.list_adaptor import ListAdaptor
6+
from tessagon.types.brick_tessagon import BrickTessagon
7+
from tessagon.types.dissected_hex_quad_tessagon import DissectedHexQuadTessagon
8+
from tessagon.types.dissected_hex_tri_tessagon import DissectedHexTriTessagon
9+
from tessagon.types.dissected_square_tessagon import DissectedSquareTessagon
10+
from tessagon.types.dissected_triangle_tessagon import DissectedTriangleTessagon
11+
from tessagon.types.dodeca_tessagon import DodecaTessagon
12+
from tessagon.types.floret_tessagon import FloretTessagon
13+
from tessagon.types.hex_big_tri_tessagon import HexBigTriTessagon
14+
15+
# Import all tessagon types
16+
from tessagon.types.hex_tessagon import HexTessagon
17+
from tessagon.types.hex_tri_tessagon import HexTriTessagon
18+
from tessagon.types.octo_tessagon import OctoTessagon
19+
from tessagon.types.pythagorean_tessagon import PythagoreanTessagon
20+
from tessagon.types.rhombus_tessagon import RhombusTessagon
21+
from tessagon.types.square_tessagon import SquareTessagon
22+
from tessagon.types.square_tri_tessagon import SquareTriTessagon
23+
from tessagon.types.tri_tessagon import TriTessagon
24+
from tessagon.types.weave_tessagon import WeaveTessagon
25+
from tessagon.types.zig_zag_tessagon import ZigZagTessagon
26+
27+
import compas_libigl as igl
28+
29+
# Dictionary of tessagon classes
30+
TESSAGON_TYPES = {
31+
1: ("Hex", HexTessagon),
32+
2: ("Tri", TriTessagon),
33+
3: ("Octo", OctoTessagon),
34+
4: ("Square", SquareTessagon),
35+
5: ("Rhombus", RhombusTessagon),
36+
6: ("HexTri", HexTriTessagon),
37+
7: ("DissectedSquare", DissectedSquareTessagon),
38+
8: ("DissectedTriangle", DissectedTriangleTessagon),
39+
9: ("DissectedHexQuad", DissectedHexQuadTessagon),
40+
10: ("DissectedHexTri", DissectedHexTriTessagon),
41+
11: ("Floret", FloretTessagon),
42+
12: ("Pythagorean", PythagoreanTessagon),
43+
13: ("Brick", BrickTessagon),
44+
14: ("Weave", WeaveTessagon),
45+
15: ("ZigZag", ZigZagTessagon),
46+
16: ("HexBigTri", HexBigTriTessagon),
47+
17: ("Dodeca", DodecaTessagon),
48+
18: ("SquareTri", SquareTriTessagon),
49+
}
50+
51+
# Pattern selection - change this value to use a different pattern
52+
PATTERN_TYPE = 15
53+
54+
# ==============================================================================
55+
# Input geometry: 3D Mesh
56+
# ==============================================================================
57+
58+
mesh = Mesh.from_obj("data/minimal_surface.obj")
59+
for key, attr in mesh.vertices(True):
60+
y = attr["y"]
61+
attr["y"] = -attr["z"]
62+
attr["z"] = y
63+
mesh.translate([2, 2, 0.5])
64+
65+
v, f = mesh.to_vertices_and_faces()
66+
67+
68+
# ==============================================================================
69+
# Input geometry: 2D Pattern creation using Tessagon library, can be other mesh.
70+
# ==============================================================================
71+
72+
options = {
73+
"function": lambda u, v: [u, v, 0],
74+
"u_range": [-0.25, 1.25],
75+
"v_range": [-0.25, 1.25],
76+
"u_num": 20,
77+
"v_num": 20,
78+
"u_cyclic": False,
79+
"v_cyclic": False,
80+
"adaptor_class": ListAdaptor,
81+
}
82+
83+
# Get pattern name and class based on selected pattern type
84+
pattern_name, pattern_class = TESSAGON_TYPES[PATTERN_TYPE]
85+
86+
# Create the selected tessagon pattern
87+
tessagon = pattern_class(**options)
88+
tessagon_mesh = tessagon.create_mesh()
89+
pv = tessagon_mesh["vert_list"]
90+
pf = tessagon_mesh["face_list"]
91+
92+
# ==============================================================================
93+
# Mapping: 3D Mesh, 2D Pattern, UV
94+
# ==============================================================================
95+
96+
mv, mf = igl.map_mesh((v, f), (pv, pf))
97+
mesh_mapped = Mesh.from_vertices_and_faces(mv, mf)
98+
99+
# ==============================================================================
100+
# Viewer
101+
# ==============================================================================
102+
103+
104+
config = Config()
105+
config.camera.target = [2, 2, 0.25]
106+
config.camera.position = [5, 2, 1.5]
107+
# config.camera.scale = 100
108+
109+
viewer = Viewer(config=config)
110+
viewer.scene.add(mesh, name="mesh", show_faces=False, linecolor=Color.grey(), opacity=0.2)
111+
viewer.scene.add(Mesh.from_vertices_and_faces(pv, pf), name="pattern2d")
112+
viewer.scene.add(mesh_mapped, name="mesh_mapped", facecolor=Color.red())
113+
114+
# To see where the pattern is mapped:
115+
uv = igl.trimesh_lscm((v, f))
116+
mesh_flattened = mesh.copy()
117+
for i in range(mesh.number_of_vertices()):
118+
mesh_flattened.vertex_attributes(i, "xyz", [uv[i][0], uv[i][1], 0])
119+
120+
viewer.scene.add(mesh_flattened, name="mesh_flattened")
121+
viewer.show()

src/compas_libigl/mapping.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,8 @@
44

55

66
def map_mesh(target_mesh, pattern_mesh):
7-
"""Map a 2D pattern mesh onto a 3D target.
7+
"""
8+
Map a 2D pattern mesh onto a 3D target.
89
910
Parameters
1011
----------
@@ -34,10 +35,9 @@ def map_mesh(target_mesh, pattern_mesh):
3435
v_numpy = np.array(v, dtype=np.float64)
3536
f_numpy = np.array(f, dtype=np.int32)
3637
pattern_v_numpy = np.array(pv, dtype=np.float64)
37-
pattern_f_numpy = np.array(pf, dtype=np.int32)
3838

3939
# Perform the mapping
40-
pattern_f_numpy_cleaned = _mapping.map_mesh_with_automatic_parameterization(v_numpy, f_numpy, pattern_v_numpy, pattern_f_numpy)
40+
pattern_f_numpy_cleaned = _mapping.map_mesh_with_automatic_parameterization(v_numpy, f_numpy, pattern_v_numpy, pf)
4141

4242
# Return the result as a tuple
4343
return pattern_v_numpy, pattern_f_numpy_cleaned

0 commit comments

Comments
 (0)