/** * \return List of bezier spline segments which together represent this curve. */ QList<RSpline> RSpline::getBezierSegments() const { // spline is a single bezier segment: if (countControlPoints()==getDegree()+1) { return QList<RSpline>() << *this; } updateInternal(); QList<RSpline> ret; #ifndef R_NO_OPENNURBS ON_NurbsCurve* dup = dynamic_cast<ON_NurbsCurve*>(curve.DuplicateCurve()); if (dup==NULL) { return ret; } dup->MakePiecewiseBezier(); for (int i=0; i<=dup->CVCount() - dup->Order(); ++i) { ON_BezierCurve bc; if (!dup->ConvertSpanToBezier(i, bc)) { continue; } QList<RVector> ctrlPts; for (int cpi=0; cpi<bc.CVCount(); cpi++) { ON_3dPoint onp; bc.GetCV(cpi, onp); ctrlPts.append(RVector(onp.x, onp.y, onp.z)); } ret.append(RSpline(ctrlPts, degree)); } delete dup; #endif return ret; }
/** * Cubic bezier approximation of a circular arc centered at the origin, * from (radians) a1 to a2, where a2-a1 < pi/2. The arc's radius is r. * * Returns an spline approximation. * * This algorithm is based on the approach described in: * A. Riškus, "Approximation of a Cubic Bezier Curve by Circular Arcs and Vice Versa," * Information Technology and Control, 35(4), 2006 pp. 371-378. */ RSpline RSpline::createBezierFromSmallArc(double r, double a1, double a2) { // Compute all four points for an arc that subtends the same total angle // but is centered on the X-axis double a = (a2 - a1) / 2.0; // double x4 = r * cos(a); double y4 = r * sin(a); double x1 = x4; double y1 = -y4; //double k = 0.552284749831; //double k = 4.0/3.0*(sqrt(2.0)-1.0); //double f = k * tan(a); double q1 = x1*x1 + y1*y1; double q2 = q1 + x1*x4 + y1*y4; double k2 = 4/3 * (sqrt(2 * q1 * q2) - q2) / (x1 * y4 - y1 * x4); double x2 = x1 - k2 * y1; double y2 = y1 + k2 * x1; //double x2 = x1 + f * y4; //double y2 = y1 + f * x4; double x3 = x2; double y3 = -y2; // Find the arc points actual locations by computing x1,y1 and x4,y4 // and rotating the control points by a + a1 double ar = a + a1; double cos_ar = cos(ar); double sin_ar = sin(ar); QList<RVector> ctrlPts; ctrlPts << RVector( r * cos(a1), r * sin(a1) ) << RVector( x2 * cos_ar - y2 * sin_ar, x2 * sin_ar + y2 * cos_ar ) << RVector( x3 * cos_ar - y3 * sin_ar, x3 * sin_ar + y3 * cos_ar ) << RVector( r * cos(a2), r * sin(a2) ); // qDebug() << "ctrlPts: " << ctrlPts[0]; // qDebug() << "ctrlPts: " << ctrlPts[1]; // qDebug() << "ctrlPts: " << ctrlPts[2]; // qDebug() << "ctrlPts: " << ctrlPts[3]; return RSpline(ctrlPts, 2); }