osg::Node* RhinoReader::BuildEdge(const ON_Brep* theBrep) { osg::ref_ptr<osg::Geode> aGeode = new osg::Geode(); for (int i = 0; i < theBrep->m_E.Count(); ++i) { osg::ref_ptr<osg::Geometry> aGeometry = new osg::Geometry(); osg::ref_ptr<osg::Vec3Array> aVertices = new osg::Vec3Array(); ON_BrepEdge* anEdge = theBrep->Edge(i); double t0 = 0.0; double t1 = 0.0; double d = 0.0; anEdge->GetDomain(&t0, &t1); d = (t1 - t0) / 5.0; for (double t = t0; (t - t1) < TOLERANCE_EDGE; t += d) { ON_3dPoint aPoint = anEdge->PointAt(t); aVertices->push_back(osg::Vec3(aPoint.x, aPoint.y, aPoint.z)); } aGeometry->setVertexArray(aVertices); aGeometry->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP, 0, aVertices->size())); aGeode->addDrawable(aGeometry); } return aGeode.release(); }
int brep_edge_check(int reason, const SubsurfaceBBNode* sbv, const ON_BrepFace* face, const ON_Surface* surf, const ON_Ray& r, HitList& hits) { // if the intersection was not found for any reason, we need to // check and see if we are close to any topological edges; we may // have hit a crack... // the proper way to do this is to only look at edges // interesecting with the subsurface bounding box... but for // now, we'll look at the edges associated with the face for the bounding box... // XXX - optimize this set<ON_BrepEdge*> edges; ON_3dPoint pt; for (int i = 0; i < face->LoopCount(); i++) { ON_BrepLoop* loop = face->Loop(i); for (int j = 0; j < loop->TrimCount(); j++) { ON_BrepTrim* trim = loop->Trim(j); ON_BrepEdge* edge = trim->Edge(); pair<set<ON_BrepEdge*>::iterator, bool> res = edges.insert(edge); // if (res.second) { // only check if its the first time we've seen this // edge const ON_Curve* curve = edge->EdgeCurveOf(); Sample s; if (curve->CloseTo(ON_3dPoint(hits.back().point), BREP_EDGE_MISS_TOLERANCE, s)) { TRACE1("CLOSE TO EDGE"); hits.back().closeToEdge = true; return BREP_INTERSECT_FOUND; } } } return BREP_INTERSECT_TRIMMED; }
bool ON_Brep::IsValidForV2( const ON_BrepEdge& edge ) const { int ei = edge.m_edge_index; if ( ei < 0 || ei >= m_E.Count() ) return false; if ( &edge != &m_E[ei] ) return false; if ( edge.ProxyCurveIsReversed() ) return false; if ( edge.Domain() != edge.ProxyCurveDomain() ) return false; const ON_Curve * curve = edge.EdgeCurveOf(); if ( curve != edge.ProxyCurve() ) return false; const ON_NurbsCurve* nurbs_curve = ON_NurbsCurve::Cast(curve); if ( 0 == nurbs_curve ) return false; if ( !nurbs_curve->IsClamped(2) ) return false; if ( nurbs_curve->m_dim != 3 ) return false; if ( nurbs_curve->m_is_rat ) { // 2 June 2003 Dale Lear - RR 8809 fix // V2 likes end weights to be 1.0 if ( nurbs_curve->m_cv[3] != 1.0 || nurbs_curve->CV(nurbs_curve->m_cv_count-1)[3] != 1.0 ) { return false; } } if ( curve->Domain() != edge.Domain() ) return false; // 14 April 2003 Dale Lear // RR 8808 - V2 requires edges to be strictly closed/open if ( nurbs_curve->m_cv_count >= 4 && 0 == ON_ComparePoint( nurbs_curve->m_dim, nurbs_curve->m_is_rat, nurbs_curve->m_cv, nurbs_curve->CV(nurbs_curve->m_cv_count-1) ) ) { if ( edge.m_vi[0] != edge.m_vi[1] ) return false; } else if (edge.m_vi[0] == edge.m_vi[1] ) { return false; } return true; }
int ON_Brep::SplitEdgeAtParameters( int edge_index, int edge_t_count, const double* edge_t ) { // Default kink_tol_radians MUST BE ON_PI/180.0. // // The default kink tol must be kept in sync with the default for // TL_Brep::SplitKinkyFace() and ON_Brep::SplitKinkyFace(). // See comments in TL_Brep::SplitKinkyFace() for more details. if (0 == edge_t_count) return 0; if (0 == edge_t) return 0; if (edge_index < 0 || edge_index >= m_E.Count()) return 0; ON_BrepEdge& E = m_E[edge_index]; if (E.m_c3i < 0) return 0; ON_Curve* curve = m_C3[E.m_c3i]; if (!curve) return 0; ON_Interval Edomain; if ( !E.GetDomain(&Edomain.m_t[0],&Edomain.m_t[1]) ) return 0; if ( !Edomain.IsIncreasing() ) return 0; // get a list of unique and valid splitting parameters ON_SimpleArray<double> split_t(edge_t_count); { for (int i = 0; i < edge_t_count; i++) { double e = edge_t[i]; if ( !ON_IsValid(e) ) { ON_ERROR("Invalid edge_t[] value"); continue; } if ( e <= Edomain.m_t[0] ) { ON_ERROR("edge_t[] <= start of edge domain"); continue; } if ( e >= Edomain.m_t[1] ) { ON_ERROR("edge_t[] >= end of edge domain"); continue; } split_t.Append(e); } if ( split_t.Count() > 1 ) { // sort split_t[] and remove duplicates ON_SortDoubleArray( ON::heap_sort, split_t.Array(), split_t.Count() ); int count = 1; for ( int i = 1; i < split_t.Count(); i++ ) { if ( split_t[i] > split_t[count-1] ) { if ( i > count ) split_t[count] = split_t[i]; count++; } } split_t.SetCount(count); } } if (split_t.Count() <= 0) return 0; // Reverse split_t[] so the starting segment of the original // edge m_E[edge_index] is the one at m_E[edge_index]. split_t.Reverse(); ON_Curve* new_curve = TuneupSplitteeHelper(m_E[edge_index].ProxyCurve()); if ( 0 != new_curve ) { m_E[edge_index].m_c3i = AddEdgeCurve(new_curve); m_E[edge_index].SetProxyCurve(new_curve); new_curve = 0; } int eti, ti; int successful_split_count = 0; for (int i=0; i<split_t.Count(); i++) { double t0, t1; m_E[edge_index].GetDomain(&t0, &t1); if (t1 - t0 < 10.0*ON_ZERO_TOLERANCE) break; //6 Dec 2002 Dale Lear: // I added the relative edge_split_s and trm_split_s tests to detect // attempts to trim a nano-gnats-wisker off the end of a trim. double edge_split_s = ON_Interval(t0,t1).NormalizedParameterAt(split_t[i]); double trim_split_s = 0.5; if (split_t[i] - t0 <= ON_ZERO_TOLERANCE || edge_split_s <= ON_SQRT_EPSILON ) { // this split is not possible continue; } if (t1 - split_t[i] <= ON_ZERO_TOLERANCE || edge_split_s >= 1.0-ON_SQRT_EPSILON) { // this split is not possible continue; } // trim_t[] = corresponding trim parameters ON_SimpleArray<double> trim_t(m_E[edge_index].m_ti.Count()); for ( eti = 0; eti < m_E[edge_index].m_ti.Count(); eti++) { ti = m_E[edge_index].m_ti[eti]; if ( ti < 0 || ti >= m_T.Count() ) continue; ON_BrepTrim& trim = m_T[ti]; if ( 0 == i ) { // On the first split, make sure the trim curve is up to snuff. new_curve = TuneupSplitteeHelper(trim.ProxyCurve()); if (new_curve) { trim.m_c2i = AddTrimCurve(new_curve); trim.SetProxyCurve(new_curve); new_curve = 0; } } double t = ON_UNSET_VALUE; if (!GetTrimParameter(ti, split_t[i], &t) || !ON_IsValid(t)) break; trim_t.Append(t); const ON_Interval trim_domain = trim.Domain(); trim_split_s = trim_domain.NormalizedParameterAt(t); if ( trim_split_s <= ON_SQRT_EPSILON || t - trim_domain[0] <= ON_ZERO_TOLERANCE ) break; if ( trim_split_s >= 1.0-ON_SQRT_EPSILON || trim_domain[1] - t <= ON_ZERO_TOLERANCE ) break; } if ( trim_t.Count() != m_E[edge_index].m_ti.Count() ) continue; if (!SplitEdge(edge_index, split_t[i], trim_t)) { continue; } // SplitEdge generally adjusts proxy domains instead // of trimming the orginal curve. These DuplicateCurve() // calls make a new curve whose domain exactly matches // the edge. for ( int epart = 0; epart < 2; epart++ ) { ON_BrepEdge* newE = (0 == epart) ? &m_E[edge_index] : m_E.Last(); if ( 0 == newE ) continue; new_curve = TuneupEdgeOrTrimRealCurve(*newE,true); if (new_curve) { newE->m_c3i = AddEdgeCurve(new_curve); newE->SetProxyCurve(new_curve); } for ( eti = 0; eti < newE->m_ti.Count(); eti++ ) { ti = newE->m_ti[eti]; if ( ti < 0 || ti >= m_T.Count() ) continue; ON_BrepTrim& trim = m_T[ti]; new_curve = TuneupEdgeOrTrimRealCurve(trim,false); if (new_curve) { trim.m_c2i = AddTrimCurve(new_curve); trim.SetProxyCurve(new_curve); } } } successful_split_count++; } return successful_split_count; }