QList<RVector> RSpline::getDiscontinuities() const { updateInternal(); QList<RVector> ret; #ifndef R_NO_OPENNURBS if (isValid()) { for (int c=0; c<=11; c++) { double t0=getTMin(); double t1=getTMax(); bool found; do { double t; found = curve.GetNextDiscontinuity((ON::continuity)c, t0, t1, &t); if (found) { ret.append(getPointAt(t)); t0=t; } } while(found); } } #endif return ret; }
/** * \return List of RLines describing this spline. */ QList<QSharedPointer<RShape> > RSpline::getExploded(int segments) const { if (!exploded.isEmpty() && segments==-1) { return exploded; } //qDebug() << "RSpline::getExploded: segments: " << segments; //RDebug::printBacktrace("getExploded: "); //##boundingBox = RBox(); updateInternal(); exploded.clear(); if (!isValid()) { //qWarning() << "RSpline::getExploded: invalid spline"; return exploded; } if (segments==-1) { segments = 8; } double tMin = getTMin(); double tMax = getTMax(); double step = getTDelta() / (controlPoints.size() * segments); RVector p1; RVector prev = RVector::invalid; for (double t = tMin; t<tMax+(step/2.0); t+=step) { double tc = qMin(t, tMax); p1 = getPointAt(tc); if (RMath::isNaN(p1.x) || RMath::isNaN(p1.y)) { continue; } if (prev.isValid()) { RLine* line = new RLine(prev, p1); exploded.append(QSharedPointer<RShape>(line)); } prev = p1; //##boundingBox.growToInclude(p1); } p1 = getEndPoint(); if (!RMath::isNaN(p1.x) && !RMath::isNaN(p1.y)) { if (prev.isValid()) { RLine* line = new RLine(prev, p1); // prevent zero length line at the end: if (line->getLength()>1.0e-4) { exploded.append(QSharedPointer<RShape>(line)); } } } return exploded; }
/** * \return Tangent angle of spline at end point. */ double RSpline::getDirection2() const { if (!isValid()) { return 0.0; } updateInternal(); #ifndef R_NO_OPENNURBS ON_3dVector ontan = curve.TangentAt(getTMax()); RVector rtan(ontan.x, ontan.y); return RMath::getNormalizedAngle(rtan.getAngle() + M_PI); #else return 0.0; #endif }
double RSpline::getLength() const { if (!isValid()) { return 0.0; } if (hasProxy()) { return splineProxy->getDistanceAtT(*this, getTMax()); } else { double length = 0.0; QList<QSharedPointer<RShape> > shapes = getExploded(); for (int i=0; i<shapes.size(); i++) { QSharedPointer<RShape> shape = shapes[i]; length += shape->getLength(); } return length; } // seems to only work in the context of another product which uses OpenNURBS: // curve.GetLength(&length); }
void RSpline::print(QDebug dbg) const { dbg.nospace() << "RSpline("; RShape::print(dbg); dbg.nospace() << ", degree: " << getDegree(); dbg.nospace() << ", order: " << getOrder(); dbg.nospace() << ", closed: " << isClosed(); dbg.nospace() << ", periodic: " << isPeriodic(); dbg.nospace() << ", start point: " << getStartPoint(); dbg.nospace() << ", end point: " << getEndPoint(); dbg.nospace() << ", start tan: " << getTangentAtStart(); dbg.nospace() << ", end tan: " << getTangentAtEnd(); dbg.nospace() << ", t_min: " << getTMin(); dbg.nospace() << ", t_max: " << getTMax(); QList<RVector> controlPoints = getControlPointsWrapped(); dbg.nospace() << ",\ncontrolPoints (" << controlPoints.count() << "): "; for (int i=0; i<controlPoints.count(); ++i) { dbg.nospace() << i << ": " << controlPoints.at(i) << ", "; } QList<RVector> fitPoints = getFitPoints(); dbg.nospace() << ",\nfitPoints (" << fitPoints.count() << "): "; for (int i=0; i<fitPoints.count(); ++i) { dbg.nospace() << i << ": " << fitPoints.at(i) << ", "; } QList<double> knotVector = getKnotVector(); dbg.nospace() << ",\nknots (" << knotVector.count() << "): "; for (int i=0; i<knotVector.count(); ++i) { dbg.nospace() << i << ": " << knotVector.at(i) << ", "; } knotVector = getActualKnotVector(); dbg.nospace() << ",\ninternally used knots (" << knotVector.count() << "): "; for (int i=0; i<knotVector.count(); ++i) { dbg.nospace() << i << ": " << knotVector.at(i) << ", "; } }
RVector RSpline::getEndPoint() const { return getPointAt(getTMax()); }
double RSpline::getTDelta() const { return getTMax() - getTMin(); }