27#ifndef INC_CINOSNURBSCURVE_H
28#define INC_CINOSNURBSCURVE_H
33#define DF_INOS_NURBSCURVE_UNDIFINED_SEG_INDEX 0xFFFFFFFF
46#include <inosstdtypes.h>
48#include <cinosspline.h>
60static constexpr double BinCoeff[6 * 6] = {
61 1.0, 0.0, 0.0, 0.0, 0.0, 0.0,
62 1.0, 1.0, 0.0, 0.0, 0.0, 0.0,
63 1.0, 2.0, 1.0, 0.0, 0.0, 0.0,
64 1.0, 3.0, 3.0, 1.0, 0.0, 0.0,
65 1.0, 4.0, 6.0, 5.0, 1.0, 0.0,
66 1.0, 5.0, 10.0, 10.0, 5.0, 1.0
80 if (aPoint.
w != 0.0) {
84 if (aPoint.
w != 1.0) {
100 for (uint32 i=0; i<N; i++) {
108 void AddKnot(
double adKnot, uint32 auMultiplicity)
111 for (uint32 i=0; i<auMultiplicity; i++){
130 return (uint32)
P.size();
153 if (
P.size() < (
D+1)) {
157 D = (int)(
P.size() - 1);
178 double dk = 1.0/double(
P.size()-
D);
179 for (uint32 i=1; i<(
P.size()-
D); i++) {
186 if (
U.size() != (
P.size()+
D+1)) {
198 static constexpr double d43 = 4.0/3.0;
199 static constexpr double d13 = 1.0/3.0;
210 if((
m_uFlags & eFlgCurveValid) == 0) {
212 uint32 uError =
Check();
225 m_sPreviousCache[0].
m_dP = 0.0;
234 uint32 uNoP = (uint32)
P.size();
237 m_UofPs.resize(uNoP - 1,
nullptr);
241 if(uNoP == 2 &&
P[0] ==
P[1]) {
246 m_UofPs[0] =
new CINOSSpline(2);
249 auto Spline = m_UofPs[0];
252 Spline->SetPoint(0, 0.0, 0.0);
254 Spline->SetPoint(1, 1.0, 0.0);
264 TINOSVector<N> point1;
265 TINOSVector<N> point2;
266 TINOSVector<N> point3;
282 const double dUSeg =
U.back() / double(uNoP - 1);
284 const double du_2 =du * 0.5;
285 const double du_edge =du * 0.0001;
289 for(uint32 uIxP = 0; uIxP < uNoP - 1; uIxP++) {
294 auto Spline = m_UofPs[uIxP];
297 Spline->SetPoint(0, L, u);
300 uSeg = u = dUSeg * (double)uIxP;
314 double vStart = du_edge / ldiff;
331 ldiff = d43 * l1 - d13 * l2;
351 Spline->SetPoint(uIx, L, u);
367 double vSEnd = du_edge / l1;
370 Spline->Calc(
true, CINOSSpline::eBt1stDeriv, vStart,
371 CINOSSpline::eBt1stDeriv, vSEnd,
false);
387 double u = GetLocalU(adP, 0);
393 virtual void GetPosition(
double adP, TINOSVector<N>& ovPos, uint32& auSegment)
396 double u = GetLocalU(adP, 0);
400 auSegment = GetSegment(0, adP, ovPos);
423 else if(adU>=
U[
P.size()]) {
424 m_sPreviousCache[0].
m_uUSpan = (uint32)(
P.size()-1);
426 else if(m_sPreviousCache[0].m_uPSpan == DF_INOS_NURBSCURVE_UNDIFINED_SEG_INDEX) {
429 else if(adU >=
U[m_sPreviousCache[0].m_uUSpan + 1]) {
433 while(adU >=
U[m_sPreviousCache[0].m_uUSpan + 1]);
435 else if(adU <
U[m_sPreviousCache[0].m_uUSpan]) {
439 while(adU <
U[m_sPreviousCache[0].m_uUSpan]);
452 virtual void GetPositionU(
double adU, TINOSVector<N>& ovPos, uint32 auUSpan)
459 if (!(
m_uFlags & eFlgCustomWeight)) {
461 for(uint32 i=0;i<=
D;i++) {
462 ovPos = ovPos + (Nb[i] *
P[auUSpan-
D+i]);
468 for(uint32 i=0;i<=
D;i++) {
469 uint32 ii = auUSpan-
D+i;
470 double ww = Nb[i] *
P[ii].w;
472 ovPos = ovPos + (ww *
P[ii]);
475 ovPos = ovPos * (1.0/w);
481 virtual void GetDerivative(uint32 auLevel,
double adP, TINOSVector<N>& ovDer)
484 double u = GetLocalU(adP, auLevel);
486 GetDerivativeU(auLevel, u, ovDer);
493 GetDerivativeU(auLevel,
U.front(), ovDer);
500 GetDerivativeU(auLevel,
U.back(), ovDer);
506 virtual void GetDerivativeU(uint32 auLevel,
double adU, TINOSVector<N>& ovDer)
509 if (adU >
U.back()) adU =
U.back();
510 else if (adU <
U.front()) adU =
U.front();
524 ovDer = 1.0/l * ders[1];
527 else if (auLevel == 2) {
528 double dotProd = 0.0;
530 for(
int i = 0; i < N; i++) {
532 dotProd += ders[1][i] * ders[2][i];
533 div += ders[1][i] * ders[1][i];
542 for(
int i = 0; i < N; i++) {
544 ovDer[i] = ders[2][i] - dotProd * ders[1][i];
547 ovDer[i] = ders[2][i] ;
557 div = div * div * div * l;
565 dNom = ders[1][ixs[0]] * ders[2][ixs[1]] - ders[1][ixs[1]] * ders[2][ixs[0]];
568 TINOSVector<N> crossProd;
569 crossProd[0] = ders[1][ixs[1]] * ders[2][ixs[2]] - ders[1][ixs[2]] * ders[2][ixs[1]];
570 crossProd[1] =ders[1][ixs[2]] * ders[2][ixs[0]] - ders[1][ixs[0]] * ders[2][ixs[2]];
571 crossProd[2] = ders[1][ixs[0]] * ders[2][ixs[1]] - ders[1][ixs[1]] * ders[2][ixs[0]];
573 dNom = crossProd.GetLength();
580 ovDer = (dNom / div) * ovDer;
586 double nom = 1 / (div * div);
587 for(
int i = 0; i < N; i++) {
589 ovDer[i] = nom * ovDer[i]
606 double u =
U.front();
612 TINOSVector<N> derivatives;
613 GetDerivativeU(2, u, derivatives);
614 for (uint32 i=0; i<N; i++){
616 double dD2 = fabs(derivatives[i]);
618 if (dD2 > ovD2Max[i]){
646 uint32 u = m_UofPs.size();
651 if (adP > m_UofPs[i]->GetMaxX()) {
654 else if (adP < m_UofPs[i]->GetMinX()){
663 uint32 uIndex = DF_INOS_SPLINE_BINARY_SEARCH_INDEX;
664 return m_UofPs[i]->GetY(adP, uIndex);
667 double GetLocalU(
double adP, uint32 auChannel)
670 m_sPreviousCache[auChannel].
m_uPSpan = 0;
675 m_sPreviousCache[auChannel].
m_uPSpan = (uint32)(m_UofPs.size() - 1);
679 if(m_sPreviousCache[auChannel].m_uPSpan == DF_INOS_NURBSCURVE_UNDIFINED_SEG_INDEX) {
683 uint32 u = (uint32)m_UofPs.size();
688 if (adP > m_UofPs[i]->GetMaxX()) {
691 else if (adP < m_UofPs[i]->GetMinX()){
699 m_sPreviousCache[auChannel].
m_uPSpan = i;
701 else if(adP >= m_UofPs[m_sPreviousCache[auChannel].m_uPSpan]->GetMaxX()) {
703 m_sPreviousCache[auChannel].
m_uPSpan++;
705 while(adP >= m_UofPs[m_sPreviousCache[auChannel].m_uPSpan]->GetMaxX());
709 else if(adP < m_UofPs[m_sPreviousCache[auChannel].m_uPSpan]->GetMinX()) {
711 m_sPreviousCache[auChannel].
m_uPSpan--;
713 while(adP < m_UofPs[m_sPreviousCache[auChannel].m_uPSpan]->GetMinX());
718 return m_UofPs[m_sPreviousCache[auChannel].
m_uPSpan]->
719 GetY(adP, m_sPreviousCache[auChannel].m_uSplineIndex);
731 uint32 auLengthMask = 0xFFFFFFF8)
739 for(uint32 uD = 0; uD<N; uD++) {
747 memset(&m_sPreviousCache, 0,
sizeof(m_sPreviousCache));
748 for (uint32 i=0; i<eCnsMaxChannels; i++) {
749 m_sPreviousCache[i].
m_uPSpan = DF_INOS_NURBSCURVE_UNDIFINED_SEG_INDEX;
750 m_sPreviousCache[i].
m_uSplineIndex = DF_INOS_SPLINE_BINARY_SEARCH_INDEX;
754 m_sPreviousCache[i].
m_dP = 0.0;
761 for(
auto spline : m_UofPs) {
762 if(spline !=
nullptr) {
775 return (uint32)(
P.size()-1) ;
779 int high = (int)(
P.size()+1) ;
780 int mid = (low+high)/2 ;
781 while(u<
U[mid] || u>=
U[mid+1]){
795 double* right = &left[
D+1] ;
798 for(uint32 j=1; j<=
D ; j++){
799 left[j] = u-
U[i+1-j] ;
800 right[j] =
U[i+j]-u ;
802 for(uint32 r=0 ; r<j; r++){
803 temp = Nb[r]/(right[r+1]+left[j-r]) ;
804 Nb[r] = saved+right[r+1] * temp ;
805 saved = left[j-r] * temp ;
815 double* right = &left[
D+1] ;
820 for(
int j=1; j<=(int)
D ;j++){
821 left[j] = u-
U[span+1-j] ;
822 right[j] =
U[span+j]-u ;
826 ndu[j][r] = right[r+1]+left[j-r] ;
827 temp = ndu[r][j-1]/ndu[j][r] ;
829 ndu[r][j] = saved+right[r+1] * temp ;
830 saved = left[j-r] * temp ;
835 for(
int j=(
int)
D;j>=0;--j)
836 ders[0][j] = ndu[j][
D];
840 for (
int r=0;r<=(int)
D;r++) {
845 for (
int k=1;k<=(int)n;k++) {
849 rk = r-k ; pk =
D-k ;
851 a[s2][0] = a[s1][0]/ndu[pk+1][rk];
852 d = a[s2][0]*ndu[rk][pk] ;
866 for (j=j1;j<=j2;j++){
867 a[s2][j] = (a[s1][j]-a[s1][j-1])/ndu[pk+1][rk+j];
868 d += a[s2][j]*ndu[rk+j][pk];
871 a[s2][k] = -a[s1][k-1]/ndu[pk+1][r];
872 d += a[s2][k]*ndu[r][pk] ;
875 j = s1 ; s1 = s2 ; s2 = j ;
880 for(
int k=1;k<=(int)n;k++){
881 for(
int j=(
int)
D;j>=0;--j)
894 for (uint32 k=
D+1; k<=d; k++) ck[k] = 0.0;
903 TINOSVector<N> wders;
905 for(
int k=du;k>=0;--k){
907 for(
int j=0; j<=(int)
D; j++){
908 Aders[k] = Aders[k] + nders[k][j]*
P[span-
D+j] *
P[span-
D+j].w;
909 wders[k] = wders[k] + nders[k][j]*
P[span-
D+j].w ;
914 double wders0_inv = 1/wders[0];
916 for(uint32 k= 0; k<=d; k++) {
917 TINOSVector<N> v = Aders[k];
918 for(uint32 i=1; i<=k; i++)
919 v = v - BinCoeff[k * 6 + i]*wders[i]*ck[k-i];
920 ck[k] = v*wders0_inv;
924 for(
int k=du;k>=0;--k){
926 for(
int j=0; j<=(int)
D; j++){
927 ck[k] = ck[k] + nders[k][j]*
P[span-
D+j] ;
933 uint32 GetSegment (uint32 auChannel,
double adP, TINOSVector<N>& ovPos)
936 auto& cnl = m_sPreviousCache[auChannel];
939 if (cnl.m_dDistanceSegEnd<0.0){
942 cnl.m_dDistanceSegBeg = (
P[0]-ovPos).GetMaskedLength2(
m_uLengthMask);
946 else if(adP > cnl.m_dP) {
948 if (cnl.m_uSegment <
P.size()-2) {
950 double dDistanceOld = cnl.m_dDistanceSegEnd;
951 cnl.m_dDistanceSegEnd =
954 if (dDistanceOld<cnl.m_dDistanceSegEnd){
958 cnl.m_dDistanceSegBeg = cnl.m_dDistanceSegEnd;
960 cnl.m_dDistanceSegEnd =
965 cnl.m_dDistanceSegBeg =
971 cnl.m_dDistanceSegBeg =
976 else if(adP < cnl.m_dP) {
978 if (cnl.m_uSegment > 0) {
980 double dDistanceOld = cnl.m_dDistanceSegBeg;
981 cnl.m_dDistanceSegBeg =
984 if (dDistanceOld<cnl.m_dDistanceSegEnd){
988 cnl.m_dDistanceSegEnd = cnl.m_dDistanceSegBeg;
990 cnl.m_dDistanceSegBeg = (
P[cnl.m_uSegment]-ovPos).GetLength2(
m_uLengthMask);
994 cnl.m_dDistanceSegEnd = (
P[cnl.m_uSegment+1]-ovPos).GetLength2(
m_uLengthMask);
999 cnl.m_dDistanceSegEnd = (
P[cnl.m_uSegment+1]-ovPos).GetLength2(
m_uLengthMask);
1006 return cnl.m_uSegment;
1014 eFlgPrepared = 0x00000001,
1015 eFlgCustomWeight = 0x00000002,
1016 eFlgZeroWeight = 0x00000004,
1017 eFlgCurveValid = 0x00000008,
1020 eCnsMaxChannels = 4,
1032 double m_dLength = std::numeric_limits<double>::quiet_NaN();
1034 inos_std::vector<CINOSNurbsPoint<N>>
P;
1036 inos_std::vector<double>
U;
1062 } m_sPreviousCache[eCnsMaxChannels];
1064 inos_std::vector<CINOSSpline*> m_UofPs;
The CINOSNurbsPoint class.
#define DECLARE_DYNAMIC_N(aClass, aN)
Definition cinospartitionmemory.h:338
#define IMPLEMENT_DYNAMIC_N(aClass, aN)
Definition cinospartitionmemory.h:373
Definition cinosmovepath.h:566
Definition cinosnurbscurve.h:70
TINOSVector< N > _array_vector[DF_INOS_NURBSCURVE_MAX_DEGREE+1]
get auLevel derivative at param 'adU' (The NURBS book, page 93, A3.2)
Definition cinosnurbscurve.h:505
virtual void GetPositionLast(TINOSVector< N > &ovPos)
get last position
Definition cinosnurbscurve.h:411
void AddPoint(TINOSVector< N > &aPoint)
add control point to curve
Definition cinosnurbscurve.h:96
void BasisFuns(double u, uint32 i, _vector &Nb) const
compute the nonvanishing basis functions (The NURBS book, page 70, A2.2)
Definition cinosnurbscurve.h:792
void DersBasisFuns(uint32 n, double u, uint32 span, _matrix &ders) const
compute nonzero basis functions and their derivatives (The NURBS book, page 72, A2....
Definition cinosnurbscurve.h:812
uint32 m_uFlags
flags
Definition cinosnurbscurve.h:1024
virtual void GetD2max(TINOSVector< N > &ovD2Max)
get max. second derivative over the whole curve
Definition cinosnurbscurve.h:603
uint8 m_uNoLengthDims
numeber of length relevant dimensions
Definition cinosnurbscurve.h:1041
virtual void GetDerivativeEnd(uint32 auLevel, TINOSVector< N > &ovDer)
get auLevel derivative at curve end
Definition cinosnurbscurve.h:497
void GetPositionU(double adU, TINOSVector< N > &ovPos)
get position at param 'adU' (The NURBS book, page 124, A4.1)
Definition cinosnurbscurve.h:446
double GetLength()
get curve length
Definition cinosnurbscurve.h:202
uint32 m_uInterpolationPoints
curve interpolation points
Definition cinosnurbscurve.h:1030
uint8 m_uLengthDims[N]
length relevant dimensions indices
Definition cinosnurbscurve.h:1039
virtual void GetPositionFirst(TINOSVector< N > &ovPos)
get first position
Definition cinosnurbscurve.h:404
void CurveDerivs(double u, uint32 d, _array_vector &ck)
compute curve derivatives (The NURBS book, page 93, A3.2)
Definition cinosnurbscurve.h:889
uint32 Check()
check curve
Definition cinosnurbscurve.h:141
virtual void GetDerivativeBgn(uint32 auLevel, TINOSVector< N > &ovDer)
get auLevel derivative at curve begin
Definition cinosnurbscurve.h:490
inos_std::vector< double > U
knot vector
Definition cinosnurbscurve.h:1036
virtual void GetD3max(TINOSVector< N > &ovD3Max)
get max. 3rd derivative over the whole curve
Definition cinosnurbscurve.h:628
double GetGlobalU(double adP)
approximately project P tu U
Definition cinosnurbscurve.h:635
virtual void GetPosition(double adP, TINOSVector< N > &ovPos, uint32 &auSegment)
get position at 'adP'
Definition cinosnurbscurve.h:393
void AddKnot(double adKnot, uint32 auMultiplicity)
add knot to curve
Definition cinosnurbscurve.h:108
void GetLocalPositionU(double adU, TINOSVector< N > &ovPos)
get position at param 'adU' (The NURBS book, page 124, A4.1)
Definition cinosnurbscurve.h:418
inos_std::vector< CINOSNurbsPoint< N > > P
control points
Definition cinosnurbscurve.h:1034
CINOSNurbsCurve(uint32 auDegree=DF_INOS_NURBSCURVE_MAX_DEGREE, uint32 auInterpolationPoints=DF_INOS_NURBSCURVE_INTERPOLATION_POINTS, uint32 auLengthMask=0xFFFFFFF8)
constructor
Definition cinosnurbscurve.h:729
virtual ~CINOSNurbsCurve()
destructor
Definition cinosnurbscurve.h:759
void AddPoint(CINOSNurbsPoint< N > &aPoint)
add control point to curve
Definition cinosnurbscurve.h:77
void SetPoints(uint32 auPoints)
set number of control points
Definition cinosnurbscurve.h:120
double m_dLength
curve length
Definition cinosnurbscurve.h:1032
uint32 D
curve degree
Definition cinosnurbscurve.h:1026
virtual void GetDerivative(uint32 auLevel, double adP, TINOSVector< N > &ovDer)
get auLevel derivative at 'adP'
Definition cinosnurbscurve.h:481
uint32 FindSpan(double u) const
determine the knot span index (The NURBS book, page 68, A2.1)
Definition cinosnurbscurve.h:772
const uint32 m_uLengthMask
length mask (bit = 1 -> axis is not length relevant)
Definition cinosnurbscurve.h:1028
virtual void GetPositionU(double adU, TINOSVector< N > &ovPos, uint32 auUSpan)
get position at param 'adU' (The NURBS book, page 124, A4.1)
Definition cinosnurbscurve.h:452
void SetInterpolationPoints(uint32 auInterpolationPoints)
set number of interpolation points
Definition cinosnurbscurve.h:134
uint32 GetPoints()
get number of control points
Definition cinosnurbscurve.h:127
virtual void GetPosition(double adP, TINOSVector< N > &ovPos)
get position at 'adP'
Definition cinosnurbscurve.h:384
Definition cinosnurbspoint.h:47
double w
point weight
Definition cinosnurbspoint.h:71
#define DF_INOS_NURBSCURVE_INTERPOLATION_POINTS
Definition inosdefault.h:188
#define DF_INOS_NURBSCURVE_MAX_DEGREE
Definition inosdefault.h:180
uint32 INOS_OK
Definition inoserror.h:1681
uint32 INOS_MOVEPATH_ERROR_NURBS_RELEVANT_LENGTH_ZERO
Definition inoserror.h:1681
uint32 INOS_MOVEPATH_ERROR_NURBS_ALL_WEIGHTS_ZERO
Definition inoserror.h:1681
uint32 INOS_MOVEPATH_ERROR_NURBS_NUMBER_OF_KNOTS_INVALID
Definition inoserror.h:1681
uint32 INOS_MOVEPATH_ERROR_NURBS_NOT_ENOUGH_POINTS
Definition inoserror.h:1681
uint32 INOS_MOVEPATH_ERROR_NURBS_DEGREE_INVALID
Definition inoserror.h:1681
Definition cinosnurbscurve.h:1045
double m_dDistanceSegEnd
Distance to segment end.
Definition cinosnurbscurve.h:1057
uint32 m_uSplineIndex
current spline index
Definition cinosnurbscurve.h:1049
uint32 m_uUSpan
current span in Us
Definition cinosnurbscurve.h:1051
uint32 m_uPSpan
current span in Ps
Definition cinosnurbscurve.h:1047
uint32 m_uSegment
current segment
Definition cinosnurbscurve.h:1053
double m_dP
P value.
Definition cinosnurbscurve.h:1059
double m_dDistanceSegBeg
Distance to segment begin.
Definition cinosnurbscurve.h:1055