orbingol / NURBS-Python

Object-oriented pure Python B-Spline and NURBS library
https://onurraufbingol.com/NURBS-Python/
MIT License
636 stars 156 forks source link

run NURBS Surface example but "ZeroDivisionError" #146

Open goldengrape opened 2 years ago

goldengrape commented 2 years ago

Describe the bug run NURBS Surface example https://nurbs-python.readthedocs.io/en/5.x/module_nurbs.html#nurbs-surface

but failed.

To Reproduce Steps to reproduce the behavior:

from geomdl import NURBS

# Create a NURBS surface instance
surf = NURBS.Surface()

# Set degrees
surf.degree_u = 3
surf.degree_v = 2

# Set control points (weights vector will be 1 by default)
# Use curve.ctrlptsw is if you are using homogeneous points as Pw
control_points = [[0, 0, 0], [0, 4, 0], [0, 8, -3],
                  [2, 0, 6], [2, 4, 0], [2, 8, 0],
                  [4, 0, 0], [4, 4, 0], [4, 8, 3],
                  [6, 0, 0], [6, 4, -3], [6, 8, 0]]
surf.set_ctrlpts(control_points, 4, 3)

# Set knot vectors
surf.knotvector_u = [0, 0, 0, 0, 1, 1, 1, 1]
surf.knotvector_v = [0, 0, 0, 1, 1, 1]

# Set evaluation delta (control the number of surface points)
surf.delta = 0.05

# Get surface points (the surface will be automatically evaluated)
surface_points = surf.evalpts

The error message:

ZeroDivisionError                         Traceback (most recent call last)
..\AppData\Local\Temp/ipykernel_21148/3509177292.py in <module>
     24 
     25 # Get surface points (the surface will be automatically evaluated)
---> 26 surface_points = surf.evalpts

~\miniconda3\lib\site-packages\geomdl\abstract.py in evalpts(self)
    263         """
    264         if self._eval_points is None or len(self._eval_points) == 0:
--> 265             self.evaluate()
    266         return self._eval_points
    267 

~\miniconda3\lib\site-packages\geomdl\BSpline.py in evaluate(self, **kwargs)
    614 
    615         # Evaluate and cache
--> 616         self._eval_points = self._evaluator.evaluate(self.data,
    617                                                      start=(start_u, start_v),
    618                                                      stop=(stop_u, stop_v))

~\miniconda3\lib\site-packages\geomdl\evaluators.py in evaluate(self, datadict, **kwargs)
    395         eval_points = []
    396         for pt in cptw:
--> 397             cpt = [float(c / pt[-1]) for c in pt[0:(dimension - 1)]]
    398             eval_points.append(cpt)
    399 

~\miniconda3\lib\site-packages\geomdl\evaluators.py in <listcomp>(.0)
    395         eval_points = []
    396         for pt in cptw:
--> 397             cpt = [float(c / pt[-1]) for c in pt[0:(dimension - 1)]]
    398             eval_points.append(cpt)
    399 

ZeroDivisionError: float division by zero

Expected Behavior I had tried to reduce surf.delta to 0.01, 0.005, also got ZeroDivisionError

Configuration:

NGrillanda commented 1 year ago

I have exactly the same problem! Has there been any progress on this?

NGrillanda commented 1 year ago

The problem can be solved by using homogenous control points as follows. I'll copy-past here my example.

from geomdl import NURBS as nrb from geomdl import compatibility as compat

SURFACE EXAMPLE

Define surface object

srf = nrb.Surface()

Assign surface degrees

srf.degree_u = 3 srf.degree_v = 1

Assign control points. Here control points must be merged with weights and then flipped (python use the v-order)

control_points = [[0, 0, 0], [0, 0, 1], [2, 0, 1], [2, 0, 0], [0, 1, 0], [0, 1, 1], [2, 1, 1], [2, 1, 0]] weights = [1, 1, 1, 1, 1, 1, 1, 1] control_points_w = compat.combine_ctrlpts_weights(control_points, weights) points_size_u = 4 points_size_v = 2 control_points_w = compat.flip_ctrlpts_u(control_points_w, points_size_u, points_size_v) srf.set_ctrlpts(control_points_w, points_size_u, points_size_v)

Assign knot vectors

srf.knotvector_u = [0, 0, 0, 0, 1, 1, 1, 1] srf.knotvector_v = [0, 0, 1, 1]

Parameters used as steps for point evaluation

srf.delta_u = 0.2 srf.delta_v = 0.2 points = srf.evalpts