float interpolate_tricubic_simple(float* tex, float3 coord, uint3 volumeExtent) { // transform the coordinate from [0,extent] to [-0.5, extent-0.5] const float3 coord_grid = coord - 0.5; float3 indexF = floor(coord_grid); const float3 fraction = coord_grid - indexF; int3 index = make_int3((int)indexF.x, (int)indexF.y, (int)indexF.z); //index = index + 0.5; //move from [-0.5, extent-0.5] to [0, extent] float result = 0.0; for (int z=-1; z <= 2; z++) //range [-1, 2] { float bsplineZ = bspline(z-fraction.z); int w = index.z + z; for (int y=-1; y <= 2; y++) { float bsplineYZ = bspline(y-fraction.y) * bsplineZ; int v = index.y + y; for (int x=-1; x <= 2; x++) { float bsplineXYZ = bspline(x-fraction.x) * bsplineYZ; int u = index.x + x; result += bsplineXYZ * tex3D(tex, u, v, w, volumeExtent); } } } return result; }
Vector3 BSpline::interpolate(scalar_t t) const { if(t > 1.0) t = 1.0; if(t < 0.0) t = 0.0; if(control_points.size() < 4) return Vector3(0, 0, 0); if(arc_parametrize) { t = ease(parametrize(t)); } // find the appropriate segment of the spline that t lies and calculate the piecewise parameter t = (scalar_t)(control_points.size() - 3) * t; int seg = (int)t; t -= (scalar_t)floor(t); if(seg >= get_segment_count()) { seg = get_segment_count() - 1; t = 1.0f; } ListNode<Vector3> *iter = const_cast<BSpline*>(this)->control_points.begin(); for(int i=0; i<seg; i++) iter = iter->next; Vector3 Cp[4]; for(int i=0; i<4; i++) { Cp[i] = iter->data; iter = iter->next; } Vector3 res; res.x = bspline(Cp[0].x, Cp[1].x, Cp[2].x, Cp[3].x, t); res.y = bspline(Cp[0].y, Cp[1].y, Cp[2].y, Cp[3].y, t); res.z = bspline(Cp[0].z, Cp[1].z, Cp[2].z, Cp[3].z, t); return res; }
Status GraphicsPath::AddClosedCurve( const PointF* points, INT count ) { if ( !points || count <= 0 ) return SetStatus( InvalidParameter ); // Add the first point: agg::path_storage poly; poly.move_to( points[ 0 ].X, points[ 0 ].Y ); // Loop over the points, adding them to the path storage: for ( int i = 1; i < count; i++ ) poly.line_to( points[ i ].X, points[ i ].Y ); poly.close_polygon(); typedef agg::conv_bspline< agg::path_storage > conv_bspline_type; conv_bspline_type bspline( poly ); bspline.interpolation_step( 1.0 / (double)( 20.0 ) ); typedef agg::conv_stroke< conv_bspline_type > conv_stroke_type; conv_stroke_type stroke( bspline ); // Add the spline to the path: mPathStorage.concat_path( stroke, 0 ); return SetStatus( Ok ); }
float eval(__global float* data_, float tx, float ty, float tz, size_t width_, size_t height_, size_t depth_){ float ttx=tx*(width_-1); float bx=floor(ttx); float deltax=ttx-bx; int bix=(int)bx; float tty=ty*(height_-1); float by=floor(tty); float deltay=tty-by; int biy=(int)by; float ttz=tz*(depth_-1); float bz=floor(ttz); float deltaz=ttz-bz; int biz=(int)bz; float v=0.0f; for(int k=-1;k<=2;++k) { int indexz=biz+k; if(indexz<0) indexz=-indexz; else if(indexz>=depth_) indexz=2*depth_-indexz-2; for(int j=-1;j<=2;++j) { int indexy=biy+j; if(indexy<0) indexy=-indexy; else if(indexy>=height_) indexy=2*height_-indexy-2; for(int i=-1;i<=2;++i) { int indexx=bix+i; if(indexx<0) indexx=-indexx; else if(indexx>=width_) indexx=2*width_-indexx-2; v+=get(data_, indexz, indexx, indexy, width_, height_)*bspline(deltax-(float)i)*bspline(deltay-(float)j)*bspline(deltaz-(float)k); } } } return v; }
/////////////////////////////////////////////////////////////////////////////// // STARE FUNKCIE - NEPOUZIVAJU SA >>>>> QPointF *BSpline::calculateCurve(int resolution) { QPointF *out_pts; out_pts = new QPointF[resolution]; bspline(numInternCtrlPts, polynomDegree, controlPts, out_pts, resolution); return out_pts; }
// Atualiza/Processa os pontos da curva Nurbs void Nurbs::updatePtsCurv() { int i = 0; double t = 0, inic = nos[ordCurva-1], fim = nos[((int)nos.size())-ordCurva]; double inc = ( fim - inic ) / quant; float x = 0, y = 0, z = 0; float x2 = 0, y2 = 0, z2 = 0; float coefbs = 0; vector<float> pts; if(inic == fim){ inic = nos[ordCurva-1]; fim = nos[((int)nos.size())-(ordCurva-1)]; inc = ( fim - inic ) / quant; } for(t = inic; t <= fim; t+=inc){ x = y = z = 0; x2 = y2 = z2 = 0; for(i = 0; i < (int) ptControle.size(); i++){ coefbs = bspline(i,ordCurva,t); x = x + (coefbs * ptControle[i][0] * pesos[i]); x2 = x2 + (coefbs * pesos[i]); y = y + (coefbs * ptControle[i][1] * pesos[i]); y2 = y2 + (coefbs * pesos[i]); z = z + (coefbs * ptControle[i][2] * pesos[i]); z2 = z2 + (coefbs * pesos[i]); } pts.push_back(x/x2); pts.push_back(y/y2); pts.push_back(z/z2); } cout << "nos" <<endl; for(i = 0; i < (int) nos.size(); i++){ cout << nos[i] << endl; } cout << endl; ptsCurv = pts; }
static bool test_bspline(void) { const double knots[11] = { 0., 0.0, 0.0, 0., 0.25, 0.5, 0.75, 1., 1., 1., 1. }; const double coord[7] = { 0., 0., 0., 1., 0., 0., 0. }; double err = 0.; for (double x = 0.; x < 1.; x += 0.01) { double a = bspline(10, 3, 2, knots, x); double b = bspline_curve(10, 2, knots, coord, x); err += pow(a - b, 2); } return (err < 1.E-28); }
void splineShape::calcSplines() { /* * Este metodo tiene que trabajar sobre los puntos de control que ya existen. * Su finalidad es servir como un "update" al calculo de la spline cuando * hacemos alguna variacion sobre los puntos de control ya calculados */ int *u; bspline(14, t, pts, out_pts);//antes era tpn-1 //una vez tengo la salida de los puntos del spline quiero sacar los puntos //de control marcados para la curva para ver como se comporta a diferentes //grados del polinomio. exportControlPoints(); exportSplines(); updateControlPoints(); }
static int curve_expand_points(struct objlist *obj, N_VALUE *inst, int intp, struct narray *expand_points) { int i, j, num, bsize, spcond, x, y; struct narray *points; double c[8]; double *buf; double bs1[7], bs2[7], bs3[4], bs4[4]; int *pdata; _getobj(obj, "points", inst, &points); num = arraynum(points)/2; pdata = arraydata(points); arrayclear(expand_points); switch (intp) { case INTERPOLATION_TYPE_SPLINE: case INTERPOLATION_TYPE_SPLINE_CLOSE: if (num < 2) return 0; bsize = num + 1; buf = g_malloc(sizeof(double) * 9 * bsize); if (buf == NULL) return 1; for (i = 0; i < bsize; i++) buf[i]=i; for (i = 0; i < num; i++) { buf[bsize + i] = pdata[i * 2]; buf[bsize * 2 + i] = pdata[i * 2 + 1]; } if (intp == INTERPOLATION_TYPE_SPLINE) { spcond = SPLCND2NDDIF; } else { spcond = SPLCNDPERIODIC; if (buf[num - 1 + bsize] != buf[bsize] || buf[num - 1 + 2 * bsize] != buf[2 * bsize]) { buf[num + bsize] = buf[bsize]; buf[num + 2 * bsize] = buf[2 * bsize]; num++; } } if (spline(buf, buf + bsize, buf + 3 * bsize, buf + 4 * bsize, buf + 5 * bsize, num, spcond, spcond, 0, 0)) { g_free(buf); error(obj, ERRSPL); return 1; } if (spline(buf, buf + 2 * bsize, buf + 6 * bsize, buf + 7 * bsize, buf + 8 * bsize, num, spcond, spcond, 0, 0)) { g_free(buf); error(obj, ERRSPL); return 1; } x = nround(buf[bsize]); y = nround(buf[bsize * 2]); arrayadd(expand_points, &x); arrayadd(expand_points, &y); for (i = 0; i < num - 1; i++) { for (j = 0; j < 6; j++) { c[j] = buf[i + (j + 3) * bsize]; } if (! curve_expand(c, buf[i + bsize], buf[i + 2 * bsize], splinedif, splineint, expand_points)) { break; } } g_free(buf); break; case INTERPOLATION_TYPE_BSPLINE: if (num < 7) { return 0; } for (i = 0; i < 7; i++) { bs1[i] = pdata[i * 2]; bs2[i] = pdata[i * 2 + 1]; } for (j = 0; j < 2; j++) { bspline(j + 1, bs1 + j, c); bspline(j + 1, bs2 + j, c + 4); if (j == 0) { x = nround(c[0]); y = nround(c[4]); arrayadd(expand_points, &x); arrayadd(expand_points, &y); } if (! curve_expand(c, c[0], c[4], bsplinedif, bsplineint, expand_points)) { return 0; } } for (; i < num; i++) { for (j = 1; j < 7; j++) { bs1[j - 1] = bs1[j]; bs2[j - 1] = bs2[j]; } bs1[6] = pdata[i*2]; bs2[6] = pdata[i*2+1]; bspline(0, bs1 + 1, c); bspline(0, bs2 + 1, c + 4); if (! curve_expand(c, c[0], c[4], bsplinedif, bsplineint, expand_points)) { return 0; } } for (j = 0; j < 2; j++) { bspline(j + 3, bs1 + j + 2, c); bspline(j + 3, bs2 + j + 2, c + 4); if (! curve_expand(c, c[0], c[4], bsplinedif, bsplineint, expand_points)) { return 0; } } break; case INTERPOLATION_TYPE_BSPLINE_CLOSE: if (num < 4) { return 0; } for (i = 0; i < 4; i++) { bs1[i] = pdata[i * 2]; bs3[i] = pdata[i * 2]; bs2[i] = pdata[i * 2 + 1]; bs4[i] = pdata[i * 2 + 1]; } bspline(0, bs1, c); bspline(0, bs2, c + 4); x = nround(c[0]); y = nround(c[4]); arrayadd(expand_points, &x); arrayadd(expand_points, &y); if (! curve_expand(c, c[0], c[4], bsplinedif, bsplineint, expand_points)) { return 0; } for (; i < num; i++) { for (j = 1; j < 4; j++) { bs1[j - 1] = bs1[j]; bs2[j - 1] = bs2[j]; } bs1[3] = pdata[i * 2]; bs2[3] = pdata[i * 2 + 1]; bspline(0, bs1, c); bspline(0, bs2, c + 4); if (! curve_expand(c, c[0], c[4], bsplinedif, bsplineint, expand_points)) { return 0; } } for (j = 0; j < 3; j++) { bs1[4 + j] = bs3[j]; bs2[4 + j] = bs4[j]; bspline(0, bs1 + j + 1, c); bspline(0, bs2 + j + 1, c + 4); if (! curve_expand(c, c[0], c[4], bsplinedif, bsplineint, expand_points)) { return 0; } } break; } return 0; }
void splineShape::initialSpline() { int *u; int i; //____________________________________Creamos el spline para la superficie superior /* * Esta parte se puede emplear para hacer una distribucion senoidal de los puntos static double step; double x; int index; step = pi/n; for (int i = 0; i < n; i++) {//este debe ser n+1 x = i*step; index = (int) ceil( Ni*(0.5*(1-cos(x))) ); if(index == Ni) { index = Ni-1; } pts[i].x = xl[index]; pts[i].y=zl[index]; pts[i].z=0.0; } //_______________________________Generamos los puntos para el spline de la sup. inferior. for (int i = 0; i < n; i++) { x = i*step; index = (int) ceil( Ni*(0.5*(1-cos(x))) ); index = Ni-index; if(index == Ni) { index = Ni-1;} //non-"index out of bounds" condition //Una vez tenemos calculados los indices creamos los puntos automaticamente pts[i+n].x = xu[index]; pts[i+n].y=zu[index]; pts[i+n].z=0.0; } //_____________________________________________________________________________ */ //Debido a la distribucion senoidal de los puntos, no se situan donde tenia pensado, //tengo que ver como los ajusto... pts[0].x = xu[Ni-1]; pts[0].y=zu[Ni-1]; pts[0].z=0.0; pts[1].x = xu[84]; pts[1].y=zu[84]; pts[1].z=0.0; pts[2].x = xu[70]; pts[2].y=zu[70]; pts[2].z=0.0; pts[3].x = xu[49]; pts[3].y=zu[49]; pts[3].z=0.0; pts[4].x = xu[30]; pts[4].y=zu[30]; pts[4].z=0.0; pts[5].x = xu[16]; pts[5].y=zu[16]; pts[5].z=0.0; pts[6].x = xu[3]; pts[6].y=zu[3]; pts[6].z=0.0; pts[7].x = xu[0]; pts[7].y=zu[0]; pts[7].z=0.0; pts[8].x = xl[3]; pts[8].y=zl[3]; pts[8].z=0.0; pts[9].x = xl[15]; pts[9].y=zl[15]; pts[9].z=0.0; pts[10].x = xl[29]; pts[10].y=zl[29]; pts[10].z=0.0; pts[11].x = xl[49]; pts[11].y=zl[49]; pts[11].z=0.0; pts[12].x = xl[70]; pts[12].y=zl[70]; pts[12].z=0.0; pts[13].x = xl[84]; pts[13].y=zl[84]; pts[13].z=0.0; pts[14].x = xu[Ni-1]; pts[14].y=zu[Ni-1]; pts[14].z=0.0; // Copy pts values to original_pts cause later we will need it. for (int i = 0; i < 2*n; i++) { original_pts[i].x = pts[i].x; original_pts[i].y = pts[i].y; original_pts[i].z = pts[i].z; } out_pts = new point[2*Ni]; //antes teniamos Ni elementos en upper y Ni en lower, ahora debemos tener 2 Ni bspline(tnp-1, t, pts, out_pts); exportControlPoints(); updateControlPoints(); }
baseline_reml::baseline_reml(MCMCoptions * o, const datamatrix & d, const datamatrix & leftint, const datamatrix & lefttrunc, const unsigned & nrk, const unsigned & degr, const unsigned & tgr, const unsigned & nrq, const unsigned & nrb, const knotpos & kp, const fieldtype & ft, const ST::string & ti, const ST::string & fp, const ST::string & pres, const double & l, const double & sl, const knotpos & gp, const int & gs, const bool & catsp, const double & rv) : spline_basis(o,d,nrk,degr,kp,ft,ti,fp,pres,l,sl,catsp,0.0,0.0,0.0,0.0,gs,rv) { unsigned i,j,k; baseline=true; varcoeff=false; // refcheck=false; gridpos = gp; double tmax=d.max(0); if(gridpos == MCMC::equidistant) { tgrid = tgr; tvalues = datamatrix(tgrid+1,1); tstep = tmax / tgrid; for(i=0;i<tvalues.rows();i++) tvalues(i,0) = i*tstep; } else if(gridpos == MCMC::quantiles) { tgrid = nrq*nrb; tvalues = datamatrix(tgrid+1,1); nrquant = nrq; nrbetween = nrb; datamatrix tquantiles = datamatrix(nrquant+1,1,0); for(i=1; i<nrquant; i++) { tquantiles(i,0) = d.quantile(((double)i/nrquant)*100,0); } tquantiles(nrquant,0) = tmax; double intmax, intmin, intstep; for(i=0; i<nrquant; i++) { intmin=tquantiles(i,0); intmax=tquantiles(i+1,0); intstep=(intmax-intmin)/nrbetween; for(j=0; j<nrbetween; j++) { tvalues(i*nrbetween+j,0) = intmin + j*intstep; } } tvalues(tgrid,0) = tmax; } else { make_index(d); vector<int>::iterator freqwork = freqoutput.begin(); int * workindex = index.getV(); tvalues = datamatrix(nrdiffobs,1,0); for(j=0;j<d.rows();j++,freqwork++,workindex++) if(freqwork==freqoutput.begin() || *freqwork!=*(freqwork-1)) tvalues(*freqwork,0) = d(*workindex,0); } tsteps = datamatrix(tvalues.rows()-1,1,0); for(i=0; i<tsteps.rows(); i++) tsteps(i,0) = tvalues(i+1,0)-tvalues(i,0); interact_var = datamatrix(d.rows(),1,1); datamatrix betahelp(nrpar,1,0); DG = datamatrix(tvalues.rows(),degree+1,0); DGfirst = vector<int>(tvalues.rows()); for(i=0;i<tvalues.rows();i++) { betahelp.assign( bspline(tvalues(i,0)) ); j=degree+1; while(knot[j] <= tvalues(i,0) && j<nrknots+degree) j++; for(k=0;k<degree+1;k++) DG(i,k) = betahelp(k+j-(degree+1),0); DGfirst[i] = j-(degree+1); } tleft = vector<unsigned>(d.rows(),0); tright = vector<unsigned>(d.rows(),1); ttrunc = vector<unsigned>(d.rows(),0); // indices for truncation times if(lefttrunc.rows()>1) { for(i=0; i<lefttrunc.rows(); i++) { j=1; while(j<tvalues.rows() && tvalues(j,0) < lefttrunc(i,0)) { ttrunc[i]++; j++; } } } for(i=0; i<d.rows(); i++) { j=0; while(j<tvalues.rows()-2 && tvalues(j,0)<d(i,0)) { tright[i]++; j++; } } if(leftint.rows()>1) { for(i=0; i<d.rows(); i++) { if( leftint(i,0) < d(i,0)) { j=0; while(j<tvalues.rows()-1 && tvalues(j,0)<leftint(i,0)) { tleft[i]++; j++; } } else if(leftint(i,0)> d(i,0)) { tleft[i] = tright[i]+1; } else { tleft[i] = tright[i]; } } } else { for(i=0; i<d.rows(); i++) { tleft[i] = tright[i]; } } }
void baseline_reml::createreml(datamatrix & X,datamatrix & Z, const unsigned & Xpos, const unsigned & Zpos) { unsigned i,j; double * workdata; double * workZ; double * workX; unsigned Xcols = X.cols(); datamatrix refhelp; if(refcheck) { refhelp = bspline(reference); if(!varcoeff) X_ref = datamatrix(1,1); else X_ref = datamatrix(1,2); } // X für Daten berechen datamatrix knoten = datamatrix(nrpar,1,0.0); for(i=0;i<nrpar;i++) knoten(i,0) = knot[i]; multBS_index(spline,knoten); workdata = spline.getV(); workX = X.getV()+Xpos; if(varcoeff) { double * workintact = data_forfixed.getV(); double * workX_VCM = X_VCM.getV()+1; for (i=0;i<spline.rows();i++,workdata++,workintact++,workX+=Xcols,workX_VCM+=2) { *workX = *workintact; *(workX+1) = *workdata**workintact; *workX_VCM = *workdata; } } else { for (i=0;i<spline.rows();i++,workdata++,workX+=Xcols) { *workX = *workdata; } } if(refcheck) { if(!varcoeff) { for(i=0; i<knoten.rows(); i++) X_ref(0,0) += knoten(i,0)*refhelp(i,0); // X_ref(0,0) -= splinemean; } else { X_ref(0,0) = 1.0; for(i=0; i<knoten.rows(); i++) X_ref(0,1) += knoten(i,0)*refhelp(i,0); } } // Z für Daten berechnen compute_Kweights(); datamatrix diffmatrix = weighteddiffmat(2,weight); diffmatrix = diffmatrix.transposed()*diffmatrix.transposed().sscp().inverse(); if(refcheck) Z_ref = datamatrix(1,dimZ); unsigned Zcols = Z.cols(); for(j=0;j<dimZ;j++) { multBS_index(spline,diffmatrix.getCol(j)); workdata = spline.getV(); workZ = Z.getV()+Zpos+j; if(refcheck) { Z_ref(0,j) = (refhelp.transposed()*diffmatrix.getCol(j))(0,0); } if(varcoeff) { double * workintact = data_forfixed.getV(); double * workZ_VCM = Z_VCM.getV()+j; for (i=0;i<spline.rows();i++,workdata++,workintact++,workZ+=Zcols,workZ_VCM+=dimZ) { *workZ = *workdata**workintact; *workZ_VCM = *workdata; } } else { for (i=0;i<spline.rows();i++,workdata++,workZ+=Zcols) { *workZ = *workdata; } } } if(!varcoeff) { // X für tvalues berechen t_X = datamatrix(tvalues.rows(),2,1); spline = datamatrix(tvalues.rows(),1,0); multDG(spline,knoten); workdata = spline.getV(); for (i=0;i<spline.rows();i++,workdata++) { t_X(i,1) = *workdata; } // Z für tvalues berechnen t_Z = datamatrix(tvalues.rows(),dimZ,0); for(j=0;j<dimZ;j++) { multDG(spline,diffmatrix.getCol(j)); workdata = spline.getV(); for (i=0;i<spline.rows();i++,workdata++) { t_Z(i,j) = *workdata; } } } if(gridsize>0) { X_grid=t_X.getCol(1); Z_grid=t_Z; } }
virtual void on_draw() { pixfmt pixf(rbuf_window()); renderer_base rb(pixf); renderer_solid r(rb); rb.clear(agg::rgba(1, 1, 1)); scanline_type sl; agg::rasterizer_scanline_aa<> ras; m_poly.close(m_close.status()); agg::simple_polygon_vertex_source path(m_poly.polygon(), m_poly.num_points(), false, m_close.status()); typedef agg::conv_bspline<agg::simple_polygon_vertex_source> conv_bspline_type; conv_bspline_type bspline(path); bspline.interpolation_step(1.0 / m_num_points.value()); agg::trans_single_path tcurve; tcurve.add_path(bspline); tcurve.preserve_x_scale(m_preserve_x_scale.status()); if(m_fixed_len.status()) tcurve.base_length(1120); typedef agg::conv_curve<font_manager_type::path_adaptor_type> conv_font_curve_type; typedef agg::conv_segmentator<conv_font_curve_type> conv_font_segm_type; typedef agg::conv_transform<conv_font_segm_type, agg::trans_single_path> conv_font_trans_type; conv_font_curve_type fcurves(m_fman.path_adaptor()); conv_font_segm_type fsegm(fcurves); conv_font_trans_type ftrans(fsegm, tcurve); fsegm.approximation_scale(3.0); fcurves.approximation_scale(2.0); m_feng.height(40.0); //m_feng.italic(true); if(m_feng.create_font("Times New Roman", agg::glyph_ren_outline)) { double x = 0.0; double y = 3.0; const char* p = text; while(*p) { const agg::glyph_cache* glyph = m_fman.glyph(*p); if(glyph) { if(x > tcurve.total_length()) break; m_fman.add_kerning(&x, &y); m_fman.init_embedded_adaptors(glyph, x, y); if(glyph->data_type == agg::glyph_data_outline) { ras.reset(); ras.add_path(ftrans); r.color(agg::rgba8(0, 0, 0)); agg::render_scanlines(ras, sl, r); } // increment pen position x += glyph->advance_x; y += glyph->advance_y; } ++p; } } typedef agg::conv_stroke<conv_bspline_type> conv_stroke_type; conv_stroke_type stroke(bspline); stroke.width(2.0); r.color(agg::rgba8(170, 50, 20, 100)); ras.add_path(stroke); agg::render_scanlines(ras, sl, r); //-------------------------- // Render the "poly" tool and controls r.color(agg::rgba(0, 0.3, 0.5, 0.3)); ras.add_path(m_poly); agg::render_scanlines(ras, sl, r); agg::render_ctrl(ras, sl, rb, m_close); agg::render_ctrl(ras, sl, rb, m_preserve_x_scale); agg::render_ctrl(ras, sl, rb, m_fixed_len); agg::render_ctrl(ras, sl, rb, m_animate); agg::render_ctrl(ras, sl, rb, m_num_points); //-------------------------- }
void ASSDrawEngine::AddDrawCmdToAGGPathStorage(DrawCmd* cmd, agg::path_storage& path, DRAWCMDMODE mode) { if (mode == HILITE && cmd->prev) path.move_to(cmd->prev->m_point->x(), cmd->prev->m_point->y()); switch(cmd->type) { case M: path.move_to(cmd->m_point->x(),cmd->m_point->y()); break; case B: if (cmd->initialized) { //path.move_to(cmd->prev->m_point->x(),cmd->prev->m_point->y()); PointList::iterator iterate = cmd->controlpoints.begin(); int x[2], y[2]; x[0] = (*iterate)->x(); y[0] = (*iterate)->y(); iterate++; x[1] = (*iterate)->x(); y[1] = (*iterate)->y(); path.curve4(x[0], y[0], x[1], y[1], cmd->m_point->x(),cmd->m_point->y()); break; } case L: if (mode == CTRL_LN) path.move_to(cmd->m_point->x(),cmd->m_point->y()); else path.line_to(cmd->m_point->x(),cmd->m_point->y()); break; case S: unsigned np = cmd->controlpoints.size(); agg::pod_array<double> m_polygon(np * 2); unsigned _pn = 0; PointList::iterator iterate = cmd->controlpoints.begin(); while (iterate != cmd->controlpoints.end()) { m_polygon[_pn] = (*iterate)->x(); _pn++; m_polygon[_pn] = (*iterate)->y(); _pn++; iterate++; } //m_polygon[_pn++] = cmd->m_point->x(); //m_polygon[_pn++] = cmd->m_point->y(); //path.move_to(cmd->prev->m_point->x(),cmd->prev->m_point->y()); if (mode == CTRL_LN) { _pn = 0; while (_pn < np * 2) { path.line_to((int) m_polygon[_pn],(int) m_polygon[_pn + 1]); _pn += 2; } path.line_to(cmd->m_point->x(), cmd->m_point->y()); } else { //path.line_to((int) m_polygon[0],(int) m_polygon[1]); aggpolygon poly(&m_polygon[0], np, false, false); agg::conv_bcspline<agg::simple_polygon_vertex_source> bspline(poly); bspline.interpolation_step(0.01); agg::path_storage npath; npath.join_path(bspline); path.join_path(npath); if (mode == HILITE) path.move_to((int) m_polygon[np * 2 - 2], (int) m_polygon[np * 2 - 1] ); path.line_to(cmd->m_point->x(), cmd->m_point->y()); } break; } }
static void SimplifySketch(const double deviation, bool make_bspline ) { wxGetApp().CreateUndoPoint(); double original_tolerance = wxGetApp().m_geom_tol; wxGetApp().m_geom_tol = sketch_tool_options.m_cleanup_tolerance; std::list<HeeksObj *> selected_sketches; std::copy( wxGetApp().m_marked_list->list().begin(), wxGetApp().m_marked_list->list().end(), std::inserter( selected_sketches, selected_sketches.begin() )); std::list<HeeksObj*>::const_iterator It; for(It = selected_sketches.begin(); It != selected_sketches.end(); It++){ HeeksObj* object = *It; std::list<HeeksObj *> new_objects; if (object->GetType() == SketchType) { std::list<TopoDS_Shape> wires; try { heekscad_interface.ConvertSketchToFaceOrWire(object, wires, false); } // End try catch(...) { continue; } for (std::list<TopoDS_Shape>::iterator itWire = wires.begin(); itWire != wires.end(); itWire++) { std::list<SimplifySketchTool::SortPoint> points = SimplifySketchTool::GetPoints( TopoDS::Wire(*itWire), deviation ); if (sketch_tool_options.m_sort_points) { // The sort points option is turned on. The idea of this is to detect shapes that include // sections that 'double back' on themselves. The first example being a shape made up of // a box as well as a single line that layed along one edge of the box. In this case the extra // line was superfluous. If we sort the points so that each point is closest to the previous // point then, hopefully, we will reorder these shapes that double back on themselves. If this // doesn't work then the user can always turn the 'sort points' option off and try again. std::vector<SimplifySketchTool::SortPoint> sorted_points; std::copy( points.begin(), points.end(), std::inserter( sorted_points, sorted_points.begin() )); for (std::vector<SimplifySketchTool::SortPoint>::iterator l_itPoint = sorted_points.begin(); l_itPoint != sorted_points.end(); l_itPoint++) { // We've already begun. Just sort based on the previous point's location. std::vector<SimplifySketchTool::SortPoint>::iterator l_itNextPoint = l_itPoint; l_itNextPoint++; if (l_itNextPoint != sorted_points.end()) { SimplifySketchTool::sort_points_by_distance compare( *l_itPoint ); std::sort( l_itNextPoint, sorted_points.end(), compare ); } // End if - then } // End for points.clear(); std::copy( sorted_points.begin(), sorted_points.end(), std::inserter( points, points.begin() )); // This sorting process will have resulted in the start and end points being located next to each other // and hence removed. If the original wire was periodic (closed shape) then make sure the last point // is the same as the first point. TopoDS_Wire wire(TopoDS::Wire(*itWire)); if (wire.Closed()) { if (*(points.begin()) != *(points.rbegin())) { points.push_back(*points.begin()); // Close the shape manually. } } } // Whether we sorted or not, we may want to close the shape. if (sketch_tool_options.m_force_closed_shape) { if (*(points.begin()) != *(points.rbegin())) { points.push_back(*points.begin()); // Close the shape manually. } } // Now keep removing points from this list as long as the midpoints are within deviation of // the line between the two neighbour points. bool points_removed = false; do { points_removed = false; for (std::list<SimplifySketchTool::SortPoint>::iterator itPoint = points.begin(); itPoint != points.end(); itPoint++ ) { std::list<SimplifySketchTool::SortPoint>::iterator itP1 = itPoint; std::list<SimplifySketchTool::SortPoint>::iterator itP2 = itPoint; std::list<SimplifySketchTool::SortPoint>::iterator itP3 = itPoint; itP2++; if (itP2 != points.end()) { itP3 = itP2; itP3++; if (itP3 != points.end()) { // First see if p1 and p2 are too close to each other. if (itP1->Distance(*itP2) < deviation) { // Discard p2. points.erase(itP2); points_removed = true; continue; } if (itP2->Distance(*itP3) < deviation) { // Discard p2 points.erase(itP2); points_removed = true; continue; } if (itP1->Distance(*itP3) > deviation) { // Now draw a line between p1 and p3. Measure the distance between p2 and the nearest point // along that line. If this distance is less than the max deviation then discard p2. gp_Lin line(*itP1, gp_Dir(itP3->X() - itP1->X(), itP3->Y() - itP1->Y(), itP3->Z() - itP1->Z())); if (line.SquareDistance(*itP2) < deviation) { // Discard p2 points.erase(itP2); points_removed = true; continue; } } } } } // End for } while (points_removed == true); if (points.size() >= 2) { if (make_bspline) { try { TColgp_Array1OfPnt Points(0, points.size()-1); Standard_Integer i=0; for (std::list<SimplifySketchTool::SortPoint>::iterator itPoint = points.begin(); itPoint != points.end(); itPoint++, i++) { Points.SetValue(i, *itPoint); } // GeomAPI_PointsToBSpline bspline(Points); GeomAPI_PointsToBSpline bspline(Points, sketch_tool_options.m_degree_min, sketch_tool_options.m_degree_max, GeomAbs_Shape(sketch_tool_options.m_continuity), sketch_tool_options.m_cleanup_tolerance); // Standard_EXPORT GeomAPI_PointsToBSpline(const TColgp_Array1OfPnt& Points,const Standard_Integer DegMin = 3,const Standard_Integer DegMax = 8,const GeomAbs_Shape Continuity = GeomAbs_C2,const Standard_Real Tol3D = 1.0e-3); HSpline *hspline = new HSpline(bspline.Curve(), &(wxGetApp().current_color)); heekscad_interface.Add( hspline, NULL ); } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); wxMessageBox(_("Failed to create BSpline curve")); } } // End if - then else { // We're making straight lines HeeksObj *sketch = heekscad_interface.NewSketch(); for (std::list<SimplifySketchTool::SortPoint>::iterator itPoint = points.begin(); itPoint != points.end(); itPoint++) { std::list<SimplifySketchTool::SortPoint>::iterator itNext = itPoint; itNext++; if (itNext == points.end()) continue; double start[3], end[3]; itPoint->ToDoubleArray(start); itNext->ToDoubleArray(end); sketch->Add(heekscad_interface.NewLine(start, end), NULL); } // End for // heekscad_interface.Add(sketch, NULL); new_objects.push_back(sketch); } // End if - else } // End if - then } // End for if (new_objects.size() > 0) { #ifdef MULTIPLE_OWNERS std::list<HeeksObj *> parents = object->Owners(); for (std::list<HeeksObj *>::iterator itOwner = parents.begin(); itOwner != parents.end(); itOwner++) { #else if(object->m_owner) { #endif if ((object->CanEditString()) && (object->GetShortString())) { // (*itOwner)->Remove(object); // Mark the old sketches with a name that can be easily recognised so that we can delete the // old objects if we're satisfied with the replacements. wxString title; title << _("Replaced ") << object->GetShortString(); object->OnEditString(title); } // End if - then for (std::list<HeeksObj *>::iterator itNewChild = new_objects.begin(); itNewChild != new_objects.end(); itNewChild++) { #ifdef MULTIPLE_OWNERS (*itOwner)->Add( *itNewChild, NULL ); #else object->m_owner->Add( *itNewChild, NULL ); #endif } // End for } // End for } // End if - then } // End if - then } // End for wxGetApp().m_geom_tol = original_tolerance; wxGetApp().Changed(); } void SimplifySketchTool::Run() { SimplifySketch(m_deviation, false); } // End Run() method