Esempio n. 1
0
// Add a face to the partial boundingbox result.
static void ON_Brep_GetTightFaceBoundingBox_Helper( const ON_BrepFace& face, ON_BoundingBox& bbox, const ON_Xform* xform, const ON_Xform* xform_inverse )
{
  ON_BoundingBox loose_box;

  // This should ideally test for planarity inside the OuterLoop() pbox only,
  // but no such function exists in the SDK as far as I can tell.
  if( face.IsPlanar() )
    return;

  // Get loose boundingbox of face.
  if( face.GetBoundingBox(loose_box, false) )
  {
    if( xform_inverse ) 
      loose_box.Transform(*xform_inverse); 

    if( bbox.Includes(loose_box, false) )
      return;
  }

  const TL_Brep* tlbrep = TL_Brep::Promote(face.Brep());
  if( tlbrep )
  {
    ON_Brep_GetTightIsoCurveBoundingBox_Helper( *tlbrep, face, bbox, xform, 0);
    ON_Brep_GetTightIsoCurveBoundingBox_Helper( *tlbrep, face, bbox, xform, 1);
  }
}
Esempio n. 2
0
bool
brep_pt_trimmed(pt2d_t pt, const ON_BrepFace& face) {
    bool retVal = false;
    TRACE1("brep_pt_trimmed: " << PT2(pt));
    // for each loop
    const ON_Surface* surf = face.SurfaceOf();
    double umin, umax;
    ON_2dPoint from, to;
    from.x = pt[0];
    from.y = to.y = pt[1];
    surf->GetDomain(0, &umin, &umax);
    to.x = umax + 1;
    ON_Line ray(from,to);
    int intersections = 0;
    for (int i = 0; i < face.LoopCount(); i++) {
	ON_BrepLoop* loop = face.Loop(i);
	// for each trim
	for (int j = 0; j < loop->m_ti.Count(); j++) {
	    ON_BrepTrim& trim = face.Brep()->m_T[loop->m_ti[j]];
	    const ON_Curve* trimCurve = trim.TrimCurveOf();
	    // intersections += brep_count_intersections(ray, trimCurve);
	    //ray.IntersectCurve(trimCurve, intersections, 0.0001);
	    intersections += trimCurve->NumIntersectionsWith(ray);
	}
    }
// If we base trimming on the number of intersections with, rhino generated curves won't raytrace.
// In fact, we need to ignore trimming for the time being, just return false.
// To do: figure out what this code does, and fix it for rhino generated geometries. djg 4/16/08
    // the point is trimmed if the # of intersections is even and non-zero
    retVal= (intersections > 0 && (intersections % 2) == 0);

    return retVal;
}
Esempio n. 3
0
RH_C_FUNCTION const ON_Surface* ON_BrepFace_SurfaceOf( const ON_Brep* pConstBrep, int faceIndex )
{
  const ON_Surface* rc = NULL;
  if( pConstBrep )
  {
    ON_BrepFace* pFace = pConstBrep->Face(faceIndex);
    if( pFace )
      rc = pFace->SurfaceOf();
  }
  return rc;
}
Esempio n. 4
0
RH_C_FUNCTION const ON_Mesh* ON_BrepFace_Mesh( const ON_Brep* pConstBrep, int faceIndex, int meshtype )
{
  const ON_Mesh* rc = NULL;
  if( pConstBrep )
  {
    ON_BrepFace* pFace = pConstBrep->Face(faceIndex);
    if( pFace )
    {
      rc = pFace->Mesh( ON::MeshType(meshtype) );
    }
  }
  return rc;
}
Esempio n. 5
0
RH_C_FUNCTION ON_Surface* ON_Brep_DuplicateFaceSurface( const ON_Brep* pConstBrep, int faceIndex )
{
  ON_Surface* rc = NULL;
  if( pConstBrep )
  {
    ON_BrepFace* pFace = pConstBrep->Face(faceIndex);
    if( pFace )
    {
      const ON_Surface* pSurf = pFace->SurfaceOf();
      if( pSurf )
        rc = pSurf->DuplicateSurface();
    }
  }
  return rc;
}
Esempio n. 6
0
// XXX - most of this function is broken :-( except for the bezier span caching
// need to fix it! - could provide real performance benefits...
void
brep_preprocess_trims(const ON_BrepFace& face, SurfaceTree* tree) {

    list<BBNode*> leaves;
    tree->getLeaves(leaves);

    for (list<BBNode*>::iterator i = leaves.begin(); i != leaves.end(); i++) {
	SubsurfaceBBNode* bb = dynamic_cast<SubsurfaceBBNode*>(*i);


	// XXX - TODO: check to see if this portion of the surface
	// needs to be checked for trims
	pt2d_t test[] = {{bb->m_u.Min(),bb->m_v.Min()},
			 {bb->m_u.Max(),bb->m_v.Min()},
			 {bb->m_u.Max(),bb->m_v.Max()},
			 {bb->m_u.Min(),bb->m_v.Max()}};


	// check to see if the bbox encloses a trim
	ON_3dPoint uvmin(bb->m_u.Min(),bb->m_v.Min(),0);
	ON_3dPoint uvmax(bb->m_u.Max(),bb->m_v.Max(),0);
	ON_BoundingBox bbox(uvmin,uvmax);
	bool internalTrim = false;
	for (int i = 0; i < face.Brep()->m_L.Count(); i++) {
	    ON_BrepLoop& loop = face.Brep()->m_L[i];
	    // for each trim
	    for (int j = 0; j < loop.m_ti.Count(); j++) {
		ON_BrepTrim& trim = face.Brep()->m_T[loop.m_ti[j]];
		if (bbox.Intersection(trim.m_pbox)) internalTrim = true;

		// tell the NURBS curves to cache their Bezier spans
		// (used in trimming routines, and not thread safe)
		const ON_Curve* c = trim.TrimCurveOf();
		if (c->ClassId()->IsDerivedFrom(&ON_NurbsCurve::m_ON_NurbsCurve_class_id)) {
		    ON_NurbsCurve::Cast(c)->CacheBezierSpans();
		}
	    }
	}
	bb->m_checkTrim = true; // XXX - ack, hardcode for now
	// for this node to be completely trimmed, all four corners
	// must be trimmed and the depth of the tree needs to be > 0,
	// since 0 means there is just a single leaf - and since
	// "internal" outer loops will be make a single node seem
	// trimmed, we must account for it.
	bb->m_trimmed = false; // XXX - ack, hardcode for now
    }
}
Esempio n. 7
0
// Add the isocurves of a BrepFace to the partial boundingbox result.
static void ON_Brep_GetTightIsoCurveBoundingBox_Helper( const TL_Brep& tlbrep, const ON_BrepFace& face, ON_BoundingBox& bbox, const ON_Xform* xform, int dir )
{
  ON_Interval domain = face.Domain(1 - dir);
  int degree =         face.Degree(1 - dir);
  int spancount =      face.SpanCount(1 - dir);
  int spansamples =    degree * (degree + 1) - 1;
  if( spansamples < 2 )
    spansamples = 2;

  // pbox delineates the extremes of the face interior.
  // We can use it to trivially reject spans and isocurves.
  ON_BrepLoop* pOuterLoop = face.OuterLoop();
  if( NULL==pOuterLoop )
    return;

  const ON_BoundingBox& pbox = pOuterLoop->m_pbox;
  double t0 = ((dir == 0) ? pbox.Min().y : pbox.Min().x);
  double t1 = ((dir == 0) ? pbox.Max().y : pbox.Max().x);

  // Get the surface span vector.
  ON_SimpleArray<double> spanvector(spancount + 1);
  spanvector.SetCount(spancount + 1);
  face.GetSpanVector(1 - dir, spanvector.Array());

  // Generate a list of all the sampling parameters.
  ON_SimpleArray<double> samples(spancount * spansamples);
  for( int s = 0; s < spancount; s++)
  {
    double s0 = spanvector[s];
    double s1 = spanvector[s+1];

    // Reject span if it does not intersect the pbox.
    if( s1 < t0 ) { continue; }
    if( s0 > t1 ) { continue; }
    
    ON_Interval span(s0, s1);
    for( int i = 1; i < spansamples; i++ )
    {
      double t = span.ParameterAt((double)i / (double)(spansamples - 1));
      // Reject iso if it does not intersect the pbox.
      if( t < t0 )
        continue;
      if( t > t1 )
        break;
      samples.Append(t);
    }
  }

  //Iterate over samples
  int sample_count = samples.Count();
  ON_BoundingBox loose_box;
  ON_SimpleArray<ON_Interval> intervals;
  ON_NurbsCurve isosubcrv;

  for( int i = 0; i<sample_count; i++)
  {
    // Retrieve iso-curve.
    ON_Curve* isocrv = face.IsoCurve(dir, samples[i]);

    while( NULL!=isocrv )
    {
      // Transform isocurve if necessary, this is better than transforming downstream boundingboxes.
      if( xform )
        isocrv->Transform(*xform);

      // Compute loose box.
      if( !isocrv->GetBoundingBox(loose_box, false))
        break;

      // Determine whether the loose box is already contained within the partial result.
      if( bbox.Includes(loose_box, false) ) 
        break;

      // Solve trimming domains for the iso-curve.
      intervals.SetCount(0);
      if( !tlbrep.GetIsoIntervals(face, dir, samples[i], intervals))
        break;

      // Iterate over trimmed iso-curves.
      int interval_count = intervals.Count();
      for( int k=0; k<interval_count; k++ )
      {
        //this to mask a bug in Rhino4. GetNurbForm does not destroy the Curve Tree. It does now.
        isosubcrv.DestroyCurveTree();
        isocrv->GetNurbForm(isosubcrv, 0.0, &intervals[k]);
        ON_Brep_GetTightCurveBoundingBox_Helper(isosubcrv, bbox, NULL, NULL);
      }
      break;
    }

    if( isocrv )
    {
      delete isocrv;
      isocrv = NULL;
    }
  }
}
Esempio n. 8
0
void ON_GL( const ON_BrepFace& face,
            GLUnurbsObj* nobj     // created with gluNewNurbsRenderer )
          )
{
  bool bSkipTrims = false;

  const ON_Mesh* mesh;
  mesh = face.Mesh(ON::render_mesh);
  if ( mesh ) 
  {
    // use saved render mesh
    ON_GL(*mesh);
  }
  else 
  {
    // use (slow and buggy) glu trimmed NURBS rendering
    double knot_scale[2][2] = {{0.0,1.0},{0.0,1.0}};
    const ON_Brep* brep = face.Brep();
    if ( !brep )
      return;

    // untrimmed surface
    {
      ON_NurbsSurface tmp_nurbssrf;
      const ON_Surface* srf = brep->m_S[face.m_si];
      const ON_NurbsSurface* nurbs_srf = ON_NurbsSurface::Cast(srf);
      if ( !nurbs_srf ) 
      {
        // attempt to get NURBS form of this surface
        if ( srf->GetNurbForm( tmp_nurbssrf ) )
          nurbs_srf = &tmp_nurbssrf;
      }
      if ( !nurbs_srf )
        return;
      gluBeginSurface( nobj );
      ON_GL( *nurbs_srf,
             nobj, 
             (nurbs_srf->IsRational()) ? GL_MAP2_VERTEX_4 : GL_MAP2_VERTEX_3,
             true, knot_scale[0], knot_scale[1]
            );
    }

    if ( bSkipTrims || brep->FaceIsSurface( face.m_face_index ) ) {
      gluEndSurface( nobj );
      return; // face is trivially trimmed
    }

    int fli, li, lti, ti;

    // any knot scaling applied to the surface must also be applied to
    // the parameter space trimming geometry
    double xform[4][4] 
      = {{knot_scale[0][1], 0.0, 0.0, -knot_scale[0][0]*knot_scale[0][1] },
         {0.0, knot_scale[1][1], 0.0, -knot_scale[1][0]*knot_scale[1][1] },
         {0.0, 0.0, 1.0, 0.0},
         {0.0, 0.0, 0.0, 1.0}};

    // Add face's 2d trimming loop(s)
    const int face_loop_count = face.m_li.Count();
    for ( fli = 0; fli < face_loop_count; fli++ ) 
    {
      gluBeginTrim( nobj );

      li = face.m_li[fli];
      const ON_BrepLoop& loop = brep->m_L[li];
      const int loop_trim_count = loop.m_ti.Count();
      for ( lti = 0; lti < loop_trim_count; lti++ )
      {
        ti = loop.m_ti[lti];
        const ON_BrepTrim& trim = brep->m_T[ti];
        ON_GL( trim,
               nobj, 
               GLU_MAP1_TRIM_2,
               xform
              );
      }

      gluEndTrim( nobj );
    }
    gluEndSurface( nobj );
  }
}
static bool SealSeam(int closed_dir, ON_BrepFace& F)

