11from __future__ import annotations
2+ from itertools import product
23
34from typing import Generator , Optional , Tuple , List , Dict
45
6+ import numpy as np
7+
58from compas .geometry import Point , Vector , Line , Frame , Box
69from compas .geometry import Transformation
710from compas .utilities import meshgrid , linspace , flatten
@@ -395,7 +398,7 @@ def to_tesselation(self) -> Mesh:
395398 triangles .append (tess .GetTriangleIndex (i ))
396399 return Mesh .from_vertices_and_faces (vertices , triangles )
397400
398- def to_mesh (self , u : int = 100 , v : Optional [int ] = None ) -> Mesh :
401+ def to_mesh (self , nu : int = 100 , nv : Optional [int ] = None ) -> Mesh :
399402 """Convert the surface to a quad mesh."""
400403 from itertools import product
401404 from functools import lru_cache
@@ -404,17 +407,42 @@ def to_mesh(self, u: int = 100, v: Optional[int] = None) -> Mesh:
404407 def point_at (i , j ):
405408 return self .point_at (i , j )
406409
407- v = v or u
408- U , V = meshgrid (self .u_space ( u ), self .v_space ( v ) )
410+ nv = nv or nu
411+ V , U = np . meshgrid (self .v_space ( nv + 1 ), self .u_space ( nu + 1 ), indexing = 'ij' )
409412 quads = [[
410413 point_at (U [i + 0 ][j + 0 ], V [i + 0 ][j + 0 ]),
411414 point_at (U [i + 0 ][j + 1 ], V [i + 0 ][j + 1 ]),
412415 point_at (U [i + 1 ][j + 1 ], V [i + 1 ][j + 1 ]),
413416 point_at (U [i + 1 ][j + 0 ], V [i + 1 ][j + 0 ])
414- ] for i , j in product (range (v - 1 ), range (u - 1 ))]
417+ ] for i , j in product (range (nv ), range (nu ))]
415418
416419 return Mesh .from_polygons (quads )
417420
421+ def to_triangles (self , nu : int = 100 , nv : Optional [int ] = None ) -> List [Tuple [float , float , float ]]:
422+ """Convert the surface to a quad mesh."""
423+ from itertools import product
424+ from functools import lru_cache
425+
426+ @lru_cache (maxsize = None )
427+ def point_at (i , j ):
428+ return self .point_at (i , j )
429+
430+ nv = nv or nu
431+ V , U = np .meshgrid (self .v_space (nv + 1 ), self .u_space (nu + 1 ), indexing = 'ij' )
432+
433+ tris = [None ] * (6 * nu * nv )
434+ index = 0
435+ for i , j in product (range (nv ), range (nu )):
436+ tris [index + 0 ] = point_at (U [i + 0 ][j + 0 ], V [i + 0 ][j + 0 ])
437+ tris [index + 1 ] = point_at (U [i + 0 ][j + 1 ], V [i + 0 ][j + 1 ])
438+ tris [index + 2 ] = point_at (U [i + 1 ][j + 1 ], V [i + 1 ][j + 1 ])
439+ tris [index + 3 ] = point_at (U [i + 0 ][j + 0 ], V [i + 0 ][j + 0 ])
440+ tris [index + 4 ] = point_at (U [i + 1 ][j + 1 ], V [i + 1 ][j + 1 ])
441+ tris [index + 5 ] = point_at (U [i + 1 ][j + 0 ], V [i + 1 ][j + 0 ])
442+ index += 6
443+
444+ return tris
445+
418446 # ==============================================================================
419447 # OCC
420448 # ==============================================================================
@@ -534,13 +562,13 @@ def u_space(self, n: int = 10) -> Generator[float, None, None]:
534562 """Compute evenly spaced parameters over the surface domain in the U direction.
535563 """
536564 umin , umax = self .u_domain
537- return linspace (umin , umax , n )
565+ return np . linspace (umin , umax , n )
538566
539567 def v_space (self , n : int = 10 ) -> Generator [float , None , None ]:
540568 """Compute evenly spaced parameters over the surface domain in the V direction.
541569 """
542570 vmin , vmax = self .v_domain
543- return linspace (vmin , vmax , n )
571+ return np . linspace (vmin , vmax , n )
544572
545573 def u_isocurve (self , u : float ) -> NurbsCurve :
546574 """Compute the isoparametric curve at parameter u."""
@@ -568,8 +596,8 @@ def boundary(self) -> List[NurbsCurve]:
568596 def xyz (self , nu : int = 10 , nv : int = 10 ) -> List [Point ]:
569597 """Compute point locations corresponding to evenly spaced parameters over the surface domain.
570598 """
571- U , V = meshgrid (self .u_space (nu ), self .v_space (nv ), 'ij' )
572- return [self .point_at (u , v ) for u , v in zip ( flatten ( U ), flatten ( V ))]
599+ U , V = np . meshgrid (self .u_space (nu ), self .v_space (nv ), indexing = 'ij' )
600+ return [self .point_at (U [ i , j ], V [ i , j ] ) for i , j in product ( np . arange ( nu ), np . arange ( nv ))]
573601
574602 def point_at (self , u : float , v : float ) -> Point :
575603 """Compute a point on the surface.
0 commit comments