//=========================================================================== shared_ptr<SplineSurface> SurfaceCreators::mergeRationalParts(const SplineSurface& nom_sf, const SplineSurface& den_sf, bool weights_in_first) //=========================================================================== { ASSERT((!nom_sf.rational()) && (!den_sf.rational())); ASSERT(den_sf.dimension() == 1); int dim = nom_sf.dimension(); // We first make sure they share spline space. vector<shared_ptr<SplineSurface> > sfs; sfs.push_back(shared_ptr<SplineSurface>(nom_sf.clone())); sfs.push_back(shared_ptr<SplineSurface>(den_sf.clone())); double knot_diff_tol = 1e-06; GeometryTools::unifySurfaceSplineSpace(sfs, knot_diff_tol); vector<double> rcoefs; vector<double>::const_iterator iter = sfs[0]->coefs_begin(); vector<double>::const_iterator riter = sfs[1]->coefs_begin(); int num_coefs = sfs[0]->numCoefs_u()*sfs[0]->numCoefs_v(); for (int ki = 0; ki < num_coefs; ++ki) { for (int kj = 0; kj < dim; ++kj) { if (weights_in_first) { rcoefs.push_back(iter[ki*dim+kj]); } else { rcoefs.push_back(iter[ki*dim+kj]*riter[ki]); } } rcoefs.push_back(riter[ki]); } shared_ptr<SplineSurface> rat_sf(new SplineSurface (sfs[0]->numCoefs_u(), sfs[0]->numCoefs_v(), sfs[0]->order_u(), sfs[0]->order_v(), sfs[0]->basis_u().begin(), sfs[0]->basis_v().begin(), rcoefs.begin(), dim, true)); return rat_sf; }
shared_ptr<SplineSurface> GeometryTools::surfaceSum(const SplineSurface& sf1, double fac1, const SplineSurface& sf2, double fac2, double num_tol) //******************************************************************** // Addition of two signed SplineSurfaces, i.e. this function can // also be used for subtraction. The surfaces is assumed to live on // the same parameter domain, but may have different knot vectors. //******************************************************************** { // Check input ALWAYS_ERROR_IF(fabs(sf1.startparam_u() - sf2.startparam_u()) > num_tol || fabs(sf1.endparam_u() - sf2.endparam_u()) > num_tol || fabs(sf1.startparam_v() - sf2.startparam_v()) > num_tol || fabs(sf1.endparam_v() - sf2.endparam_v()) > num_tol, "Inconsistent parameter domain."); // For the time being if (sf1.rational() || sf2.rational()) { THROW("Sum of rational surfaces is not implemented"); } // Make copy of surfaces vector<shared_ptr<SplineSurface> > surfaces; surfaces.reserve(2); shared_ptr<SplineSurface> sf; // #ifdef _MSC_VER // sf = shared_ptr<SplineSurface>(dynamic_cast<SplineSurface*>(sf1.clone())); // #else sf = shared_ptr<SplineSurface>(sf1.clone()); // #endif surfaces.push_back(sf); // #ifdef _MSC_VER // sf = shared_ptr<SplineSurface>(dynamic_cast<SplineSurface*>(sf2.clone())); // #else sf = shared_ptr<SplineSurface>(sf2.clone()); // #endif surfaces.push_back(sf); // Make sure that the surfaces live on the same knot vector GeometryTools::unifySurfaceSplineSpace(surfaces, num_tol); // Add signed coefficients vector<double> coefs; int nmb_coefs_u = surfaces[0]->numCoefs_u(); int nmb_coefs_v = surfaces[0]->numCoefs_v(); int dim = surfaces[0]->dimension(); coefs.resize(dim*nmb_coefs_u*nmb_coefs_v); int ki; std::vector<double>::iterator s1 = surfaces[0]->coefs_begin(); std::vector<double>::iterator s2 = surfaces[1]->coefs_begin(); for (ki=0; ki<dim*nmb_coefs_u*nmb_coefs_v; ki++) coefs[ki] = fac1*s1[ki] + fac2*s2[ki]; // Create output curve shared_ptr<SplineSurface> surfacesum(new SplineSurface(nmb_coefs_u, nmb_coefs_v, surfaces[0]->order_u(), surfaces[0]->order_v(), surfaces[0]->basis_u().begin(), surfaces[0]->basis_v().begin(), &coefs[0], dim, false)); return surfacesum; }
//=========================================================================== shared_ptr<SplineSurface> SurfaceCreators::insertParamDomain(const SplineSurface& sf_1d) //=========================================================================== { shared_ptr<SplineSurface> sf_1d_cp(sf_1d.clone()); int dim = sf_1d.dimension(); ASSERT(dim == 1); bool rat = sf_1d_cp->rational(); // The returned object should be linear in the first two directions. // We create an additional 1d-sf describing the linear param space. vector<double> lin_knots_u(4, sf_1d_cp->startparam_u()); lin_knots_u[2] = lin_knots_u[3] = sf_1d_cp->endparam_u(); vector<double> lin_knots_v(4, sf_1d_cp->startparam_v()); lin_knots_v[2] = lin_knots_v[3] = sf_1d_cp->endparam_v(); int rdim = (rat) ? dim + 1 : dim; vector<double> lin_coefs_u(4, 1.0); lin_coefs_u[0] = lin_coefs_u[2] = lin_knots_u[0]; lin_coefs_u[1] = lin_coefs_u[3] = lin_knots_u[2]; shared_ptr<SplineSurface> lin_sf_u(new SplineSurface(2, 2, 2, 2, lin_knots_u.begin(), lin_knots_v.begin(), lin_coefs_u.begin(), 1)); vector<double> lin_coefs_v(4*rdim, 1.0); lin_coefs_v[0] = lin_coefs_v[1] = lin_knots_v[0]; lin_coefs_v[2] = lin_coefs_v[3] = lin_knots_v[2]; shared_ptr<SplineSurface> lin_sf_v(new SplineSurface(2, 2, 2, 2, lin_knots_u.begin(), lin_knots_v.begin(), lin_coefs_v.begin(), 1)); if (rat) { // We extract the rational part (i.e. the denominator sf) and mult it the linear parts. vector<shared_ptr<SplineSurface> > rat_parts = separateRationalParts(*sf_1d_cp); lin_sf_u = SurfaceCreators::mult1DSurfaces(*lin_sf_u, *rat_parts[1]); lin_sf_v = SurfaceCreators::mult1DSurfaces(*lin_sf_v, *rat_parts[1]); // We must then raise the order of sf_1d_cp by 1. rat_parts[0]->raiseOrder(1, 1); rat_parts[1]->raiseOrder(1, 1); sf_1d_cp = mergeRationalParts(*rat_parts[0], *rat_parts[1], false); } else { int raise_u = sf_1d_cp->order_u() - 2; int raise_v = sf_1d_cp->order_v() - 2; lin_sf_u->raiseOrder(raise_u, raise_v); lin_sf_v->raiseOrder(raise_u, raise_v); } // If not bezier we must also refine the space. int ik1 = sf_1d_cp->order_u(); int ik2 = sf_1d_cp->order_v(); int in1 = sf_1d_cp->numCoefs_u(); int in2 = sf_1d_cp->numCoefs_v(); if (ik1 < in1 || ik2 < in2) { vector<double> new_knots_u(sf_1d_cp->basis_u().begin() + ik1, sf_1d_cp->basis_u().begin() + in1); vector<double> new_knots_v(sf_1d_cp->basis_v().begin() + ik2, sf_1d_cp->basis_v().begin() + in2); lin_sf_u->insertKnot_u(new_knots_u); lin_sf_u->insertKnot_v(new_knots_v); lin_sf_v->insertKnot_u(new_knots_u); lin_sf_v->insertKnot_v(new_knots_v); } // Finally we create our space sf (i.e. living in a 3-dimensional env). vector<double> all_coefs; int coefs_size = sf_1d_cp->numCoefs_u()*sf_1d_cp->numCoefs_v(); for (int ki = 0; ki < coefs_size; ++ki) { if (rat) { all_coefs.push_back(lin_sf_u->coefs_begin()[ki*dim]); all_coefs.push_back(lin_sf_v->coefs_begin()[ki*dim]); all_coefs.push_back(sf_1d_cp->rcoefs_begin()[ki*rdim]); all_coefs.push_back(sf_1d_cp->rcoefs_begin()[ki*rdim+1]); } else { all_coefs.push_back(lin_sf_u->coefs_begin()[ki*dim]); all_coefs.push_back(lin_sf_v->coefs_begin()[ki*dim]); all_coefs.push_back(sf_1d_cp->coefs_begin()[ki*dim]); } } shared_ptr<SplineSurface> return_sf(new SplineSurface(sf_1d_cp->numCoefs_u(), sf_1d_cp->numCoefs_v(), sf_1d_cp->order_u(), sf_1d_cp->order_v(), sf_1d_cp->basis_u().begin(), sf_1d_cp->basis_v().begin(), all_coefs.begin(), 3, rat)); return return_sf; }