Skip to content

Commit 12987e9

Browse files
Merge pull request #29 from compas-dev/2d_pattern_weld
2d pattern weld and simplification
2 parents e7ed598 + 84556dc commit 12987e9

File tree

8 files changed

+218
-61
lines changed

8 files changed

+218
-61
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1818

1919
### Added
2020

21+
- Added simplified borders to map_mesh function.
22+
- Added fixed points to map_mesh function.
23+
2124
### Changed
2225

26+
- Fixed point welding bug in map_mesh function.
27+
- Changed example_isolines to work with the new compas_viewer.
2328
- GA for cibuildwheel, bring back the tessagon test.
2429

2530
### Removed

CMakeLists.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ project(compas_libigl LANGUAGES CXX)
44
set(CMAKE_CXX_STANDARD 20)
55
set(CMAKE_CXX_EXTENSIONS OFF)
66

7-
option(ENABLE_PRECOMPILED_HEADERS "Enable precompiled headers" OFF)
7+
option(ENABLE_PRECOMPILED_HEADERS "Enable precompiled headers" ON)
88
option(MULTITHREADED_COMPILATION "Enable multi-threaded compilation (Ninja only)" ON)
99

1010
if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)

docs/examples/example_isolines.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353

5454
for i, isolines in enumerate(isolines):
5555
color = cmap(values[i], minval, maxval)
56-
viewer.scene.add(isolines, linecolor=color, linewidth=3)
56+
for isoline in isolines:
57+
viewer.scene.add(isoline, linecolor=color, linewidth=3)
5758

5859
viewer.show()

docs/examples/example_mapping_patterns.py

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
from pathlib import Path
22

33
from compas.colors import Color
4+
from compas.geometry import Point
45
from compas.datastructures import Mesh
56
from compas_viewer import Viewer
67
from compas_viewer.config import Config
@@ -15,16 +16,31 @@
1516

1617
mesh = Mesh.from_obj(Path(__file__).parent.parent.parent / "data" / "minimal_surface.obj")
1718

19+
20+
1821
for vertex in mesh.vertices():
1922
x, y, z = mesh.vertex_attributes(vertex, "xyz") # type: ignore
2023
mesh.vertex_attributes(vertex, "xyz", [x, -z, y])
2124

2225
# ==============================================================================
23-
# Mapping: 3D Mesh, 2D Pattern, UV
26+
# Get Lowest and Highest points
2427
# ==============================================================================
2528

26-
mesh_mapped = map_pattern_to_mesh("ZigZag", mesh, clip_boundaries=True, tolerance=1e-6, pattern_u=16, pattern_v=16)
29+
aabb = mesh.aabb()
30+
fixed_vertices = []
31+
32+
33+
for vertex in mesh.vertices():
34+
x, y, z = mesh.vertex_attributes(vertex, "xyz") # type: ignore
35+
if abs(z-aabb.zmin) < 1e-3 or abs(z-aabb.zmax) < 1e-3:
36+
fixed_vertices.append(vertex)
37+
38+
# ==============================================================================
39+
# Mapping: 3D Mesh, 2D Pattern, UV
40+
# ==============================================================================
2741

42+
mesh_mapped0 = map_pattern_to_mesh("ZigZag", mesh, clip_boundaries=True, tolerance=1e-6, pattern_u=16, pattern_v=16, simplify_borders=True, fixed_vertices=fixed_vertices)
43+
mesh_mapped1 = map_pattern_to_mesh("ZigZag", mesh, clip_boundaries=True, tolerance=1e-6, pattern_u=16, pattern_v=16, simplify_borders=False)
2844
# ==============================================================================
2945
# Viewer
3046
# ==============================================================================
@@ -35,7 +51,11 @@
3551

3652
viewer = Viewer(config=config)
3753

38-
# viewer.scene.add(mesh, name="mesh", show_faces=False, linecolor=Color.grey(), opacity=0.2)
39-
viewer.scene.add(mesh_mapped, name="mesh_mapped", facecolor=Color.red())
54+
viewer.scene.add(mesh, name="mesh", show_faces=False, linecolor=Color.grey(), opacity=0.2)
55+
viewer.scene.add(mesh_mapped0, name="mesh_mapped0", facecolor=Color.red(), show_points=True)
56+
# viewer.scene.add(mesh_mapped1, name="mesh_mapped1", facecolor=Color.blue(), show_points=True, show_faces=False)
57+
58+
for p in fixed_vertices:
59+
viewer.scene.add(mesh.vertex_point(p), pointcolor=Color.red(), pointsize=10)
4060

4161
viewer.show()

mesh_flattened.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

src/compas_libigl/mapping.py

Lines changed: 44 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
from compas_libigl._types_std import VectorVectorInt # noqa: F401
2727

2828

