18 #ifndef __UT_FitCubicImpl__
19 #define __UT_FitCubicImpl__
21 #ifndef __UT_FitCubic_H__
22 #error Do not include this file directly. Include UT_FitCubic.h instead.
32 #define ACUTE_ANGLE 1.6
33 #define MAXITERATIONS 4
46 Span *node =
new Span;
50 node->point[0] = fcurve[0];
51 node->point[1] = fcurve[1];
52 node->point[2] = fcurve[2];
53 node->isLinear = islinear;
93 myHead = myHead->next;
101 template <
typename T>
104 bool preserveExtrema,
bool use_kupan_slopes)
107 Span *tail=0, *headS, *tailS;
128 if(boss->
opStart(
"Fitting Curve"))
135 findCorner(d, start, last, &corner);
142 nsegs = fitLine(d, start, corner, &headS, &tailS, 1);
144 nsegs = fitLine(d, start, corner, &headS, &tailS, 0);
149 if (use_kupan_slopes)
150 tHat1 = computeMonotonicTangent(d, start);
152 tHat1 = computeCenterTangent(d, start);
154 if (use_kupan_slopes)
155 tHat2 = computeMonotonicTangent(d, corner);
157 tHat2 = computeCenterTangent(d, corner);
160 if (closed && (corner==last) && !isSeamCorner(d, last))
164 tHat1 = tHat2*(-1.0);
166 nsegs = fitCubic(d, start, corner, tHat1, tHat2,
167 &headS, &tailS, preserveExtrema,
168 use_kupan_slopes, boss);
194 }
while(start < last);
209 template <
typename T>
219 for (i=first+2; i<last-2; ++i)
229 theta = SYSacos(v1.
dot(v2));
243 template <
typename T>
253 if (last<2)
return 1;
258 v2 = d[last-1] - d[0];
261 theta = SYSacos(v1.
dot(v2));
278 template <
typename T>
281 Span **
head, Span **tail,
295 npts = last - first + 1;
302 fcurve[0] = d[
first];
304 fcurve[1] = fcurve[0] + temp1*
dist;
305 fcurve[2] = fcurve[3] + temp2*
dist;
311 *head = *tail = appendCurve(fcurve, 1);
317 u = chordLengthParameterize(d, first, last);
318 maxError2 = computeLineError(d, first, last, fcurve, u, &maxi);
321 if (maxError2 < myError2)
323 *tail = *head = appendCurve(fcurve, 1);
328 nsegs = fitLine(d, first, maxi, &headL, &tailL, recurse);
329 nsegs += fitLine(d, maxi, last, &headR, &tailR, recurse);
331 if(headL && tailL && headR && tailR)
337 else if(headL && tailL)
364 template <
typename T>
367 Vector2 tHat2, Span **head, Span **tail,
368 bool preserveExtrema,
bool use_kupan_slopes,
UT_Interrupt *boss)
384 npts = last - first + 1;
387 Vector2 tempv(d[first] - d[last]);
388 fpreal dist = tempv.length() / 3.0;
389 rcurve[0] = d[
first];
391 rcurve[1] = rcurve[0] + tHat1*
dist;
392 rcurve[2] = rcurve[3] + tHat2*
dist;
393 *head = *tail = appendCurve(rcurve, 1);
401 u = chordLengthParameterize(d, first, last);
402 generateBezier(d, first, last, u, tHat1, tHat2, rcurve);
403 maxError2 = computeBezierError(d, first, last, rcurve, u, &splitPoint);
407 simpleCurve(d, first, last, tHat1, tHat2, rcurve);
408 maxError2 = computeCubicError(d, first, last, rcurve, &splitPoint,
413 if (maxError2 < myError2)
416 *tail = *head = appendCurve(rcurve, 0);
429 iterationError = myError2 * myError2;
430 if (maxError2 < iterationError)
434 uPrime = reparameterize(d, first, last, u, rcurve);
435 generateBezier(d, first, last, uPrime, tHat1, tHat2, rcurve);
436 maxError2 = computeBezierError(d, first, last, rcurve,
437 uPrime, &splitPoint);
438 if (maxError2 < myError2)
442 *tail = *head = appendCurve(rcurve, 0);
452 if (uPrime)
delete [] uPrime;
463 if (use_kupan_slopes)
464 tHatCenter = computeMonotonicTangent(d, splitPoint);
466 tHatCenter = computeCenterTangent(d, splitPoint);
468 nsegs = fitCubic(d, first, splitPoint, tHat1, tHatCenter, &headL,
469 &tailL, preserveExtrema, use_kupan_slopes, boss);
473 nsegs += fitCubic(d, splitPoint, last, tHatCenter, tHat2, &headR,
474 &tailR, preserveExtrema, use_kupan_slopes, boss);
478 if(headL && tailL && headR && tailR)
484 else if(headL && tailL)
519 template <
typename T>
526 fpreal dist = tempv.length() / 3.0;
528 rcurve[0] = d[
first];
530 rcurve[1] = rcurve[0] + tHat1*
dist;
531 rcurve[2] = rcurve[3] + tHat2*
dist;
535 template <
typename T>
539 Vector2 tHat2, CubicCurve rcurve)
552 npts = last - first + 1;
567 for (i=0; i<npts; i++) {
568 A0[i] = tHat1*BEZ_MULT_1(uPrime[i]);
569 A1[i] = tHat2*BEZ_MULT_2(uPrime[i]);
580 for (i = 0; i < npts; i++)
582 C[0][0] += A0[i].
dot(A0[i]);
583 C[0][1] += A0[i].
dot(A1[i]);
585 C[1][1] += A1[i].
dot(A1[i]);
587 tmp = d[
last]*BEZ_MULT_3(uPrime[i]);
588 tmp += d[
last]*BEZ_MULT_2(uPrime[i]);
589 tmp += d[
first]*BEZ_MULT_1(uPrime[i]);
590 tmp += d[
first]*BEZ_MULT_0(uPrime[i]);
591 tmp = d[first+i] - tmp;
593 X[0] += A0[i].
dot(tmp);
594 X[1] += A1[i].
dot(tmp);
602 det_C0_C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1];
603 det_C0_X = C[0][0] * X[1] - C[0][1] * X[0];
604 det_X_C1 = X[0] * C[1][1] - X[1] * C[0][1];
609 alpha_l = alpha_r = 0;
613 alpha_l = det_X_C1 / det_C0_C1;
614 alpha_r = det_C0_X / det_C0_C1;
617 if (alpha_l < 0.0 || alpha_r < 0.0)
619 simpleCurve(d, first, last, tHat1, tHat2, rcurve);
628 rcurve[0] = d[
first];
630 rcurve[1] = rcurve[0] + tHat1*alpha_l;
631 rcurve[2] = rcurve[3] + tHat2*alpha_r;
643 template <
typename T>
648 int npts = last-first+1;
652 uPrime =
new T[npts];
654 for (i = first; i <=
last; i++)
655 uPrime[i-first] = newtonRaphsonRootFind(fcurve, d[i], u[i- first]);
667 template <
typename T>
671 fpreal numerator, denominator;
679 Q_u = calcBezier3(Q, u);
682 for (i = 0; i <= 2; i++)
683 Q1[i] = (Q[i+1] - Q[i]) * 3.0;
686 for (i = 0; i <= 1; i++)
687 Q2[i] = (Q1[i+1] - Q1[i]) * 2.0;
691 Q1_u = calcBezier2(Q1, u);
693 Q2_u = Q2[0]*(1.0-u);
697 numerator = Q1_u.
dot(Q_u - P);
698 denominator = Q1_u.length2() + Q2_u.
dot(Q_u - P);
704 uPrime = u - (numerator/denominator);
719 template <
typename T>
737 Vtemp[0] = Vtemp[0]*u;
738 Vtemp[0] += Vtemp[1]*
t;
740 Vtemp[1] = Vtemp[1]*u;
741 Vtemp[1] += Vtemp[2]*
t;
743 Vtemp[0] = Vtemp[0]*u;
744 Vtemp[0] += Vtemp[1]*
t;
750 template <
typename T>
765 Vtemp[0] = Vtemp[0]*u;
766 Vtemp[0] += Vtemp[1]*
t;
771 template <
typename T>
787 ml = (V[1].
y() - V[0].
y()) / (V[1].
x() - V[0].
x());
788 mh = (V[3].
y() - V[2].
y()) / (V[3].
x() - V[2].
x());
799 a = m0 + m1 + 2*(y0 -
y1);
800 b = 3*(y1-y0) - m1 - 2*m0;
804 x = (t - xl) / (xh - xl);
806 vec.
assign(t, a*x*x*x + b*x*x + c*x + d - (yh-yl));
818 template <
typename T>
829 i1 = myClosed ? (myNumPoints - 1) : 0;
831 if (i2 >= myNumPoints)
832 i2 = myClosed ? 0 : (myNumPoints - 1);
834 tHatCenter = d[
i1] - d[
i2];
835 tHatCenter.normalize();
840 template <
typename T>
850 if (i2 >= myNumPoints)
855 else if (i2 >= myNumPoints)
886 template <
typename T>
894 u =
new T[last-first+1];
898 for (i = first+1; i <=
last; i++)
900 tempv = d[i] - d[i-1];
901 u[i-
first] = u[i-first-1] + tempv.length();
904 for (i = first+1; i <=
last; i++)
905 u[i-first] = u[i-first] / u[last-first];
918 template <
typename T>
921 CubicCurve rcurve, T *u,
int *splitPoint)
930 *splitPoint =
int((first+last) * 0.5);
932 for (i = first + 1; i <
last; i++)
934 P = calcBezier3(rcurve, u[i-first]);
947 template <
typename T>
950 CubicCurve rcurve,
int *splitPoint,
951 bool preserveExtrema)
961 int typeLocal = SYSisGreater(d[first+1].
y(), localVal) ? +1 :
962 (SYSisLess(d[first+1].
y(), localVal) ? -1 : 0);
965 *splitPoint =
int((first+last) * 0.5);
967 for (i = first + 1; i <
last; i++)
969 P = calcCubic(rcurve, d[i].
x());
970 dist = SYSpow(P.y() - d[i].y(),
T(2.0));
979 if ((SYSisLess(d[i].
y(), localVal) && typeLocal == -1)
980 || (SYSisGreater(d[i].
y(), localVal) && typeLocal == 1)
981 || (
SYSisEqual(localVal, d[i].
y()) && typeLocal == 0))
988 *splitPoint = iLocal;
1004 template <
typename T>
1007 CubicCurve rcurve, T *u,
int *maxi)
1019 for (i = first + 1; i <
last; i++)
1021 P = rcurve[0]*(1-u[i-
first]);
1022 P += rcurve[3]*u[i-
first];
1025 if (dist >= maxDist)
1035 #endif // __UT_FitCubicImpl__
typedef int(APIENTRYP RE_PFNGLXSWAPINTERVALSGIPROC)(int)
GA_API const UT_StringHolder dist
UT_StringArray JOINTS head
GLboolean GLboolean GLboolean GLboolean a
GLfloat GLfloat GLfloat v2
constexpr SYS_FORCE_INLINE T & x() noexcept
int opInterrupt(int percent=-1)
static Vector2 calcCubic(Vector2 *V, fpreal t)
GLboolean GLboolean GLboolean b
static fpreal64 getMonotoneSlopePA(fpreal64 v_cur, fpreal64 t_cur, fpreal64 v_prev, fpreal64 t_prev, fpreal64 v_next, fpreal64 t_next)
bool SYSequalZero(const UT_Vector3T< T > &v)
__hostdev__ uint64_t last(uint32_t i) const
constexpr SYS_FORCE_INLINE void negate() noexcept
UT_API UT_Interrupt * UTgetInterrupt()
Obtain global UT_Interrupt singleton.
S dot(const V &rhs) const
Return the dot product of two vectors.
int opStart(const char *opname=0, int npoll=0, int immediate_dialog=0, int *opid=0)
void assign(T xx=0.0f, T yy=0.0f)
Set the values of the vector components.
int fitCurve(Vector2 *d, int nPts, int closed, fpreal error2, bool preserveExtrema, bool use_kupan_slopes=false)
bool SYSisEqual(const UT_Vector2T< T > &a, const UT_Vector2T< T > &b, S tol=SYS_FTOLERANCE)
Componentwise equality.
SYS_FORCE_INLINE UT_StorageMathFloat_t< T > normalize() noexcept
constexpr SYS_FORCE_INLINE T & y() noexcept