@@ -521,23 +521,23 @@ def find_span(n: int, p: int, u: float, U: NDArray[np.float64]) -> int:
521521 Finds the knot span index for a given parameter u.
522522 Based on Algorithm A2.1 from 'The NURBS Book'.
523523 """
524- # if u >= U[n + 1]:
525- # return n
526- #
527- ## Binary search
528- # low = p
529- # high = n + 1
530- # mid = (low + high) // 2
531- #
532- # while (u < U[mid]) or (u >= U[mid + 1]):
533- # if u < U[mid]:
534- # high = mid
535- # else:
536- # low = mid
537- # mid = (low + high) // 2
538- #
539- # return mid
540- return find_span ( n , p , u , U )
524+ if u >= U [n + 1 ]:
525+ return n
526+
527+ # Binary search
528+ low = p
529+ high = n + 1
530+ mid = (low + high ) // 2
531+
532+ while (u < U [mid ]) or (u >= U [mid + 1 ]):
533+ if u < U [mid ]:
534+ high = mid
535+ else :
536+ low = mid
537+ mid = (low + high ) // 2
538+
539+ return mid
540+
541541
542542
543543def ders_basis_funs (span_i : int , u : float , p : int , U : NDArray [np .float64 ], n_ders : int = 1 ) -> NDArray [np .float64 ]:
@@ -548,75 +548,75 @@ def ders_basis_funs(span_i: int, u: float, p: int, U: NDArray[np.float64], n_der
548548 Based on Algorithm A2.3 from 'The NURBS Book'.
549549 """
550550
551- # ders = np.zeros((n_ders + 1, p + 1))
552- # ndu = np.zeros((p + 1, p + 1))
553- # left = np.zeros(p + 1)
554- # right = np.zeros(p + 1)
555- #
556- # ndu[0, 0] = 1.0
557- #
558- ## Compute basis functions (and store terms for derivatives)
559- # for j in range(1, p + 1):
560- # left[j] = u - U[span_i + 1 - j]
561- # right[j] = U[span_i + j] - u
562- # saved = 0.0
563- # for r in range(j):
564- # # Lower triangle
565- # ndu[j, r] = right[r + 1] + left[j - r]
566- # temp = ndu[r, j - 1] / ndu[j, r]
567- # # Upper triangle
568- # ndu[r, j] = saved + right[r + 1] * temp
569- # saved = left[j - r] * temp
570- # ndu[j, j] = saved
571- #
572- ## Load the basis functions
573- # for j in range(p + 1):
574- # ders[0, j] = ndu[j, p]
575- #
576- ## Compute derivatives
577- # a = np.zeros((2, p + 1)) # Only need rows 0 and 1 for recursion locally
578- # for r in range(0, p + 1):
579- # s1 = 0
580- # s2 = 1
581- # a[0, 0] = 1.0
582- #
583- # # Loop to compute k-th derivative
584- # for k in range(1, n_ders + 1):
585- # d = 0.0
586- # rk = r - k
587- # pk = p - k
588- #
589- # if r >= k:
590- # a[s2, 0] = a[s1, 0] / ndu[pk + 1, rk]
591- # d = a[s2, 0] * ndu[rk, pk]
592- #
593- # j1 = 1 if rk >= -1 else -rk
594- # j2 = k - 1 if (r - 1) <= pk else p - r
595- #
596- # for j in range(j1, j2 + 1):
597- # a[s2, j] = (a[s1, j] - a[s1, j - 1]) / ndu[pk + 1, rk + j]
598- # d += a[s2, j] * ndu[rk + j, pk]
599- #
600- # if r <= pk:
601- # a[s2, k] = -a[s1, k - 1] / ndu[pk + 1, r]
602- # d += a[s2, k] * ndu[r, pk]
603- #
604- # ders[k, r] = d
605- #
606- # # Swap rows
607- # j = s1
608- # s1 = s2
609- # s2 = j
610- #
611- ## Multiply by correct factors for derivatives
612- # r = p
613- # for k in range(1, n_ders + 1):
614- # for j in range(p + 1):
615- # ders[k, j] *= r
616- # r *= (p - k)
617- #
618- # return ders
619- return _ders_basis_funs ( span_i , u , p , U , n_ders )
551+ ders = np .zeros ((n_ders + 1 , p + 1 ))
552+ ndu = np .zeros ((p + 1 , p + 1 ))
553+ left = np .zeros (p + 1 )
554+ right = np .zeros (p + 1 )
555+
556+ ndu [0 , 0 ] = 1.0
557+
558+ # Compute basis functions (and store terms for derivatives)
559+ for j in range (1 , p + 1 ):
560+ left [j ] = u - U [span_i + 1 - j ]
561+ right [j ] = U [span_i + j ] - u
562+ saved = 0.0
563+ for r in range (j ):
564+ # Lower triangle
565+ ndu [j , r ] = right [r + 1 ] + left [j - r ]
566+ temp = ndu [r , j - 1 ] / ndu [j , r ]
567+ # Upper triangle
568+ ndu [r , j ] = saved + right [r + 1 ] * temp
569+ saved = left [j - r ] * temp
570+ ndu [j , j ] = saved
571+
572+ # Load the basis functions
573+ for j in range (p + 1 ):
574+ ders [0 , j ] = ndu [j , p ]
575+
576+ # Compute derivatives
577+ a = np .zeros ((2 , p + 1 )) # Only need rows 0 and 1 for recursion locally
578+ for r in range (0 , p + 1 ):
579+ s1 = 0
580+ s2 = 1
581+ a [0 , 0 ] = 1.0
582+
583+ # Loop to compute k-th derivative
584+ for k in range (1 , n_ders + 1 ):
585+ d = 0.0
586+ rk = r - k
587+ pk = p - k
588+
589+ if r >= k :
590+ a [s2 , 0 ] = a [s1 , 0 ] / ndu [pk + 1 , rk ]
591+ d = a [s2 , 0 ] * ndu [rk , pk ]
592+
593+ j1 = 1 if rk >= - 1 else - rk
594+ j2 = k - 1 if (r - 1 ) <= pk else p - r
595+
596+ for j in range (j1 , j2 + 1 ):
597+ a [s2 , j ] = (a [s1 , j ] - a [s1 , j - 1 ]) / ndu [pk + 1 , rk + j ]
598+ d += a [s2 , j ] * ndu [rk + j , pk ]
599+
600+ if r <= pk :
601+ a [s2 , k ] = - a [s1 , k - 1 ] / ndu [pk + 1 , r ]
602+ d += a [s2 , k ] * ndu [r , pk ]
603+
604+ ders [k , r ] = d
605+
606+ # Swap rows
607+ j = s1
608+ s1 = s2
609+ s2 = j
610+
611+ # Multiply by correct factors for derivatives
612+ r = p
613+ for k in range (1 , n_ders + 1 ):
614+ for j in range (p + 1 ):
615+ ders [k , j ] *= r
616+ r *= (p - k )
617+
618+ return ders
619+
620620
621621
622622def generate_hermite_knots (params : NDArray [np .float64 ], p : int ) -> NDArray [np .float64 ]:
0 commit comments