{
  if (closed_dir) closed_dir = 1;
  int seam_dir = 1-closed_dir;
  ON_Brep* pBrep = F.Brep();
  if (!pBrep) return false;
  const ON_Surface* pSrf = F.SurfaceOf();
  if (!pSrf || !pSrf->IsClosed(closed_dir)) return false;

  ON_Surface::ISO isoA = ON_Surface::not_iso;//same dir as isocurve
  ON_Surface::ISO isoB = ON_Surface::not_iso;//opposite dir as isocurve
  if (closed_dir){
    isoA = ON_Surface::S_iso;
    isoB = ON_Surface::N_iso;
  }
  else {
    isoA = ON_Surface::E_iso;
    isoB = ON_Surface::W_iso;
  }

  /* TODO: Handle cases where there is more than one trim on a seam side 
     or seam edges do not fully overlap.
  */

  //Look for a single pair of trims that match across parameter space.

  int A_id = -1;
  int B_id = -1;

  int li;
  for (li=0; li<F.m_li.Count(); li++){
    const ON_BrepLoop* L = F.Loop(li);
    if (!L || L->m_type !=  ON_BrepLoop::outer) continue;
    int lti;
    for (lti = 0; lti<L->m_ti.Count(); lti++ ){
      ON_BrepTrim* T = L->Trim(lti);
      if (!T) continue;
      if (T->m_iso == isoA) {
        if (A_id >= 0)
          return false;
        A_id = T->m_trim_index;
      }
      else if (T->m_iso == isoB) {
        if (B_id >= 0)
          return false;
        B_id = T->m_trim_index;
      }
    }
  }

  if (A_id < 0 || B_id < 0)
    return true;//no seam to join

  ON_BrepTrim& TA = pBrep->m_T[A_id];
  ON_BrepTrim& TB = pBrep->m_T[B_id];

  ON_BrepEdge* pEA = TA.Edge();
  ON_BrepEdge* pEB = TB.Edge();
  if (!pEA || !pEB)
    return false;

  ON_Interval a,b;
  int i;
  for (i=0; i<2; i++){
    a[i] = TA.PointAt(TA.Domain()[i])[seam_dir];
    b[i] = TB.PointAt(TB.Domain()[i])[seam_dir];
  }

  a.MakeIncreasing();
  b.MakeIncreasing();

  if (a[0] >= b[1] || b[0] >= a[1])
    return true; //nothing to be joined;

  double pspace_tol = 1.0e-8;

  if (a.Length() < 10.0*pspace_tol)
    return false;
  if (fabs(a[0] - b[0]) > pspace_tol || fabs(a[1] - b[1]) > pspace_tol)
    return false;

  //fix vertices so join will work.

  RebuildVertexToTrimEnd(TA, 0);
  RebuildVertexToTrimEnd(TA, 1);
  RebuildVertexToTrimEnd(TB, 0);
  RebuildVertexToTrimEnd(TB, 1);

  double join_tol = 1.0e-6;
  if (!pBrep->JoinEdges(*pEA, *pEB, join_tol))
    return false;

  TA.m_type = ON_BrepTrim::seam;
  TB.m_type = ON_BrepTrim::seam;

  return true;
}