//========================================================================== void GeometryTools::findDominant(const SplineSurface& surface, Vector3D& dominant_u, Vector3D& dominant_v) //========================================================================== { int nu = surface.numCoefs_u(); int nv = surface.numCoefs_v(); vector<double>::const_iterator start = surface.coefs_begin(); Vector3D temp; // Dominant in u-direction dominant_u = Vector3D(0.0, 0.0, 0.0); for (int j = 0; j < nv; ++j) { for (int dd = 0; dd < 3; ++dd) { temp[dd] = *(start + 3*(nu*j + (nu-1)) + dd) - *(start + 3*(nu*j) + dd); } dominant_u += temp; } // Dominant in v-direction dominant_v = Vector3D(0.0, 0.0, 0.0); for (int i = 0; i < nu; ++i) { for (int dd = 0; dd < 3; ++dd) { temp[dd] = *(start + 3*(nu*(nv-1) + i) + dd) - *(start + 3*i + dd); } dominant_v += temp; } return; }
//=========================================================================== vector<shared_ptr<SplineSurface> > SurfaceCreators::separateRationalParts(const SplineSurface& sf) //=========================================================================== { bool rat = sf.rational(); ASSERT(rat); int dim= sf.dimension(); int rdim = dim + 1; vector<shared_ptr<SplineSurface> > sep_sfs; vector<double> coefs(sf.coefs_begin(), sf.coefs_end()); int nmb1 = sf.numCoefs_u(); int nmb2 = sf.numCoefs_v(); vector<double> rcoefs; int num_coefs = nmb1*nmb2; vector<double>::const_iterator rcoef_iter = sf.rcoefs_begin(); for (int ki = 0; ki < num_coefs; ++ki) { rcoefs.push_back(rcoef_iter[ki*rdim+1]); for (int kj = 0; kj < dim; ++kj) { coefs[ki*dim+kj] /= (rcoefs.back()); } } sep_sfs.push_back(shared_ptr<SplineSurface> (new SplineSurface(nmb1, nmb2, sf.order_u(), sf.order_v(), sf.basis_u().begin(), sf.basis_v().begin(), coefs.begin(), dim))); sep_sfs.push_back(shared_ptr<SplineSurface> (new SplineSurface(nmb1, nmb2, sf.order_u(), sf.order_v(), sf.basis_u().begin(), sf.basis_v().begin(), rcoefs.begin(), 1))); return sep_sfs; }
//========================================================================== void cart_to_bary(const SplineSurface& sf, const BaryCoordSystem3D& bc, SplineSurface& sf_bc) //========================================================================== { ALWAYS_ERROR_IF(sf.dimension() != 3, "Dimension must be 3."); int nu = sf.numCoefs_u(); int nv = sf.numCoefs_v(); Vector3D cart; Vector4D bary; vector<double> new_coefs; if (!sf.rational()) { new_coefs.resize(4 * nu * nv); for (int iv = 0; iv < nv; ++iv) { for (int iu = 0; iu < nu; ++iu) { int offset = nu * iv + iu; cart = Vector3D(sf.coefs_begin() + 3 * offset); bary = bc.cartToBary(cart); for (int j = 0; j < 4; ++j) { new_coefs[4*offset + j] = bary[j]; } } } } else { new_coefs.resize(5 * nu * nv); for (int iv = 0; iv < nv; ++iv) { for (int iu = 0; iu < nu; ++iu) { int offset = nu * iv + iu; cart = Vector3D(sf.coefs_begin() + 3 * offset); bary = bc.cartToBary(cart); double w = sf.rcoefs_begin()[4*offset + 3]; for (int j = 0; j < 4; ++j) { new_coefs[5*offset + j] = bary[j] * w; } new_coefs[5*offset + 4] = w; } } } sf_bc = SplineSurface(nu, nv, sf.order_u(), sf.order_v(), sf.basis_u().begin(), sf.basis_v().begin(), new_coefs.begin(), 4, sf.rational()); return; }
int main() { ObjectHeader header; SplineSurface surf; cin >> header >> surf; PointCloud<3> cloud(surf.coefs_begin(), surf.numCoefs_u()*surf.numCoefs_v()); cloud.writeStandardHeader(cout); cout << cloud; }
//========================================================================== bool GeometryTools::negativeProj(const SplineSurface& surface, const Array<Vector3D, 2>& refvector, const double eps) //========================================================================== { int num_u = surface.numCoefs_u(); int num_v = surface.numCoefs_v(); Vector3D temp; int i = 0, j = 0; while (i < num_u-1) { j = 0; while (j < num_v) { temp[0] = *(surface.coefs_begin() + 3*(num_u*j + i+1)) - *(surface.coefs_begin() + 3*(num_u*j + i)); temp[1] = *(surface.coefs_begin() + 3*(num_u*j + i+1) + 1) - *(surface.coefs_begin() + 3*(num_u*j + i) + 1); temp[2] = *(surface.coefs_begin() + 3*(num_u*j + i+1) + 2) - *(surface.coefs_begin() + 3*(num_u*j + i) + 2); // Positive tolerance means that there must be a small // _nonzero_ negative projection before it is reported as // negative! if (temp * refvector[0] < -eps) return true; ++j; } ++i; } i = 0; while (i < num_u) { j = 0; while (j < num_v-1) { temp[0] = *(surface.coefs_begin() + 3*(num_u*(j+1) + i)) - *(surface.coefs_begin() + 3*(num_u*j + i)); temp[1] = *(surface.coefs_begin() + 3*(num_u*(j+1) + i) + 1) - *(surface.coefs_begin() + 3*(num_u*j + i) +1); temp[2] = *(surface.coefs_begin() + 3*(num_u*(j+1) + i) + 2) - *(surface.coefs_begin() + 3*(num_u*j + i) + 2); // Positive tolerance means that there must be a small // _nonzero_ negative projection before it is reported as // negative! if (temp * refvector[1] < -eps) return true; ++j; } ++i; } return false; }
//=========================================================================== void SplineUtils::refinedBezierCoefsCubic(SplineSurface& spline_sf, int ind_u_min, int ind_v_min, vector<double>& bez_coefs) //=========================================================================== { assert(!spline_sf.rational()); if (bez_coefs.size() != 48) bez_coefs.resize(48); std::fill(bez_coefs.begin(), bez_coefs.end(), 0.0); // Values for inpute spline surface. int dim = spline_sf.dimension(); int order_u = spline_sf.order_u(); int order_v = spline_sf.order_u(); int num_coefs_u = spline_sf.numCoefs_u(); int num_coefs_v = spline_sf.numCoefs_v(); // Checking that input index is within range. assert(ind_u_min >= order_u - 1 && ind_u_min < num_coefs_u); assert(ind_v_min >= order_v - 1 && ind_v_min < num_coefs_v); BsplineBasis& basis_u = spline_sf.basis_u(); BsplineBasis& basis_v = spline_sf.basis_v(); double* knot_u = &basis_u.begin()[0]; double* knot_v = &basis_v.begin()[0]; // We expect the knot index to refer to the last occurence. assert(knot_u[ind_u_min] != knot_u[ind_u_min+1]); assert(knot_v[ind_v_min] != knot_v[ind_v_min+1]); // We expect knot mult to be 1 or 4. int knot_mult_umin = (knot_u[ind_u_min-1] == knot_u[ind_u_min]) ? 4 : 1; int knot_mult_umax = (knot_u[ind_u_min+1] == knot_u[ind_u_min+2]) ? 4 : 1; int knot_mult_vmin = (knot_v[ind_v_min-1] == knot_v[ind_v_min]) ? 4 : 1; int knot_mult_vmax = (knot_v[ind_v_min+1] == knot_v[ind_v_min+2]) ? 4 : 1; bool kreg_at_ustart = (knot_mult_umin == 4); bool kreg_at_uend = (knot_mult_umax == 4); vector<double> transf_mat_u(16, 0.0); // if (!kreg_at_ustart && !kreg_at_uend) splineToBezierTransfMat(knot_u + ind_u_min - 3, transf_mat_u); #ifndef NDEBUG std::cout << "\ntransf_mat_u=" << std::endl; for (size_t kj = 0; kj < 4; ++kj) { for (size_t ki = 0; ki < 4; ++ki) std::cout << transf_mat_u[kj*4+ki] << " "; std::cout << std::endl; } std::cout << std::endl; #endif // NDEBUG // else // cubicTransfMat(knot_u + ind_u_min - 3, // kreg_at_ustart, kreg_at_uend, // transf_mat_u); bool kreg_at_vstart = (knot_mult_vmin == 4); bool kreg_at_vend = (knot_mult_vmax == 4); vector<double> transf_mat_v(16, 0.0); // if (!kreg_at_ustart && !kreg_at_uend) splineToBezierTransfMat(knot_v + ind_v_min - 3, transf_mat_v); #ifndef NDEBUG std::cout << "\ntransf_mat_v=" << std::endl; for (size_t kj = 0; kj < 4; ++kj) { for (size_t ki = 0; ki < 4; ++ki) std::cout << transf_mat_v[kj*4+ki] << " "; std::cout << std::endl; } std::cout << std::endl; #endif // NDEBUG extractBezierCoefs(&spline_sf.coefs_begin()[0], num_coefs_u, num_coefs_v, ind_u_min, ind_v_min, transf_mat_u, transf_mat_v, bez_coefs); return; }
//=========================================================================== shared_ptr<SplineSurface> SurfaceCreators::mult1DBezierPatches(const SplineSurface& patch1, const SplineSurface& patch2) //=========================================================================== { // @@sbr This should be fixed shortly. Nothing more than separating the // spatial and rational components. ASSERT(!patch1.rational() && !patch2.rational()); // We should of course also check the actual knots, but why bother (trusting the user). // ASSERT(basis1_u.numCoefs() == basis2_u.numCoefs() && // basis1_v.numCoefs() == basis2_v.numCoefs() && // basis1_u.order() == basis2_u.order() && // basis1_v.order() == basis2_v.order()); ASSERT((patch1.dimension() == 1) && (patch2.dimension() == 1)); // @@sbr Suppose we could allow for differing orders (but equal parameter domain). // Ported from SISL routine s6multsfs(). int order = max(2*(patch1.order_u() - 1) + 1, 2*(patch1.order_v() - 1) + 1);; vector<double> pascal((order+1)*(order+2)/2, 0.0); // Binomial coefficients (Pascal's triangle) int ki, kj; vector<double>::iterator psl1; /* Pointer used in Pascals triangle */ vector<double>::iterator psl2; /* Pointer used in Pascals triangle */ for(ki = 0, psl2 = pascal.begin(); ki <= order ; ki++, psl1 = psl2, psl2 += ki) { psl2[0] = 1.0; for(kj = 1; kj < ki; kj++) psl2[kj] = psl1[kj-1] + psl1[kj]; psl2[ki] = 1.0; } int order11 = patch1.order_u(); int order12 = patch1.order_v(); int order21 = patch2.order_u(); int order22 = patch2.order_v(); vector<double>::const_iterator c1 = patch1.coefs_begin(); vector<double>::const_iterator c2 = patch2.coefs_begin(); // vector<double> mult_coefs(patch1.numCoefs_u()*patch1.numCoefs_v()*patch1.dimension(), 0.0); int p1,p2,r1,r2; int kgrad11 = order11-1; int kgrad12 = order12-1; int kgrad21 = order21-1; int kgrad22 = order22-1; int kgrad1 = kgrad11 + kgrad21; // Degree of mult basis functions in 1st dir. int kgrad2 = kgrad12 + kgrad22; int kstop2 = order12+order22-1; int kstop1 = order11+order21-1; vector<double> mult_coefs(kstop1*kstop2, 0.0); vector<double>::const_iterator psl_kgrad11 = pascal.begin()+kgrad11*(kgrad11+1)/2; vector<double>::const_iterator psl_kgrad12 = pascal.begin()+kgrad12*(kgrad12+1)/2; vector<double>::const_iterator psl_kgrad21 = pascal.begin()+kgrad21*(kgrad21+1)/2; vector<double>::const_iterator psl_kgrad22 = pascal.begin()+kgrad22*(kgrad22+1)/2; vector<double>::const_iterator psl_kgrad1 = pascal.begin()+kgrad1 *(kgrad1 +1)/2; vector<double>::const_iterator psl_kgrad2 = pascal.begin()+kgrad2 *(kgrad2 +1)/2; vector<double>::const_iterator qsc1, qsc2; double tsum, sumi; vector<double>::iterator temp = mult_coefs.begin(); double tdiv, t2; int kstop3, kstop4; for (p2 = 0; p2 < kstop2; ++p2) for (p1 = 0; p1 <kstop1; p1++, temp++) { tdiv = psl_kgrad1[p1]*psl_kgrad2[p2]; kstop4 = min(p2,kgrad12); for (r2 = max(0,p2-kgrad22),tsum = 0.0; r2 <= kstop4; r2++) { t2 = psl_kgrad12[r2]*psl_kgrad22[p2-r2]; kstop3 = min(p1,kgrad11); for (r1 = max(0,p1-kgrad21),sumi = 0.0, qsc1 = c1+r2*order11,qsc2 = c2+(p2-r2)*order21; r1 <= kstop3; r1++) sumi += psl_kgrad11[r1]*psl_kgrad21[p1-r1]*qsc1[r1]*qsc2[p1-r1]; tsum += t2*sumi; } tsum /= tdiv; *temp = tsum; } // *order_newsurf1 = kstop1; // *order_newsurf2 = kstop2; // We must add knots to input basises according to new order. vector<double> new_knots_u, new_knots_v; new_knots_u.insert(new_knots_u.begin(), kstop1, patch1.startparam_u()); new_knots_u.insert(new_knots_u.end(), kstop1, patch1.endparam_u()); new_knots_v.insert(new_knots_v.begin(), kstop2, patch1.startparam_v()); new_knots_v.insert(new_knots_v.end(), kstop2, patch1.endparam_v()); // Finally we create the spline sf with the multiplied coefs. shared_ptr<SplineSurface> mult_sf(new SplineSurface(kstop1, kstop2, kstop1, kstop2, new_knots_u.begin(), new_knots_v.begin(), mult_coefs.begin(), patch1.dimension(), patch1.rational())); // SplineSurface* mult_sf = new SplineSurface(patch1.numCoefs_u(), patch1.numCoefs_v(), // patch1.order_u(), patch1.order_v(), // patch1.basis_u().begin(), patch1.basis_v().begin(), // mult_coefs.begin(), patch1.dimension(), // patch1.rational()); return mult_sf; }