Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- Added simplified borders to map_mesh function.
- Added fixed points to map_mesh function.

### Changed

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

### Removed
Expand Down
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ project(compas_libigl LANGUAGES CXX)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_EXTENSIONS OFF)

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

if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
Expand Down
3 changes: 2 additions & 1 deletion docs/examples/example_isolines.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@

for i, isolines in enumerate(isolines):
color = cmap(values[i], minval, maxval)
viewer.scene.add(isolines, linecolor=color, linewidth=3)
for isoline in isolines:
viewer.scene.add(isoline, linecolor=color, linewidth=3)

viewer.show()
28 changes: 24 additions & 4 deletions docs/examples/example_mapping_patterns.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
from pathlib import Path

from compas.colors import Color
from compas.geometry import Point
from compas.datastructures import Mesh
from compas_viewer import Viewer
from compas_viewer.config import Config
Expand All @@ -15,16 +16,31 @@

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



for vertex in mesh.vertices():
x, y, z = mesh.vertex_attributes(vertex, "xyz") # type: ignore
mesh.vertex_attributes(vertex, "xyz", [x, -z, y])

# ==============================================================================
# Mapping: 3D Mesh, 2D Pattern, UV
# Get Lowest and Highest points
# ==============================================================================

mesh_mapped = map_pattern_to_mesh("ZigZag", mesh, clip_boundaries=True, tolerance=1e-6, pattern_u=16, pattern_v=16)
aabb = mesh.aabb()
fixed_points = []


for vertex in mesh.vertices():
x, y, z = mesh.vertex_attributes(vertex, "xyz") # type: ignore
if abs(z-aabb.zmin) < 1e-3 or abs(z-aabb.zmax) < 1e-3:
fixed_points.append(vertex)

# ==============================================================================
# Mapping: 3D Mesh, 2D Pattern, UV
# ==============================================================================

mesh_mapped0 = map_pattern_to_mesh("ZigZag", mesh, clip_boundaries=True, tolerance=1e-6, pattern_u=16, pattern_v=16, simplify_borders=True, fixed_points=fixed_points)
mesh_mapped1 = map_pattern_to_mesh("ZigZag", mesh, clip_boundaries=True, tolerance=1e-6, pattern_u=16, pattern_v=16, simplify_borders=False)
# ==============================================================================
# Viewer
# ==============================================================================
Expand All @@ -35,7 +51,11 @@

viewer = Viewer(config=config)

# viewer.scene.add(mesh, name="mesh", show_faces=False, linecolor=Color.grey(), opacity=0.2)
viewer.scene.add(mesh_mapped, name="mesh_mapped", facecolor=Color.red())
viewer.scene.add(mesh, name="mesh", show_faces=False, linecolor=Color.grey(), opacity=0.2)
viewer.scene.add(mesh_mapped0, name="mesh_mapped0", facecolor=Color.red(), show_points=True)
# viewer.scene.add(mesh_mapped1, name="mesh_mapped1", facecolor=Color.blue(), show_points=True, show_faces=False)

for p in fixed_points:
viewer.scene.add(mesh.vertex_point(p), pointcolor=Color.red(), pointsize=10)

viewer.show()
2 changes: 1 addition & 1 deletion mesh_flattened.json

Large diffs are not rendered by default.

32 changes: 28 additions & 4 deletions src/compas_libigl/mapping.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
from compas_libigl._types_std import VectorVectorInt # noqa: F401


def map_mesh(target_mesh, pattern_mesh, clip_boundaries=True, tolerance=1e-6):
def map_mesh(target_mesh, pattern_mesh, clip_boundaries=True, simplify_borders=True, fixed_points=None, tolerance=1e-6):
"""
Map a 2D pattern mesh onto a 3D target.

Expand All @@ -38,6 +38,10 @@ def map_mesh(target_mesh, pattern_mesh, clip_boundaries=True, tolerance=1e-6):
A tuple of (vertices, faces) representing the pattern mesh.
clip_boundaries : bool
Whether to clip the pattern mesh to the boundaries of the target mesh.
simplify_borders : bool
Whether to simplify the border of the pattern mesh.
fixed_points : list[list[float]]
A list of fixed points on the target mesh.
tolerance : float
The tolerance for point comparison, to remove duplicates.

Expand All @@ -61,16 +65,30 @@ def map_mesh(target_mesh, pattern_mesh, clip_boundaries=True, tolerance=1e-6):
f_numpy = np.array(f, dtype=np.int32)
pattern_v_numpy = np.array(pv, dtype=np.float64)

# Handle fixed_points - provide empty array if None

fixed_points_vectorint = VectorInt()
if fixed_points is None:
fixed_points_vectorint = VectorInt()
else:
fixed_points_vectorint = VectorInt(fixed_points)

# Convert pattern_f from Python list to VectorVectorInt which is expected by C++ code

pattern_f_vec = VectorVectorInt()
for face in pf:
pattern_f_vec.append(face)

# Perform the mapping
pv_numpy_copy, pf_numpy_cleaned, p_normals, pattern_is_boundary, pattern_groups = _mapping.map_mesh_with_automatic_parameterization(
v_numpy, f_numpy, pattern_v_numpy, pf, clip_boundaries, tolerance
v_numpy, f_numpy, pattern_v_numpy, pattern_f_vec, clip_boundaries, simplify_borders, fixed_points_vectorint, tolerance
)

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


def map_pattern_to_mesh(name, mesh, clip_boundaries=True, tolerance=1e-6, pattern_u=16, pattern_v=16):
def map_pattern_to_mesh(name, mesh, clip_boundaries=True, tolerance=1e-6, pattern_u=16, pattern_v=16, simplify_borders=True, fixed_points=None):
"""
Map a 2D pattern mesh onto a 3D target.

Expand Down Expand Up @@ -108,6 +126,10 @@ def map_pattern_to_mesh(name, mesh, clip_boundaries=True, tolerance=1e-6, patter
The number of pattern vertices in the u direction.
pattern_v : int
The number of pattern vertices in the v direction.
simplify_borders : bool
Whether to simplify the border of the pattern mesh.
fixed_points : list[list[float]]
A list of fixed points on the target mesh.

Returns
-------
Expand Down Expand Up @@ -165,6 +187,8 @@ def map_pattern_to_mesh(name, mesh, clip_boundaries=True, tolerance=1e-6, patter
pf = tessagon_mesh["face_list"]

v, f = mesh.to_vertices_and_faces()
mapped_vertices, mapped_faces, mapped_normals, mapped_is_boundary, mapped_groups = map_mesh((v, f), (pv, pf), clip_boundaries=clip_boundaries, tolerance=tolerance)
mapped_vertices, mapped_faces, mapped_normals, mapped_is_boundary, mapped_groups = map_mesh(
(v, f), (pv, pf), clip_boundaries=clip_boundaries, simplify_borders=simplify_borders, fixed_points=fixed_points, tolerance=tolerance
)

return Mesh.from_vertices_and_faces(mapped_vertices, mapped_faces)
Loading
Loading