surfaces.py 1.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. # Copyright (c) 2012 Manfred Moitzi
  2. # License: MIT License
  3. from typing import List, Sequence
  4. from .bezier import bernstein_basis
  5. Vector = Sequence[float]
  6. class BezierSurface:
  7. def __init__(self, defpoints: List[List[Vector]]):
  8. """
  9. BezierSurface constructor
  10. Args:
  11. defpoints: defpoints is matrix (list of lists) of m rows and n columns.
  12. [ [m1n1, m1n2, ... ], [m2n1, m2n2, ...] ... ]
  13. each element is a 3D point (x, y, z) tuple or list
  14. """
  15. self._defpoints = defpoints
  16. self.nrows = len(defpoints)
  17. self.ncols = len(defpoints[0])
  18. def appoximate(self, usegs: int, vsegs: int) -> List[List[Vector]]:
  19. stepu = 1.0 / float(usegs)
  20. stepv = 1.0 / float(vsegs)
  21. result = [[None] * self.ncols] * self.nrows # type: List[List[Vector]]
  22. for u_index in range(usegs + 1):
  23. u = stepu * u_index
  24. for v_index in range(vsegs + 1):
  25. v = stepv * v_index
  26. result[u_index][v_index] = self.get_point(u, v)
  27. return result
  28. def get_point(self, u: float, v: float) -> Vector:
  29. """ u, v in range [0.0, 1.0].
  30. """
  31. point = [0.0, 0.0, 0.0]
  32. for irow in range(self.nrows):
  33. rowbasis = bernstein_basis(self.nrows, irow, u)
  34. row = self._defpoints[irow]
  35. for col in range(self.ncols):
  36. colbasis = bernstein_basis(self.ncols, col, v)
  37. for axis in (0, 1, 2):
  38. point[axis] += row[col][axis] * rowbasis * colbasis
  39. return point