29-
def map_mesh(target_mesh, pattern_mesh, clip_boundaries=True, tolerance=1e-6):
29+
def map_mesh(target_mesh, pattern_mesh, clip_boundaries=True, simplify_borders=True, fixed_vertices=None, tolerance=1e-6):
3030
"""
3131
Map a 2D pattern mesh onto a 3D target.
3232
@@ -36,10 +36,18 @@ def map_mesh(target_mesh, pattern_mesh, clip_boundaries=True, tolerance=1e-6):
3636
A tuple of (vertices, faces) representing the target mesh.
3737
pattern_mesh : tuple[list[list[float]], list[list[int]]]
3838
A tuple of (vertices, faces) representing the pattern mesh.
39-
clip_boundaries : bool
39+
clip_boundaries : bool, optional
4040
Whether to clip the pattern mesh to the boundaries of the target mesh.
41-
tolerance : float
41+
Default is True.
42+
simplify_borders : bool, optional
43+
Whether to simplify the border of the pattern mesh.
44+
Default is True.
45+
fixed_vertices : list[list[float]], optional
46+
A list of fixed points on the target mesh.
47+
Default is None.
48+
tolerance : float, optional
4249
The tolerance for point comparison, to remove duplicates.
50+
Default is 1e-6.
4351
4452
Returns
4553
-------
@@ -61,16 +69,30 @@ def map_mesh(target_mesh, pattern_mesh, clip_boundaries=True, tolerance=1e-6):
6169
f_numpy = np.array(f, dtype=np.int32)
6270
pattern_v_numpy = np.array(pv, dtype=np.float64)
6371

72+
# Handle fixed_vertices - provide empty array if None
73+
74+
fixed_vertices_vectorint = VectorInt()
75+
if fixed_vertices is None:
76+
fixed_vertices_vectorint = VectorInt()
77+
else:
78+
fixed_vertices_vectorint = VectorInt(fixed_vertices)
79+
80+
# Convert pattern_f from Python list to VectorVectorInt which is expected by C++ code
81+
82+
pattern_f_vec = VectorVectorInt()
83+
for face in pf:
84+
pattern_f_vec.append(face)
85+
6486
# Perform the mapping
6587
pv_numpy_copy, pf_numpy_cleaned, p_normals, pattern_is_boundary, pattern_groups = _mapping.map_mesh_with_automatic_parameterization(
66-
v_numpy, f_numpy, pattern_v_numpy, pf, clip_boundaries, tolerance
88+
v_numpy, f_numpy, pattern_v_numpy, pattern_f_vec, clip_boundaries, simplify_borders, fixed_vertices_vectorint, tolerance
6789
)
6890

6991
# Return the result as a tuple
7092
return pv_numpy_copy, pf_numpy_cleaned, p_normals, pattern_is_boundary, pattern_groups
7193

7294

73-
def map_pattern_to_mesh(name, mesh, clip_boundaries=True, tolerance=1e-6, pattern_u=16, pattern_v=16):
95+
def map_pattern_to_mesh(name, mesh, clip_boundaries=True, tolerance=1e-6, pattern_u=16, pattern_v=16, simplify_borders=True, fixed_vertices=None):
7496
"""
7597
Map a 2D pattern mesh onto a 3D target.
7698
@@ -100,14 +122,24 @@ def map_pattern_to_mesh(name, mesh, clip_boundaries=True, tolerance=1e-6, patter
100122
101123
mesh : compas.datastructures.Mesh
102124
The target mesh.
103-
clip_boundaries : bool
125+
clip_boundaries : bool, optional
104126
Whether to clip the pattern mesh to the boundaries of the target mesh.
105-
tolerance : float
127+
Default is True.
128+
tolerance : float, optional
106129
The tolerance for point comparison, to remove duplicates.
107-
pattern_u : int
130+
Default is 1e-6.
131+
pattern_u : int, optional
108132
The number of pattern vertices in the u direction.
109-
pattern_v : int
133+
Default is 16.
134+
pattern_v : int, optional
110135
The number of pattern vertices in the v direction.
136+
Default is 16.
137+
simplify_borders : bool, optional
138+
Whether to simplify the border of the pattern mesh.
139+
Default is True.
140+
fixed_vertices : list[list[float]], optional
141+
A list of fixed points on the target mesh.
142+
Default is None.
111143
112144
Returns
113145
-------
@@ -165,6 +197,8 @@ def map_pattern_to_mesh(name, mesh, clip_boundaries=True, tolerance=1e-6, patter
165197
pf = tessagon_mesh["face_list"]
166198

167199
v, f = mesh.to_vertices_and_faces()
168-
mapped_vertices, mapped_faces, mapped_normals, mapped_is_boundary, mapped_groups = map_mesh((v, f), (pv, pf), clip_boundaries=clip_boundaries, tolerance=tolerance)
200+
mapped_vertices, mapped_faces, mapped_normals, mapped_is_boundary, mapped_groups = map_mesh(
201+
(v, f), (pv, pf), clip_boundaries=clip_boundaries, simplify_borders=simplify_borders, fixed_vertices=fixed_vertices, tolerance=tolerance
202+
)
169203

170204
return Mesh.from_vertices_and_faces(mapped_vertices, mapped_faces)

0 commit comments

Comments
 (0)