X-Git-Url: http://shamusworld.gotdns.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fbase%2Fspline.cpp;fp=src%2Fbase%2Fspline.cpp;h=0000000000000000000000000000000000000000;hb=9f6ad3fe0b9cb30115a5d38e8af3aebed0d70c08;hp=37d9ee0bddb8ace7bc7c23d59c045ce7087b8650;hpb=43c13b052d069ba435277d93867380d00c04931f;p=architektonas diff --git a/src/base/spline.cpp b/src/base/spline.cpp deleted file mode 100644 index 37d9ee0..0000000 --- a/src/base/spline.cpp +++ /dev/null @@ -1,738 +0,0 @@ -// spline.cpp -// -// Part of the Architektonas Project -// Originally part of QCad Community Edition by Andrew Mustun -// Extensively rewritten and refactored by James L. Hammons -// Portions copyright (C) 2001-2003 RibbonSoft -// Copyright (C) 2010 Underground Software -// See the README and GPLv2 files for licensing and warranty information -// -// JLH = James L. Hammons -// -// Who When What -// --- ---------- ----------------------------------------------------------- -// JLH 06/02/2010 Added this text. :-) -// - -#include "spline.h" - -#include "debug.h" -#include "graphicview.h" -#include "drawing.h" -#include "paintinterface.h" - -/** - * Constructor. - */ -Spline::Spline(EntityContainer * parent, const SplineData & d): - EntityContainer(parent), data(d) -{ - calculateBorders(); -} - -/** - * Destructor. - */ -Spline::~Spline() -{ -} - -Entity * Spline::clone() -{ - Spline * l = new Spline(*this); -#warning "!!! Need to deal with setAutoDelete() Qt3->Qt4 !!!" -// l->entities.setAutoDelete(entities.autoDelete()); - l->initId(); - l->detach(); - return l; -} - -/** @return RS2::EntitySpline */ -/*virtual*/ RS2::EntityType Spline::rtti() const -{ - return RS2::EntitySpline; -} - -/** @return false */ -/*virtual*/ bool Spline::isEdge() const -{ - return false; -} - -/** @return Copy of data that defines the spline. */ -SplineData Spline::getData() const -{ - return data; -} - -/** Sets the splines degree (1-3). */ -void Spline::setDegree(int deg) -{ - if (deg >= 1 && deg <= 3) - data.degree = deg; -} - -/** @return Degree of this spline curve (1-3).*/ -int Spline::getDegree() -{ - return data.degree; -} - -/** @return 0. */ -int Spline::getNumberOfKnots() -{ - return 0; -} - -/** @return Number of control points. */ -int Spline::getNumberOfControlPoints() -{ - return data.controlPoints.count(); -} - -/** - * @retval true if the spline is closed. - * @retval false otherwise. - */ -bool Spline::isClosed() -{ - return data.closed; -} - -/** - * Sets the closed falg of this spline. - */ -void Spline::setClosed(bool c) -{ - data.closed = c; - update(); -} - -void Spline::calculateBorders() -{ - /*minV = Vector::minimum(data.startpoint, data.endpoint); - maxV = Vector::maximum(data.startpoint, data.endpoint); - - Q3ValueList::iterator it; - for (it = data.controlPoints.begin(); - it!=data.controlPoints.end(); ++it) { - - minV = Vector::minimum(*it, minV); - maxV = Vector::maximum(*it, maxV); -} - */ -} - -VectorSolutions Spline::getRefPoints() -{ - VectorSolutions ret(data.controlPoints.count()); - - int i = 0; - QList::iterator it; - - for(it=data.controlPoints.begin(); it!=data.controlPoints.end(); ++it, ++i) - { - ret.set(i, (*it)); - } - - return ret; -} - -Vector Spline::getNearestRef(const Vector & coord, double * dist) -{ - //return getRefPoints().getClosest(coord, dist); - return Entity::getNearestRef(coord, dist); -} - -Vector Spline::getNearestSelectedRef(const Vector & coord, double * dist) -{ - //return getRefPoints().getClosest(coord, dist); - return Entity::getNearestSelectedRef(coord, dist); -} - -/** - * Updates the internal polygon of this spline. Called when the - * spline or it's data, position, .. changes. - */ -void Spline::update() -{ - DEBUG->print("Spline::update"); - - clear(); - - if (isUndone()) - return; - - if (data.degree < 1 || data.degree > 3) - { - DEBUG->print("Spline::update: invalid degree: %d", data.degree); - return; - } - - if (data.controlPoints.count() < (uint)data.degree + 1) - { - DEBUG->print("Spline::update: not enough control points"); - return; - } - - resetBorders(); - -// Q3ValueList tControlPoints = data.controlPoints; - QList tControlPoints = data.controlPoints; - - if (data.closed) - { - for(int i=0; i::iterator it; - QList::iterator it; - i = 1; - - for(it=tControlPoints.begin(); it!=tControlPoints.end(); ++it) - { - b[i + 0] = (*it).x; - b[i + 1] = (*it).y; - b[i + 2] = 0.0; - - DEBUG->print("Spline::update: b[%d]: %f/%f", i, b[i], b[i + 1]); - i += 3; - } - - // set all homogeneous weighting factors to 1.0 - for(i=1; i<=npts; i++) - h[i] = 1.0; - - for(i=1; i<=3*p1; i++) - p[i] = 0.0; - - if (data.closed) - rbsplinu(npts, k, p1, b, h, p); - else - rbspline(npts, k, p1, b, h, p); - - Vector prev(false); - - for(i=1; i<=3*p1; i=i+3) - { - if (prev.valid) - { - Line * line = new Line(this, LineData(prev, Vector(p[i], p[i + 1]))); - line->setLayer(NULL); - line->setPen(Pen(RS2::FlagInvalid)); - addEntity(line); - } - - prev = Vector(p[i], p[i+1]); - minV = Vector::minimum(prev, minV); - maxV = Vector::maximum(prev, maxV); - } - - delete[] b; - delete[] h; - delete[] p; -} - -Vector Spline::getNearestEndpoint(const Vector & coord, double * dist) -{ - double minDist = RS_MAXDOUBLE; - double d; - Vector ret(false); - - for (uint i=0; i::iterator it; - QList::iterator it; - - for(it=data.controlPoints.begin(); it!=data.controlPoints.end(); ++it) - (*it).move(offset); - - update(); -} - -void Spline::rotate(Vector center, double angle) -{ -// Q3ValueList::iterator it; - QList::iterator it; - - for(it=data.controlPoints.begin(); it!=data.controlPoints.end(); ++it) - (*it).rotate(center, angle); - - update(); -} - -void Spline::scale(Vector center, Vector factor) -{ -// Q3ValueList::iterator it; - QList::iterator it; - - for(it=data.controlPoints.begin(); it!=data.controlPoints.end(); ++it) - (*it).scale(center, factor); - - update(); -} - -void Spline::mirror(Vector axisPoint1, Vector axisPoint2) -{ -// Q3ValueList::iterator it; - QList::iterator it; - - for(it=data.controlPoints.begin(); it!=data.controlPoints.end(); ++it) - (*it).mirror(axisPoint1, axisPoint2); - - update(); -} - -void Spline::moveRef(const Vector & ref, const Vector & offset) -{ -// Q3ValueList::iterator it; - QList::iterator it; - - for(it=data.controlPoints.begin(); it!=data.controlPoints.end(); ++it) - { - if (ref.distanceTo(*it) < 1.0e-4) - (*it).move(offset); - } - - update(); -} - -void Spline::draw(PaintInterface * painter, GraphicView * view, double /*patternOffset*/) -{ - if (painter == NULL || view == NULL) - return; - - Entity * e = firstEntity(RS2::ResolveNone); - double offset = 0.0; - - if (e != NULL) - { - view->drawEntity(e); - offset += e->getLength(); - //DEBUG->print("offset: %f\nlength was: %f", offset, e->getLength()); - } - - for (Entity * e=nextEntity(RS2::ResolveNone); e!=NULL; e = nextEntity(RS2::ResolveNone)) - { - view->drawEntityPlain(e, -offset); - offset += e->getLength(); - //DEBUG->print("offset: %f\nlength was: %f", offset, e->getLength()); - } -} - -/** - * Todo: draw the spline, user patterns. - */ -/* -void Spline::draw(RS_Painter* painter, GraphicView* view) { - if (painter==NULL || view==NULL) { - return; - } - - / * - if (data.controlPoints.count()>0) { - Vector prev(false); - Q3ValueList::iterator it; - for (it = data.controlPoints.begin(); it!=data.controlPoints.end(); ++it) { - if (prev.valid) { - painter->drawLine(view->toGui(prev), - view->toGui(*it)); - } - prev = (*it); - } - } - * / - - int i; - int npts = data.controlPoints.count(); - // order: - int k = 4; - // resolution: - int p1 = 100; - - double* b = new double[npts*3+1]; - double* h = new double[npts+1]; - double* p = new double[p1*3+1]; - - Q3ValueList::iterator it; - i = 1; - for (it = data.controlPoints.begin(); it!=data.controlPoints.end(); ++it) { - b[i] = (*it).x; - b[i+1] = (*it).y; - b[i+2] = 0.0; - - DEBUG->print("Spline::draw: b[%d]: %f/%f", i, b[i], b[i+1]); - i+=3; - } - - // set all homogeneous weighting factors to 1.0 - for (i=1; i <= npts; i++) { - h[i] = 1.0; - } - - // - for (i = 1; i <= 3*p1; i++) { - p[i] = 0.0; - } - - rbspline(npts,k,p1,b,h,p); - - Vector prev(false); - for (i = 1; i <= 3*p1; i=i+3) { - if (prev.valid) { - painter->drawLine(view->toGui(prev), - view->toGui(Vector(p[i], p[i+1]))); - } - prev = Vector(p[i], p[i+1]); - } -} -*/ - -/** - * @return The reference points of the spline. - */ -//Q3ValueList Spline::getControlPoints() -QList Spline::getControlPoints() -{ - return data.controlPoints; -} - -/** - * Appends the given point to the control points. - */ -void Spline::addControlPoint(const Vector & v) -{ - data.controlPoints.append(v); -} - -/** - * Removes the control point that was last added. - */ -void Spline::removeLastControlPoint() -{ - data.controlPoints.pop_back(); -} - -/** - * Generates B-Spline open knot vector with multiplicity - * equal to the order at the ends. - */ -void Spline::knot(int num, int order, int knotVector[]) -{ - knotVector[1] = 0; - - for(int i=2; i<=num+order; i++) - { - if ((i > order) && (i < num + 2)) - { - knotVector[i] = knotVector[i - 1] + 1; - } - else - { - knotVector[i] = knotVector[i - 1]; - } - } -} - -/** - * Generates rational B-spline basis functions for an open knot vector. - */ -void Spline::rbasis(int c, double t, int npts, int x[], double h[], double r[]) -{ - int nplusc; - int i, k; - double d, e; - double sum; - //double temp[36]; - - nplusc = npts + c; - - double * temp = new double[nplusc + 1]; - - // calculate the first order nonrational basis functions n[i] - for(i=1; i<=nplusc-1; i++) - { - if ((t >= x[i]) && (t < x[i + 1])) - temp[i] = 1; - else - temp[i] = 0; - } - - /* calculate the higher order nonrational basis functions */ - - for(k=2; k<=c; k++) - { - for(i=1; i<=nplusc-k; i++) - { - // if the lower order basis function is zero skip the calculation - if (temp[i] != 0) - d = ((t - x[i]) * temp[i]) / (x[i + k - 1] - x[i]); - else - d = 0; - - // if the lower order basis function is zero skip the calculation - if (temp[i + 1] != 0) - e = ((x[i + k] - t) * temp[i + 1]) / (x[i + k] - x[i + 1]); - else - e = 0; - - temp[i] = d + e; - } - } - - // pick up last point - if (t == (double)x[nplusc]) - temp[npts] = 1; - - // calculate sum for denominator of rational basis functions - sum = 0.; - - for(i=1; i<=npts; i++) - sum = sum + temp[i] * h[i]; - - // form rational basis functions and put in r vector - for(i=1; i<=npts; i++) - { - if (sum != 0) - r[i] = (temp[i] * h[i]) / (sum); - else - r[i] = 0; - } - - delete[] temp; -} - -/** - * Generates a rational B-spline curve using a uniform open knot vector. - */ -void Spline::rbspline(int npts, int k, int p1, double b[], double h[], double p[]) -{ - int i, j, icount, jcount; - int i1; - //int x[30]; /* allows for 20 data points with basis function of order 5 */ - int nplusc; - - double step; - double t; - //double nbasis[20]; - double temp; - - nplusc = npts + k; - - int * x = new int[nplusc + 1]; - double * nbasis = new double[npts + 1]; - - // zero and redimension the knot vector and the basis array - - for(i = 0; i <= npts; i++) - nbasis[i] = 0.0; - - for(i = 0; i <= nplusc; i++) - x[i] = 0; - - // generate the uniform open knot vector - knot(npts, k, x); - - icount = 0; - - // calculate the points on the rational B-spline curve - t = 0; - step = ((double)x[nplusc]) / ((double)(p1 - 1)); - - for(i1=1; i1<= p1; i1++) - { - if ((double)x[nplusc] - t < 5e-6) - t = (double)x[nplusc]; - - // generate the basis function for this value of t - rbasis(k, t, npts, x, h, nbasis); - - // generate a point on the curve - for(j=1; j<=3; j++) - { - jcount = j; - p[icount + j] = 0.0; - - // Do local matrix multiplication - for(i=1; i<=npts; i++) - { - temp = nbasis[i] * b[jcount]; - p[icount + j] = p[icount + j] + temp; - jcount = jcount + 3; - } - } - - icount = icount + 3; - t = t + step; - } - - delete[] x; - delete[] nbasis; -} - -void Spline::knotu(int num, int order, int knotVector[]) -{ - int nplusc = num + order; - int nplus2 = num + 2; - knotVector[1] = 0; - - for(int i=2; i<=nplusc; i++) - knotVector[i] = i - 1; -} - -void Spline::rbsplinu(int npts, int k, int p1, double b[], double h[], double p[]) -{ - int i, j, icount, jcount; - int i1; - //int x[30]; /* allows for 20 data points with basis function of order 5 */ - int nplusc; - - double step; - double t; - //double nbasis[20]; - double temp; - - nplusc = npts + k; - - int * x = new int[nplusc + 1]; - double * nbasis = new double[npts + 1]; - - /* zero and redimension the knot vector and the basis array */ - - for(i=0; i<=npts; i++) - nbasis[i] = 0.0; - - for(i=0; i<=nplusc; i++) - x[i] = 0; - - /* generate the uniform periodic knot vector */ - - knotu(npts, k, x); - - /* - printf("The knot vector is "); - for (i = 1; i <= nplusc; i++){ - printf(" %d ", x[i]); - } - printf("\n"); - - printf("The usable parameter range is "); - for (i = k; i <= npts+1; i++){ - printf(" %d ", x[i]); - } - printf("\n"); - */ - - icount = 0; - - /* calculate the points on the rational B-spline curve */ - - t = k - 1; - step = ((double)((npts) - (k - 1))) / ((double)(p1 - 1)); - - for(i1=1; i1<=p1; i1++) - { - if ((double)x[nplusc] - t < 5e-6) - t = (double)x[nplusc]; - - rbasis(k, t, npts, x, h, nbasis); /* generate the basis function for this value of t */ - /* - printf("t = %f \n",t); - printf("nbasis = "); - for (i = 1; i <= npts; i++){ - printf("%f ",nbasis[i]); - } - printf("\n"); - */ - for(j=1; j<=3; j++) /* generate a point on the curve */ - { - jcount = j; - p[icount + j] = 0.0; - - for(i=1; i<=npts; i++) /* Do local matrix multiplication */ - { - temp = nbasis[i] * b[jcount]; - p[icount + j] = p[icount + j] + temp; - /* - printf("jcount,nbasis,b,nbasis*b,p = %d %f %f %f %f\n",jcount,nbasis[i],b[jcount],temp,p[icount+j]); - */ - jcount = jcount + 3; - } - } - /* - printf("icount, p %d %f %f %f \n",icount,p[icount+1],p[icount+2],p[icount+3]); - */ - icount = icount + 3; - t = t + step; - } - - delete[] x; - delete[] nbasis; -} - -/** - * Dumps the spline's data to stdout. - */ -std::ostream & operator<<(std::ostream & os, const Spline & l) -{ - os << " Spline: " << l.getData() << "\n"; - return os; -}