예제 #1
0
//===========================================================================
DirectionCone Torus::tangentCone(bool pardir_is_u) const
//===========================================================================
{
    if (isSwapped())
        pardir_is_u = !pardir_is_u;

    if (pardir_is_u) {
      double par = domain_.umin() -
	parbound_.umin()*(domain_.umax()-domain_.umin())/(parbound_.umax()-parbound_.umin());
	shared_ptr<Circle> circle = getMajorCircle(par);
	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);
    }
}
예제 #2
0
파일: VolumeModel.C 프로젝트: 99731/GoTools
//===========================================================================
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]);
		}
	    }
	}
    }
}
예제 #3
0
//===========================================================================
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;
}
예제 #4
0
//===========================================================================
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
}
예제 #5
0
//===========================================================================
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;
    }

  
}
예제 #6
0
파일: GSBarea.C 프로젝트: 99731/GoTools
//===========================================================================
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;
}