1414]
1515
1616
17- def mesh_offset (mesh , distance = 1.0 , ):
17+ def mesh_offset (mesh , distance = 1.0 ):
1818 """Offset a mesh.
1919
2020 Parameters
2121 ----------
22- mesh : Mesh
22+ mesh : :class:`compas.datastructures. Mesh`
2323 A Mesh to offset.
24- distance : float
24+ distance : float, optional
2525 The offset distance.
26+ Default is ``1.0``.
2627
2728 Returns
2829 -------
29- Mesh
30+ :class:`compas.datastructures. Mesh`
3031 The offset mesh.
3132
33+ Notes
34+ -----
35+ If the offset distance is a positive value, the offset is in the direction of the vertex normal.
36+ If the value is negative, the offset is in the opposite direction.
37+ In both cases, the orientation of the offset mesh is the same as the orientation of the original.
38+
39+ In areas with high degree of curvature, the offset mesh can have self-intersections.
40+
41+ Examples
42+ --------
43+ >>> from compas.datastructures import Mesh, mesh_offset
44+ >>> from compas.geometry import distance_point_point as dist
45+ >>> mesh = Mesh.from_vertices_and_faces([[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]], [[0, 1, 2, 3]])
46+ >>> offset = mesh_offset(mesh)
47+ >>> all(dist(mesh.vertex_coordinates(a), offset.vertex_coordinates(b)) == 1 for a, b in zip(mesh.vertices(), offset.vertices()))
48+ True
49+
3250 """
3351 offset = mesh .copy ()
3452
35- for key in offset .vertices ():
36- normal = mesh .vertex_normal (key )
37- xyz = mesh .vertex_coordinates (key )
38- offset .vertex_attributes (key , 'xyz' , add_vectors (xyz , scale_vector (normal , distance )))
53+ for vertex in offset .vertices ():
54+ normal = mesh .vertex_normal (vertex )
55+ xyz = mesh .vertex_coordinates (vertex )
56+ offset .vertex_attributes (vertex , 'xyz' , add_vectors (xyz , scale_vector (normal , distance )))
3957
4058 return offset
4159
4260
43- def mesh_thicken (mesh , thickness = 1.0 ):
61+ def mesh_thicken (mesh , thickness = 1.0 , both = True ):
4462 """Thicken a mesh.
4563
4664 Parameters
4765 ----------
48- mesh : Mesh
66+ mesh : :class:`compas.datastructures. Mesh`
4967 A mesh to thicken.
50- thickness : real
51- The mesh thickness
68+ thickness : float, optional
69+ The mesh thickness.
70+ This should be a positive value.
71+ Default is ``1.0``.
72+ both : bool, optional
73+ If true, the mesh is thickened on both sides of the original.
74+ Otherwise, the mesh is thickened on the side of the positive normal.
5275
5376 Returns
5477 -------
55- thickened_mesh : Mesh
78+ thickened_mesh : :class:`compas.datastructures. Mesh`
5679 The thickened mesh.
5780
81+ Raises
82+ ------
83+ ValueError
84+ If ``thickness`` is not a positive number.
85+
86+ Examples
87+ --------
88+ >>> from compas.datastructures import Mesh, mesh_thicken
89+ >>> from compas.geometry import distance_point_point as dist
90+ >>> mesh = Mesh.from_vertices_and_faces([[0, 0, 0], [1, 0, 0], [1, 1, 0], [0, 1, 0]], [[0, 1, 2, 3]])
91+ >>> thick = mesh_thicken(mesh)
92+ >>> thick.is_closed()
93+ True
94+ >>> all(dist(mesh.vertex_coordinates(a), thick.vertex_coordinates(b)) == 1 for a, b in zip(mesh.vertices(), thick.vertices()))
95+ True
96+
5897 """
59- # offset in both directions
60- mesh_top = mesh_offset (mesh , + 0.5 * thickness )
61- mesh_bottom = mesh_offset (mesh , - 0.5 * thickness )
98+ if thickness <= 0 :
99+ raise ValueError ("Thickness should be a positive number." )
100+
101+ if both :
102+ mesh_top = mesh_offset (mesh , + 0.5 * thickness )
103+ mesh_bottom = mesh_offset (mesh , - 0.5 * thickness )
104+ else :
105+ mesh_top = mesh_offset (mesh , thickness )
106+ mesh_bottom = mesh .copy ()
62107
63108 # flip bottom part
64109 mesh_flip_cycles (mesh_bottom )
@@ -85,4 +130,4 @@ def mesh_thicken(mesh, thickness=1.0):
85130if __name__ == '__main__' :
86131
87132 import doctest
88- doctest .testmod (globs = globals () )
133+ doctest .testmod ()
0 commit comments