//=========================================================================== void TrimCrvUtils::translateSurfaceDomain(ParamSurface* sf, const Point& translate_vec) //=========================================================================== { RectDomain dom = sf->containingDomain(); BoundedSurface* bdsf = dynamic_cast<BoundedSurface*>(sf); if (bdsf) dom = bdsf->underlyingSurface()->containingDomain(); sf->setParameterDomain(dom.umin()+translate_vec[0], dom.umax()+translate_vec[0], dom.vmin()+translate_vec[1], dom.vmax()+translate_vec[1]); // if (sf->instanceType() == Class_SplineSurface) // { // SplineSurface* spline_sf = dynamic_cast<SplineSurface*>(sf); // spline_sf->setParameterDomain(spline_sf->startparam_u() + translate_vec[0], // spline_sf->endparam_u() + translate_vec[0], // spline_sf->startparam_v() + translate_vec[1], // spline_sf->endparam_v() + translate_vec[1]); // } // else if (sf->instanceType() == Class_LRSplineSurface) // { // LRSplineSurface* lr_spline_sf = dynamic_cast<LRSplineSurface*>(sf); // lr_spline_sf->setParameterDomain(lr_spline_sf->startparam_u() + translate_vec[0], // lr_spline_sf->endparam_u() + translate_vec[0], // lr_spline_sf->startparam_v() + translate_vec[1], // lr_spline_sf->endparam_v() + translate_vec[1]); // } // else // { // MESSAGE("Object type " << sf->instanceType() << " is not supported yet."); // } }
//=========================================================================== SurfaceOnVolume::SurfaceOnVolume(shared_ptr<ParamVolume> vol, shared_ptr<ParamSurface> spacesurf, int constdir, double constpar, int boundary, bool swapped) : volume_(vol), spacesurf_(spacesurf), prefer_parameter_(true), constdir_(constdir), constval_(constpar), at_bd_(boundary), orientation_(0), swap_(swapped) //=========================================================================== { // Make parameter surface // @@@ This construction may not be sufficient when trimmed volumes are // introduced if (constdir > 0) { Array<double,6> domain = volume_->parameterSpan(); RectDomain pardom = spacesurf_->containingDomain(); vector<double> knots1(4); vector<double> knots2(4); knots1[0] = knots1[1] = (swap_) ? pardom.vmin() : pardom.umin(); knots1[2] = knots1[3] = (swap_) ? pardom.vmax() : pardom.umax(); knots2[0] = knots2[1] = (swap_) ? pardom.umin() : pardom.vmin(); knots2[2] = knots2[3] = (swap_) ? pardom.umax() : pardom.vmax(); vector<double> coefs(12); domain[2*(constdir_-1)] = domain[2*(constdir_-1)+1] = constval_; coefs[0] = domain[0]; coefs[1] = domain[2]; coefs[2] = domain[4]; coefs[3] = domain[1]; coefs[4] = (constdir_ <= 2) ? domain[3] : domain[2]; coefs[5] = domain[4]; coefs[6] = domain[0]; coefs[7] = (constdir_ <= 2) ? domain[2] : domain[3]; coefs[8] = domain[5]; coefs[9] = domain[1]; coefs[10] = domain[3]; coefs[11] = domain[5]; psurf_ = shared_ptr<ParamSurface>(new SplineSurface(2, 2, 2, 2, &knots1[0], &knots2[0], &coefs[0], 3)); if (swap_) { psurf_->swapParameterDirection(); } } }
//=========================================================================== Point SurfaceOnVolume:: volumeParameter(double u_par, double v_par) const //=========================================================================== { Point param(3); RectDomain dom = containingDomain(); if (constdir_ == 1 || constdir_ == 2 || constdir_ == 3) { int idx1, idx2, idx3; idx1 = constdir_ - 1; idx2 = (idx1 == 0) ? 1 : 0; idx3 = (constdir_ == 3) ? 1 : 2; param[idx1] = constval_; if (swap_) { param[idx2] = (orientation_ == 2 || orientation_ == 3) ? dom.vmax() - (v_par - dom.vmin()) : v_par; param[idx3] = (orientation_ == 1 || orientation_ == 3) ? dom.umax() - (u_par - dom.umin()) : u_par; } else { param[idx3] = (orientation_ == 2 || orientation_ == 3) ? dom.vmax() - (v_par - dom.vmin()) : v_par; param[idx2] = (orientation_ == 1 || orientation_ == 3) ? dom.umax() - (u_par - dom.umin()) : u_par; } } else if (psurf_) param = psurf_->ParamSurface::point(u_par, v_par); else { // No parameter surface exist. Perform closest point computation Point pos = spacesurf_->ParamSurface::point(u_par, v_par); double clo_u, clo_v, clo_w, dist; Point clo_pt; double eps = 1.0e-6; volume_->closestPoint(pos, clo_u, clo_v, clo_w, clo_pt, dist, eps); param = Point(clo_u, clo_v, clo_w); } return param; }
//=========================================================================== void CurveBoundedDomain::getInternalPoint(double& upar, double& vpar) const //=========================================================================== { // Make initial guess RectDomain dom = containingDomain(); upar = 0.5*(dom.umin() + dom.umax()); vpar = 0.5*(dom.vmin() + dom.vmax()); // Adjust double tolerance = 1.0e-4; for (int ki=1; ki<3; ++ki) { bool succeeded = true; vector<pair<double, double> > inside; try { getInsideIntervals(ki, upar, vpar, tolerance, inside, false); } catch(...) { succeeded = false; } if (succeeded) { if (inside.size() > 0) { // Find the largest interval double max_len = inside[0].second - inside[0].first; size_t max_ix = 0; for (size_t kj=0; kj<inside.size(); ++kj) { double len = inside[kj].second - inside[kj].first; if (len > max_len) { max_len = len; max_ix = kj; } } if (ki == 1) upar = 0.5*(inside[max_ix].first + inside[max_ix].second); else vpar = 0.5*(inside[max_ix].first + inside[max_ix].second); // Check if we have found a boundary point Vector2D ppnt(upar, vpar); bool is_boundary = isOnBoundary(ppnt, tolerance); if (!is_boundary) break; } } } return; }
//=========================================================================== void RectangularSurfaceTesselator::tesselateIsolines() //=========================================================================== { if (!isolines_) return; isolinestrips_.resize(uiso_ + viso_); RectDomain dom = surf_.containingDomain(); Point pt(3); for (int i = 0; i < uiso_; ++i) { isolinestrips_[i].resize(isores_); double ru = double(i)/double(uiso_-1); double u = dom.umin()*(1.0-ru) + ru*dom.umax(); for (int j = 0; j < isores_; ++j) { double rv = double(j)/double(isores_-1); double v = dom.vmin()*(1.0-rv) + rv*dom.vmax(); surf_.point(pt, u, v); isolinestrips_[i].vertexArray()[j*3] = pt[0]; isolinestrips_[i].vertexArray()[j*3 + 1] = pt[1]; isolinestrips_[i].vertexArray()[j*3 + 2] = pt[2]; isolinestrips_[i].paramArray()[j] = v; } } for (int i = 0; i < viso_; ++i) { isolinestrips_[uiso_ + i].resize(isores_); double rv = double(i)/double(viso_-1); double v = dom.vmin()*(1.0-rv) + rv*dom.vmax(); for (int j = 0; j < isores_; ++j) { double ru = double(j)/double(isores_-1); double u = dom.umin()*(1.0-ru) + ru*dom.umax(); surf_.point(pt, u, v); isolinestrips_[uiso_ + i].vertexArray()[j*3] = pt[0]; isolinestrips_[uiso_ + i].vertexArray()[j*3 + 1] = pt[1]; isolinestrips_[uiso_ + i].vertexArray()[j*3 + 2] = pt[2]; isolinestrips_[uiso_ + i].paramArray()[j] = u; } } }
//=========================================================================== ProjectCurve::ProjectCurve(shared_ptr<Go::ParamCurve>& space_crv, shared_ptr<Go::ParamSurface>& surf, shared_ptr<Go::Point>& start_par_pt, shared_ptr<Go::Point>& end_par_pt, double epsgeo1, // double epsgeo2, const RectDomain* domain_of_interest) : space_crv_(space_crv), surf_(surf), start_par_pt_(start_par_pt), end_par_pt_(end_par_pt), epsgeo1_(epsgeo1), // epsgeo2_(epsgeo2), domain_of_interest_(domain_of_interest) //=========================================================================== { // Test input ALWAYS_ERROR_IF(space_crv_.get() == 0 || surf_.get() == 0, "Missing input data."); ALWAYS_ERROR_IF(space_crv_->dimension() != 3 || space_crv_->dimension() != surf_->dimension(), "Dimension mismatch."); //// Check spline surfaces for seems //shared_ptr<SplineSurface> tmp_srf = // dynamic_pointer_cast<SplineSurface,ParamSurface>(surf_); //if (tmp_srf.get()) // SurfaceTools::surfaceClosed(*tmp_srf, closed_dir_u_, closed_dir_v_); //else // closed_dir_u_ = closed_dir_v_ = false; // No particular treatment of seems // Check surfaces for seems closed_dir_u_ = false; closed_dir_v_ = false; shared_ptr<SplineSurface> tmp_srf = dynamic_pointer_cast<SplineSurface,ParamSurface>(surf_); shared_ptr<ElementarySurface> tmp_srf_el = dynamic_pointer_cast<ElementarySurface,ParamSurface>(surf_); if (tmp_srf.get()) SurfaceTools::surfaceClosed(*tmp_srf, closed_dir_u_, closed_dir_v_); else if (tmp_srf_el.get()) tmp_srf_el->isClosed(closed_dir_u_, closed_dir_v_); // Parameter domain RectDomain domain = surf_->containingDomain(); umin_ = domain.umin(); umax_ = domain.umax(); vmin_ = domain.vmin(); vmax_ = domain.vmax(); }
//=========================================================================== DirectionCone Torus::normalCone() const //=========================================================================== { RectDomain domain = parameterDomain(); double umin = domain.umin(); double umax = domain.umax(); double vmin = domain.vmin(); double vmax = domain.vmax(); Point dir; normal(dir, 0.5*(umin+umax), 0.5*(vmin+vmax)); Point ll, ur; normal(ll, umin, vmin); normal(ur, umax, vmax); double angle = std::max(dir.angle(ll), dir.angle(ur)); return DirectionCone(dir, angle); }
//=========================================================================== void TesselatorUtils::getResolution(const ParamSurface *surf, int& u_nmb, int& v_nmb, int uv_nmb) //=========================================================================== { int min_nmb = 8; // Check if the surface is trimmed and trimmed along iso curves. In that // case the size of the surface is computed from the smallest possible // underlying surface double tol2d = 1.0e-4; const ParamSurface *sf = surf; vector<shared_ptr<ParamSurface> > sfs; if (surf->instanceType() == Class_BoundedSurface) { const BoundedSurface *bd_surf = dynamic_cast<const BoundedSurface*>(surf); if (bd_surf->isIsoTrimmed(tol2d)) { RectDomain domain = bd_surf->containingDomain(); RectDomain dom2 = sf->containingDomain(); double umin = std::max(domain.umin(), dom2.umin()); double umax = std::min(domain.umax(), dom2.umax()); double vmin = std::max(domain.vmin(), dom2.vmin()); double vmax = std::min(domain.vmax(), dom2.vmax()); sfs = sf->subSurfaces(umin, vmin, umax, vmax); if (sfs.size() == 1) sf = sfs[0].get(); } } // Estimate the size of the surface in the two parameter directions double len_u, len_v; GeometryTools::estimateSurfaceSize(*sf, len_u, len_v); double fac = len_u/len_v; double len = sqrt((double)uv_nmb/fac); u_nmb = std::max(min_nmb, (int)(fac*len)); v_nmb = std::max(min_nmb, (int)len); }
//=========================================================================== DirectionCone Torus::tangentCone(bool pardir_is_u) const //=========================================================================== { if (isSwapped()) pardir_is_u = !pardir_is_u; if (pardir_is_u) { shared_ptr<Circle> circle = getMajorCircle(0.0); return circle->directionCone(); } else { DirectionCone normals = normalCone(); double angle = normals.angle(); RectDomain domain = parameterDomain(); double umid = 0.5 * (domain.umax() + domain.umin()); double vmid = 0.5 * (domain.vmax() + domain.vmin()); vector<Point> pts(3); point(pts, umid, vmid, 1); return DirectionCone(pts[2], angle); } }
//=========================================================================== void RectangularSurfaceTesselator::tesselateSurface() //=========================================================================== { int m = mesh_->numStrips() + 1; int n = mesh_->numVertices()/m; /// @@@ We can only tesselate properly rectangular-domain surfaces. RectDomain dom = surf_.containingDomain(); int dim = surf_.dimension(); Point pt(dim); for (int iu = 0; iu < n; ++iu) { double ru = double(iu)/double(n-1); double u = dom.umin()*(1.0-ru) + ru*dom.umax(); for (int iv = 0; iv < m; ++iv) { double rv = double(iv)/double(m-1); double v = dom.vmin()*(1.0-rv) + rv*dom.vmax(); surf_.point(pt, u, v); // std::cout << pt << std::endl; // std::cout << "iu: " << iu << ", iv: " << iv << ", pt: " << pt << std::endl; int j; for (j=0; j<dim; ++j) mesh_->vertexArray()[(iv*n + iu)*3+j] = pt[j]; for (; j<3; ++j) mesh_->vertexArray()[(iv*n + iu)*3 + j] = 0.0; mesh_->paramArray()[(iv*n + iu)*2] = u; mesh_->paramArray()[(iv*n + iu)*2+1] = v; if (mesh_->useNormals()) { surf_.normal(pt, u, v); mesh_->normalArray()[(iv*n + iu)*3] = pt[0]; mesh_->normalArray()[(iv*n + iu)*3 + 1] = pt[1]; mesh_->normalArray()[(iv*n + iu)*3 + 2] = pt[2]; } if (mesh_->useTexCoords()) { mesh_->texcoordArray()[(iv*n + iu)*2] = ru; mesh_->texcoordArray()[(iv*n + iu)*2+1] = rv; } } } }
//=========================================================================== void VolumeModel::setBoundarySfs() //=========================================================================== { // Fetch all faces lying at outer boundaries, i.e. all faces with no twin vector<shared_ptr<ftSurface> > bd_faces = getBoundaryFaces(); #ifdef DEBUG_VOL2 std::ofstream of("bd_sfs.g2"); #endif // Make copy of all faces to avoid destroying existing topology // information in the shells of the solids vector<shared_ptr<ftSurface> > bd_faces2(bd_faces.size()); for (size_t ki=0; ki<bd_faces.size(); ++ki) { bd_faces2[ki] = shared_ptr<ftSurface>(new ftSurface(bd_faces[ki]->surface(), (int)ki)); bd_faces2[ki]->setBody(bd_faces[ki]->getBody()); #ifdef DEBUG_VOL2 shared_ptr<ParamSurface> surf = bd_faces[ki]->surface(); shared_ptr<SurfaceOnVolume> vsurf = dynamic_pointer_cast<SurfaceOnVolume,ParamSurface>(surf); if (vsurf.get()) { vsurf->spaceSurface()->writeStandardHeader(of); vsurf->spaceSurface()->write(of); } else { surf->writeStandardHeader(of); surf->write(of); } #endif } // Represent the outer boundaries as a SurfaceModel shared_ptr<SurfaceModel> sfmodel = shared_ptr<SurfaceModel>(new SurfaceModel(toptol_.gap, toptol_.gap, toptol_.neighbour, toptol_.kink, toptol_.bend, bd_faces2)); // Fetch all connected models vector<shared_ptr<SurfaceModel> > models = sfmodel->getConnectedModels(); if (models.size() == 1) boundary_shells_.push_back(models); else { // Sort models into connected submodels and inner and outer shells // First get maximum size of model BoundingBox box = boundingBox(); // Classify shells for (size_t ki=0; ki<models.size(); ++ki) { // Check if the current model is already classified size_t kj, kr; bool found = findBoundaryShell(models[ki], kj, kr); if (found) continue; // Shell already classified if (models[ki]->nmbEntities() == 0) continue; // Empty model // Make linear curve through current model shared_ptr<ftSurface> face = models[ki]->getFace(0); // Fetch a point on this face Point pnt, norm; shared_ptr<ParamSurface> srf = face->surface(); RectDomain dom = srf->containingDomain(); double upar = 0.5*(dom.umin()+dom.umax()); double vpar = 0.5*(dom.vmin()+dom.vmax()); Point pnt0 = srf->point(upar, vpar); double dist; face->closestPoint(pnt0, upar, vpar, pnt, dist, toptol_.gap); norm = face->normal(upar, vpar); // Make large enough curve double len = box.low().dist(box.high()); // Estimated box size norm.normalize(); Point pt1 = pnt - len*norm; Point pt2 = pnt + len*norm; shared_ptr<SplineCurve> crv = shared_ptr<SplineCurve>(new SplineCurve(pt1, pt2)); // Get model intersections vector<intersection_point> int_pts = getIntSfModelsCrv(models, crv); // Sort intersection points according to curve parameter std::sort(int_pts.begin(), int_pts.end(), par_compare); size_t i1, i2, i3, i4; for (kj=0; kj<int_pts.size(); ++kj) { // Find the next intersection with the same model for (kr=kj+1; kr<int_pts.size(); ++kr) if (int_pts[kj].shell_idx == int_pts[kr].shell_idx) break; if (kr == int_pts.size()) kr = kj; found = findBoundaryShell(models[int_pts[kj].shell_idx], i1, i2); if (!found) { vector<shared_ptr<SurfaceModel> > curr; curr.push_back(models[int_pts[kj].shell_idx]); boundary_shells_.push_back(curr); i1 = boundary_shells_.size() - 1; } // Add inner boundary shells for (size_t kh=kj+1; kh<=kr; ++kh) { found = findBoundaryShell(models[int_pts[kh].shell_idx], i3, i4); if (!found) boundary_shells_[i1].push_back(models[int_pts[kh].shell_idx]); } } } } }
//=========================================================================== void Torus::closestBoundaryPoint(const Point& pt, double& clo_u, double& clo_v, Point& clo_pt, double& clo_dist, double epsilon, const RectDomain* rd, double *seed) const //=========================================================================== { // Algorithm: // 1) Find closest point overall // 2) If on boundary, return // 3) Else, snap to boundary // Find closest point overall closestPoint(pt, clo_u, clo_v, clo_pt, clo_dist, epsilon); // Check if on boundary RectDomain dom = parameterDomain(); double umin = dom.umin(); double umax = dom.umax(); double vmin = dom.vmin(); double vmax = dom.vmax(); if (fabs(clo_u - umin) < epsilon || fabs(clo_u - umax) < epsilon || fabs(clo_v - vmin) < epsilon || fabs(clo_v - vmax) < epsilon) { return; } // Overall closest point is in the inner of the patch double clo_u_inner = clo_u; double clo_v_inner = clo_v; // Fist on boundary clo_u = umin; point(clo_pt, umin, clo_v_inner); clo_dist = pt.dist(clo_pt); // Second Point clo_pt_tmp; point(clo_pt_tmp, umax, clo_v_inner); double clo_dist_tmp = pt.dist(clo_pt_tmp); if (clo_dist_tmp < clo_dist) { clo_pt = clo_pt_tmp; clo_u = umax; clo_v = clo_v_inner; clo_dist = clo_dist_tmp; } // Third point(clo_pt_tmp, clo_u_inner, vmin); clo_dist_tmp = pt.dist(clo_pt_tmp); if (clo_dist_tmp < clo_dist) { clo_pt = clo_pt_tmp; clo_u = clo_u_inner; clo_v = vmin; clo_dist = clo_dist_tmp; } // Fourth point(clo_pt_tmp, clo_u_inner, vmax); clo_dist_tmp = pt.dist(clo_pt_tmp); if (clo_dist_tmp < clo_dist) { clo_pt = clo_pt_tmp; clo_u = clo_u_inner; clo_v = vmax; clo_dist = clo_dist_tmp; } return; }
//=========================================================================== int CurveBoundedDomain::positionPointInDomain(int pardir, double parval1, double parval2, double tolerance) const // Fetch all intervals in one parameter direction // going through a specific point lying inside the // bounded domain. // // Return value: -1 : Outside of outer loop // 0 : Inside domain // j>0 : Inside hole number j, i.e. inside loop number j //=========================================================================== { // Get the rectangular domain containing this domain RectDomain parbox = containingDomain(); // Make a constant curve in the parameter domain, in the given // direct slightly larger than the found containing domain. double par1[2], par2[2], vec[2]; double parint; int par_idx = 0; if (pardir == 2) { // Make constant parameter curve in 2. parameter direction. par1[0] = par2[0] = parval1; par1[1] = parbox.vmin(); par2[1] = parbox.vmax(); parint = std::max(par2[1] - par1[1], 0.1); par1[1] -= 0.1*parint; par2[1] += 0.1*parint; par_idx = 1; } else if (pardir == 1) { // Make constant parameter curve in 1. parameter direction. par1[1] = par2[1] = parval2; par1[0] = parbox.umin(); par2[0] = parbox.umax(); parint = std::max(par2[0] - par1[0], 0.1); par1[0] -= 0.1*parint; par2[0] += 0.1*parint; par_idx = 0; } else { // Diagonal parameter curve par1[0] = par2[0] = parval1; par1[1] = par2[1] = parval2; vec[0] = parbox.umax() - parbox.umin(); vec[1] = parbox.vmax() - parbox.vmin(); par1[0] -= vec[0]; par1[1] -= vec[1]; par2[0] += vec[0]; par2[1] += vec[1]; par_idx = 0; // @@@ VSK, 0309. This is not really correct } Point pnt1(par1[0], par1[1]); Point pnt2(par2[0], par2[1]); SplineCurve isopar(pnt1, pnt2); vector<intersection_point> intpt; findPcurveInsideSegments(isopar, tolerance, intpt); int ki; int nmbpoint = (int)intpt.size(); if (nmbpoint == 1) { // Assuming non-recognized tangential intersection return -1; } else if (nmbpoint%2 != 0) { throw std::logic_error("Odd number of intersections."); } double ptol = 1.0e-8; for (ki=1; ki<nmbpoint; ki+=1) { // Check if the initial point lies inside the current interval Point eval1, eval2; isopar.point(eval1, intpt[ki-1].par1); isopar.point(eval2, intpt[ki].par1); if (eval1[0]-ptol < parval1 && eval2[0]+ptol > parval1 && eval1[1]-ptol < parval2 && eval2[1]+ptol > parval2) { // The point lies inside this interval. Check if the interval // corresponds to an inner loop int loop1 = intpt[ki-1].loop_idx; int loop2 = intpt[ki].loop_idx; if (loop1 != loop2) return 0; // In the domain else return loop1; } } return -1; // The point lies outside the domain }
//=========================================================================== void CurveBoundedDomain::getInsideIntervals(int pardir, double parval1, double parval2, double tolerance, vector<pair<double, double> >& insideInts, bool with_bd) const // Fetch all intervals in one parameter direction // going through a specific point lying inside the // bounded domain. //=========================================================================== { // Get the rectangular domain containing this domain RectDomain parbox = containingDomain(); Point mid(0.5*(parbox.umin()+parbox.umax()), 0.5*(parbox.vmin()+parbox.vmax())); Point parpt(parval1, parval2); double len1 = (parbox.umax()-parbox.umin())+(parbox.vmax()-parbox.vmin()); double len2 = mid.dist(parpt); if (len1 == 0.0) { MESSAGE("Degenerate domain!"); return; } double mult_fac = 2.0*(len1+len2)/len1; // The curve with which to intersect // should be much larger than the trimmed domain // Make a constant curve in the parameter domain, in the given // direct slightly larger than the found containing domain. double par1[2], par2[2], vec[2]; double parint; int par_idx = 0; double len; if (pardir == 2) { // Make constant parameter curve in 2. parameter direction. par1[0] = par2[0] = parval1; par1[1] = parbox.vmin(); par2[1] = parbox.vmax(); parint = std::max(par2[1] - par1[1], 0.1); len = mult_fac*parint; par1[1] -= len; par2[1] += len; par_idx = 1; } else if (pardir == 1) { // Make constant parameter curve in 1. parameter direction. par1[1] = par2[1] = parval2; par1[0] = parbox.umin(); par2[0] = parbox.umax(); parint = std::max(par2[0] - par1[0], 0.1); len = mult_fac*parint; par1[0] -= len; par2[0] += len; par_idx = 0; } else { // Diagonal parameter curve par1[0] = par2[0] = parval1; par1[1] = par2[1] = parval2; vec[0] = parbox.umax() - parbox.umin(); vec[1] = parbox.vmax() - parbox.vmin(); len = mult_fac*sqrt(vec[0]*vec[0]+vec[1]*vec[1]); par1[0] -= (mult_fac*vec[0]); par1[1] -= (mult_fac*vec[1]); par2[0] += (mult_fac*vec[0]); par2[1] += (mult_fac*vec[1]); par_idx = 0; // @@@ VSK, 0309. This is not really correct } Point pnt1(par1[0], par1[1]); Point pnt2(par2[0], par2[1]); SplineCurve isopar(pnt1, -len, pnt2, len); vector<intersection_point> intpt; findPcurveInsideSegments(isopar, tolerance, intpt, with_bd); int ki; int nmbpoint = (int)intpt.size(); if (nmbpoint == 1) { // Assuming non-recognized tangential intersection return; } else if (nmbpoint%2 != 0) { throw std::logic_error("Odd number of intersections."); } for (ki=1; ki<nmbpoint; ki+=2) { Point eval1, eval2; isopar.point(eval1, intpt[ki-1].par1); isopar.point(eval2, intpt[ki].par1); insideInts.push_back(std::make_pair(eval1[par_idx], eval2[par_idx])); // std::cout << eval1[2-pardir] <<" , " << eval2[2-pardir] << std::endl; } }
//=========================================================================== double BoundedSurface::area(double tol) const //=========================================================================== { double fac = 10.0; // Get surrounding domain RectDomain domain = containingDomain(); // Get smallest surrounding surface shared_ptr<ParamSurface> base_sf = surface_; while (base_sf->instanceType() == Class_BoundedSurface) base_sf = dynamic_pointer_cast<BoundedSurface, ParamSurface>(base_sf)->underlyingSurface(); vector<shared_ptr<ParamSurface> > sfs = base_sf->subSurfaces(domain.umin(), domain.vmin(), domain.umax(), domain.vmax()); double total_area = 0.0; size_t kr; for (kr=0; kr<sfs.size(); ++kr) { shared_ptr<SplineSurface> spline_sf = dynamic_pointer_cast<SplineSurface, ParamSurface>(sfs[kr]); if (spline_sf.get()) total_area += spline_sf->area(tol); } if (isIsoTrimmed(0.1*tol)) { // We are finished return total_area; } std::ofstream out_file("tmp_mini_surf.g2"); // Otherwise, split the current surface into smaller pieces and compare areas int nmb_split = 5; double u1 = domain.umin(); double v1 = domain.vmin(); double u_del = (domain.umax() - u1)/(double)(nmb_split); double v_del = (domain.vmax() - v1)/(double)(nmb_split); int ki, kj; double curr_area = 0.0; vector<shared_ptr<ParamSurface> > all_sfs; for (kj=0; kj<nmb_split; ++kj, v1+=v_del) for (ki=0, u1=domain.umin(); ki<nmb_split; ++ki, u1+=u_del) { vector<shared_ptr<ParamSurface> > sub_sfs = subSurfaces(u1, v1, u1+u_del, v1+v_del); for (kr=0; kr<sub_sfs.size(); ++kr) { // sub_sfs[ki]->writeStandardHeader(out_file); // sub_sfs[ki]->write(out_file); RectDomain dom2 = sub_sfs[kr]->containingDomain(); vector<shared_ptr<ParamSurface> > tmp_sfs = base_sf->subSurfaces(std::min(u1,dom2.umin()), std::min(v1,dom2.vmin()), std::max(u1+u_del,dom2.umax()), std::max(v1+v_del,dom2.vmax())); curr_area += tmp_sfs[0]->area(tol); } all_sfs.insert(all_sfs.end(), sub_sfs.begin(), sub_sfs.end()); } if (total_area/curr_area < 1.0 + fac*tol) return curr_area; // The area is close enough // Compute recursively curr_area = 0.0; for (kr=0; kr<all_sfs.size(); ++kr) curr_area += all_sfs[kr]->area(tol); return curr_area; }