Skip to content

Commit 4958745

Browse files
committed
flip directions and add triangles export
1 parent 556c868 commit 4958745

File tree

1 file changed

+36
-8
lines changed
  • src/compas_occ/geometry/surfaces

1 file changed

+36
-8
lines changed

src/compas_occ/geometry/surfaces/nurbs.py

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
from __future__ import annotations
2+
from itertools import product
23

34
from typing import Generator, Optional, Tuple, List, Dict
45

6+
import numpy as np
7+
58
from compas.geometry import Point, Vector, Line, Frame, Box
69
from compas.geometry import Transformation
710
from 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

Comments
 (0)