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_BrepTrim& trim ) const { int ti = trim.m_trim_index; if ( ti < 0 || ti >= m_T.Count() ) return false; if ( &trim != &m_T[ti] ) return false; if ( trim.ProxyCurveIsReversed() ) return false; if ( trim.Domain() != trim.ProxyCurveDomain() ) return false; const ON_Curve * curve = trim.TrimCurveOf(); if ( curve != trim.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 != 2 ) 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[2] != 1.0 || nurbs_curve->CV(nurbs_curve->m_cv_count-1)[2] != 1.0 ) { return false; } } 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) ) ) { // 14 April 2003 Dale Lear // RR 8843 - V2 wants ends of this trim farther apart if ( trim.m_vi[0] != trim.m_vi[1] ) { const ON_BrepLoop* loop = Loop(trim.m_li); if ( 0 != loop && loop->m_ti.Count() > 1 ) return false; } } if ( curve->Domain() != trim.Domain() ) return false; return true; }
static bool RebuildVertexToTrimEnd(ON_BrepTrim& T, int end) { ON_Brep* pB = T.Brep(); if (!pB) return false; int vid = T.m_vi[end]; if (vid < 0) return false; ON_BrepVertex& V = pB->m_V[vid]; ON_3dPoint P; if (end){ if (!pB->GetTrim3dEnd(T.m_trim_index, P)) return false; } else { if (!pB->GetTrim3dStart(T.m_trim_index, P)) return false; } V.SetPoint(P); return true; }
osg::Node* RhinoReader::BuildShadedFace(const ON_BrepFace* theFace) { osg::ref_ptr<osg::Geode> aGeode = new osg::Geode(); ON_NurbsSurface aSurface; if (theFace->GetNurbForm(aSurface) == 0) { return NULL; } osg::ref_ptr<osg::Geometry> aGeometry = new osg::Geometry(); osg::ref_ptr<osg::Vec3Array> aUVPoints = new osg::Vec3Array(); osg::ref_ptr<osg::Vec3Array> aPoints = new osg::Vec3Array(); osg::ref_ptr<osg::Vec3Array> aBounds = new osg::Vec3Array(); osg::ref_ptr<osgUtil::DelaunayTriangulator> dt = new osgUtil::DelaunayTriangulator(); osg::ref_ptr<osgUtil::DelaunayConstraint> dc = new osgUtil::DelaunayConstraint(); // add loop for the face. for (int i = 0; i < theFace->LoopCount(); ++i) { ON_BrepLoop* aLoop = theFace->Loop(i); if (aLoop->m_type == ON_BrepLoop::outer) { for (int j = 0; j < aLoop->TrimCount(); ++j) { ON_BrepTrim* aTrim = aLoop->Trim(j); const ON_Curve* aPCurve = aTrim->TrimCurveOf(); if (aPCurve) { ON_3dPoint aStartPoint = aPCurve->PointAtStart(); ON_3dPoint aEndPoint = aPCurve->PointAtEnd(); aUVPoints->push_back(osg::Vec3(aStartPoint.x, aStartPoint.y, 0.0)); aUVPoints->push_back(osg::Vec3(aEndPoint.x, aEndPoint.y, 0.0)); } } } else if (aLoop->m_type == ON_BrepLoop::inner) { for (int j = 0; j < aLoop->TrimCount(); ++j) { } } } dc->setVertexArray(aBounds); dc->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_LOOP, 0, aBounds->size())); // triangulate the parametric space. //dt->addInputConstraint(dc); dt->setInputPointArray(aUVPoints); dt->triangulate(); //dt->removeInternalTriangles(dc); for (osg::Vec3Array::const_iterator j = aUVPoints->begin(); j != aUVPoints->end(); ++j) { // evaluate the point on the surface ON_3dPoint aPoint = aSurface.PointAt((*j).x(), (*j).y()); aPoints->push_back(osg::Vec3(aPoint.x, aPoint.y, aPoint.z)); } //aGeometry->setVertexArray(aUVPoints); aGeometry->setVertexArray(aPoints); aGeometry->addPrimitiveSet(dt->getTriangles()); aGeode->addDrawable(aGeometry); // use smoothing visitor to set the average normals //osgUtil::SmoothingVisitor sv; //sv.apply(*aGeode); return aGeode.release(); }
static bool SplitSeam( ON_Brep& brep, ON_BrepTrim& trimA, ON_BrepTrim& trimB, ON_BrepTrim& prevtrimB, ON_BrepTrim& nexttrimB, int vcount0 // number of verts before singular fixups ) { if ( trimA.m_trim_index == trimB.m_trim_index ) return false; if ( trimA.m_trim_index == prevtrimB.m_trim_index ) return false; if ( trimA.m_trim_index == nexttrimB.m_trim_index ) return false; if ( trimB.m_trim_index == prevtrimB.m_trim_index ) return false; if ( trimB.m_trim_index == nexttrimB.m_trim_index ) return false; if ( prevtrimB.m_trim_index == nexttrimB.m_trim_index ) return false; if ( trimA.m_type != ON_BrepTrim::seam ) return false; if ( trimB.m_type != ON_BrepTrim::seam ) return false; if ( trimA.m_ei != trimB.m_ei ) return false; if ( trimA.m_vi[0] != trimB.m_vi[1] && trimA.m_vi[0] < vcount0 && trimB.m_vi[1] < vcount0 ) return false; if ( trimA.m_vi[1] != trimB.m_vi[0] && trimA.m_vi[1] < vcount0 && trimB.m_vi[0] < vcount0 ) return false; if ( prevtrimB.m_vi[1] != trimB.m_vi[0] && prevtrimB.m_vi[1] < vcount0 && trimB.m_vi[0] < vcount0 ) return false; if ( nexttrimB.m_vi[0] != trimB.m_vi[1] && prevtrimB.m_vi[0] < vcount0 && trimB.m_vi[1] < vcount0 ) return false; if ( trimA.m_li != trimB.m_li ) return false; if ( trimA.m_li != prevtrimB.m_li ) return false; if ( trimA.m_li != nexttrimB.m_li ) return false; if ( trimA.m_bRev3d == trimB.m_bRev3d ) return false; const ON_Surface* srf = trimA.SurfaceOf(); if ( 0 == srf ) return false; ON_BrepEdge* edgeA = brep.Edge(trimA.m_ei); if ( 0 == edgeA ) return false; if ( edgeA->m_ti.Count() != 2 ) return false; if ( edgeA->m_ti[0] != trimA.m_trim_index && edgeA->m_ti[1] != trimA.m_trim_index ) return false; if ( edgeA->m_ti[0] != trimB.m_trim_index && edgeA->m_ti[1] != trimB.m_trim_index ) return false; // reserve space now so the vA0 and vA1 pointers // will be valid if m_V[] is grown. brep.m_V.Reserve( brep.m_V.Count()+2 ); ON_BrepVertex* vA0 = brep.Vertex(trimA.m_vi[0]); if ( 0 == vA0 ) return false; ON_BrepVertex* vA1 = brep.Vertex(trimA.m_vi[1]); if ( 0 == vA1 ) return false; // looks like we have a valid seam to blow apart // get a new 3d curve for trimB ON_Curve* cB3 = PushUpIsoTrim( brep, trimB ); if ( 0 == cB3 ) return false; int c3i = brep.AddEdgeCurve(cB3); vA0->m_tolerance = ON_UNSET_VALUE; vA1->m_tolerance = ON_UNSET_VALUE; // make new vertices for trimB ON_BrepVertex* vB0 = 0; ON_BrepVertex* vB1 = 0; ON_3dPoint PA, PB; bool bSame = false; if (brep.GetTrim3dStart(trimB.m_trim_index, PB) && brep.GetTrim3dEnd(trimA.m_trim_index, PA)) bSame = PB.DistanceTo(PA) < ON_ZERO_TOLERANCE; if (bSame || trimB.m_vi[0] != trimA.m_vi[1] ) { // sing fixups have already blown apart this end vB0 = brep.Vertex( trimB.m_vi[0] ); } bSame = false; if (brep.GetTrim3dStart(trimA.m_trim_index, PA) && brep.GetTrim3dEnd(trimB.m_trim_index, PB)) bSame = PB.DistanceTo(PA) < ON_ZERO_TOLERANCE; if (bSame || trimB.m_vi[1] != trimA.m_vi[0] ) { // sing fixups have already blown apart this end vB1 = brep.Vertex( trimB.m_vi[1] ); } if ( 0 == vB0 ) { ON_BrepVertex& v = brep.NewVertex(); vB0 = &v; trimB.m_vi[0] = vB0->m_vertex_index; } if ( 0 == vB1 ) { ON_BrepVertex& v = brep.NewVertex(); vB1 = &v; trimB.m_vi[1] = vB1->m_vertex_index; } // disconnect edgeA and trimB trimB.m_ei = -1; if ( edgeA->m_ti[0] == trimB.m_trim_index ) edgeA->m_ti.Remove(0); else if ( edgeA->m_ti[1] == trimB.m_trim_index ) edgeA->m_ti.Remove(1); ChangeTrimVertex( brep, trimB, 0, vA1->m_vertex_index, vB0->m_vertex_index, true, true ); ChangeTrimVertex( brep, trimB, 1, vA0->m_vertex_index, vB1->m_vertex_index, true, true ); ChangeTrimVertex( brep, prevtrimB, 1, vA1->m_vertex_index, vB0->m_vertex_index, true, true ); ChangeTrimVertex( brep, nexttrimB, 0, vA0->m_vertex_index, vB1->m_vertex_index, true, true ); // make a new edgeB and connect it to trimB ON_BrepEdge& edgeB = brep.NewEdge( *vB0, *vB1, c3i ); edgeA = 0; // pointer may be invalid after m_E[] grows edgeB.m_ti.Append(trimB.m_trim_index); trimB.m_ei = edgeB.m_edge_index; trimB.m_bRev3d = false; trimA.m_type = ON_BrepTrim::boundary; trimB.m_type = ON_BrepTrim::boundary; return true; }
static bool ChangeTrimSingToBdry( ON_Brep& brep, ON_BrepTrim& trim, ON_BrepTrim* nexttrim ) { if ( trim.m_vi[0] != trim.m_vi[1] ) return false; if ( trim.m_type != ON_BrepTrim::singular ) return false; if ( trim.m_ei >= 0 ) return false; const ON_Surface* srf = trim.SurfaceOf(); if ( 0 == srf ) return false; brep.m_V.Reserve( brep.m_V.Count() + 1 ); ON_BrepVertex* v0 = brep.Vertex(trim.m_vi[0]); if ( 0 == v0 ) return false; // get new 3d curve ON_Curve* c3 = PushUpIsoTrim( brep, trim ); if ( 0 == c3 ) return false; // valid singular trim can be changed to non-singular trim // create new vertex for end of this trim v0->m_tolerance = ON_UNSET_VALUE; ON_BrepVertex* v1 = 0; if ( c3->IsClosed() ) { // 3d edge is closed so start and end vertex are still the same. v1 = v0; } else { // new 3d edge is not closed, so the single singular vertex // needs to be "split" into two vertices. brep.NewVertex(); v1 = brep.m_V.Last(); } trim.m_vi[1] = v1->m_vertex_index; // update the start of the next trim to use new vertex if ( nexttrim && nexttrim->m_trim_index != trim.m_trim_index ) { ChangeTrimVertex( brep, *nexttrim, 0, v0->m_vertex_index, v1->m_vertex_index, true, true ); } // make a new edge int ci = brep.AddEdgeCurve(c3); c3 = 0; ON_BrepEdge& edge = brep.NewEdge(*v0,*v1,ci); edge.m_tolerance = 0.0; // hook trim to new edge trim.m_type = ON_BrepTrim::boundary; trim.m_bRev3d = false; trim.m_ei = edge.m_edge_index; edge.m_ti.Append(trim.m_trim_index); return true; }
void subbrep_planar_init(struct subbrep_object_data *data) { if (!data) return; if (data->planar_obj) return; BU_GET(data->planar_obj, struct subbrep_object_data); subbrep_object_init(data->planar_obj, data->brep); bu_vls_sprintf(data->planar_obj->key, "%s", bu_vls_addr(data->key)); data->planar_obj->obj_cnt = data->obj_cnt; (*data->obj_cnt)++; bu_vls_sprintf(data->planar_obj->name_root, "%s_%d", bu_vls_addr(data->name_root), *(data->obj_cnt)); data->planar_obj->type = PLANAR_VOLUME; data->planar_obj->local_brep = ON_Brep::New(); std::map<int, int> face_map; std::map<int, int> surface_map; std::map<int, int> edge_map; std::map<int, int> vertex_map; std::map<int, int> loop_map; std::map<int, int> c3_map; std::map<int, int> c2_map; std::map<int, int> trim_map; std::set<int> faces; std::set<int> fil; std::set<int> loops; std::set<int> skip_verts; std::set<int> skip_edges; std::set<int> keep_verts; std::set<int> partial_edges; std::set<int> isolated_trims; // collect 2D trims whose parent loops aren't fully included here array_to_set(&faces, data->faces, data->faces_cnt); array_to_set(&fil, data->fil, data->fil_cnt); array_to_set(&loops, data->loops, data->loops_cnt); std::map<int, std::set<int> > face_loops; std::map<int, std::set<int> >::iterator fl_it; std::set<int>::iterator l_it; for (int i = 0; i < data->edges_cnt; i++) { int c3i; int new_edge_curve = 0; const ON_BrepEdge *old_edge = &(data->brep->m_E[data->edges[i]]); //std::cout << "old edge: " << old_edge->Vertex(0)->m_vertex_index << "," << old_edge->Vertex(1)->m_vertex_index << "\n"; // See if the vertices from this edge play a role in the planar volume int use_edge = 2; for (int vi = 0; vi < 2; vi++) { int vert_test = -1; int vert_ind = old_edge->Vertex(vi)->m_vertex_index; if (skip_verts.find(vert_ind) != skip_verts.end()) { vert_test = 1; } if (vert_test == -1 && keep_verts.find(vert_ind) != keep_verts.end()) { vert_test = 0; } if (vert_test == -1) { vert_test = characterize_vert(data, old_edge->Vertex(vi)); if (vert_test) { skip_verts.insert(vert_ind); ON_3dPoint vp = old_edge->Vertex(vi)->Point(); bu_log("vert %d (%f %f %f): %d\n", vert_ind, vp.x, vp.y, vp.z, vert_test); } else { keep_verts.insert(vert_ind); } } if (vert_test == 1) { use_edge--; } } if (use_edge == 0) { bu_log("skipping edge %d - both verts are skips\n", old_edge->m_edge_index); skip_edges.insert(old_edge->m_edge_index); continue; } if (use_edge == 1) { bu_log("One of the verts for edge %d is a skip.\n", old_edge->m_edge_index); partial_edges.insert(old_edge->m_edge_index); continue; } // Get the 3D curves from the edges if (c3_map.find(old_edge->EdgeCurveIndexOf()) == c3_map.end()) { ON_Curve *nc = old_edge->EdgeCurveOf()->Duplicate(); ON_Curve *tc = old_edge->EdgeCurveOf()->Duplicate(); if (tc->IsLinear()) { c3i = data->planar_obj->local_brep->AddEdgeCurve(nc); c3_map[old_edge->EdgeCurveIndexOf()] = c3i; } else { ON_Curve *c3 = new ON_LineCurve(old_edge->Vertex(0)->Point(), old_edge->Vertex(1)->Point()); c3i = data->planar_obj->local_brep->AddEdgeCurve(c3); c3_map[old_edge->EdgeCurveIndexOf()] = c3i; new_edge_curve = 1; } } else { c3i = c3_map[old_edge->EdgeCurveIndexOf()]; } // Get the vertices from the edges int v[2]; for (int vi = 0; vi < 2; vi++) { if (vertex_map.find(old_edge->Vertex(vi)->m_vertex_index) == vertex_map.end()) { ON_BrepVertex& newvvi = data->planar_obj->local_brep->NewVertex(old_edge->Vertex(vi)->Point(), old_edge->Vertex(vi)->m_tolerance); v[vi] = newvvi.m_vertex_index; vertex_map[old_edge->Vertex(vi)->m_vertex_index] = v[vi]; } else { v[vi] = vertex_map[old_edge->Vertex(vi)->m_vertex_index]; } } ON_BrepEdge& new_edge = data->planar_obj->local_brep->NewEdge(data->planar_obj->local_brep->m_V[v[0]], data->planar_obj->local_brep->m_V[v[1]], c3i, NULL ,0); edge_map[old_edge->m_edge_index] = new_edge.m_edge_index; // Get the 2D curves from the trims for (int j = 0; j < old_edge->TrimCount(); j++) { ON_BrepTrim *old_trim = old_edge->Trim(j); if (faces.find(old_trim->Face()->m_face_index) != faces.end()) { if (c2_map.find(old_trim->TrimCurveIndexOf()) == c2_map.end()) { ON_Curve *nc = old_trim->TrimCurveOf()->Duplicate(); int c2i = data->planar_obj->local_brep->AddTrimCurve(nc); c2_map[old_trim->TrimCurveIndexOf()] = c2i; //std::cout << "c2i: " << c2i << "\n"; } } } // Get the faces and surfaces from the trims for (int j = 0; j < old_edge->TrimCount(); j++) { ON_BrepTrim *old_trim = old_edge->Trim(j); if (face_map.find(old_trim->Face()->m_face_index) == face_map.end()) { if (faces.find(old_trim->Face()->m_face_index) != faces.end()) { ON_Surface *ns = old_trim->Face()->SurfaceOf()->Duplicate(); ON_Surface *ts = old_trim->Face()->SurfaceOf()->Duplicate(); if (ts->IsPlanar(NULL, BREP_PLANAR_TOL)) { int nsid = data->planar_obj->local_brep->AddSurface(ns); surface_map[old_trim->Face()->SurfaceIndexOf()] = nsid; ON_BrepFace &new_face = data->planar_obj->local_brep->NewFace(nsid); face_map[old_trim->Face()->m_face_index] = new_face.m_face_index; //std::cout << "old face " << old_trim->Face()->m_face_index << " is now " << new_face.m_face_index << "\n"; if (fil.find(old_trim->Face()->m_face_index) != fil.end()) { data->planar_obj->local_brep->FlipFace(new_face); } } } } } // Get the loops from the trims for (int j = 0; j < old_edge->TrimCount(); j++) { ON_BrepTrim *old_trim = old_edge->Trim(j); ON_BrepLoop *old_loop = old_trim->Loop(); if (face_map.find(old_trim->Face()->m_face_index) != face_map.end()) { if (loops.find(old_loop->m_loop_index) != loops.end()) { if (loop_map.find(old_loop->m_loop_index) == loop_map.end()) { face_loops[old_trim->Face()->m_face_index].insert(old_loop->m_loop_index); } } } } } for (fl_it = face_loops.begin(); fl_it != face_loops.end(); fl_it++) { int loop_cnt = fl_it->second.size(); if (loop_cnt == 1) { // If we have only one loop on a face it's an outer loop, // whatever it was in the original brep. const ON_BrepLoop *old_loop = &(data->brep->m_L[*(fl_it->second.begin())]); ON_BrepLoop &nl = data->planar_obj->local_brep->NewLoop(ON_BrepLoop::outer, data->planar_obj->local_brep->m_F[face_map[fl_it->first]]); loop_map[old_loop->m_loop_index] = nl.m_loop_index; } else { bu_log("loop_cnt: %d\n", loop_cnt); // If we ended up with multiple loops, one of them should be an outer loop // and the rest inner loops // Get the outer loop first for (l_it = fl_it->second.begin(); l_it != fl_it->second.end(); l_it++) { const ON_BrepLoop *old_loop = &(data->brep->m_L[*l_it]); if (data->brep->LoopDirection(data->brep->m_L[*l_it]) == 1) { ON_BrepLoop &nl = data->planar_obj->local_brep->NewLoop(ON_BrepLoop::outer, data->planar_obj->local_brep->m_F[face_map[fl_it->first]]); loop_map[old_loop->m_loop_index] = nl.m_loop_index; } } // Now get the inner loops; for (l_it = fl_it->second.begin(); l_it != fl_it->second.end(); l_it++) { const ON_BrepLoop *old_loop = &(data->brep->m_L[*l_it]); if (data->brep->LoopDirection(data->brep->m_L[*l_it]) != 1) { ON_BrepLoop &nl = data->planar_obj->local_brep->NewLoop(ON_BrepLoop::inner, data->planar_obj->local_brep->m_F[face_map[fl_it->first]]); loop_map[old_loop->m_loop_index] = nl.m_loop_index; } } } } // Now, create new trims using the old loop definitions and the maps std::map<int, int>::iterator loop_it; std::set<int> evaluated; for (loop_it = loop_map.begin(); loop_it != loop_map.end(); loop_it++) { const ON_BrepLoop *old_loop = &(data->brep->m_L[(*loop_it).first]); ON_BrepLoop &new_loop = data->planar_obj->local_brep->m_L[(*loop_it).second]; for (int j = 0; j < old_loop->TrimCount(); j++) { const ON_BrepTrim *old_trim = old_loop->Trim(j); ON_BrepEdge *o_edge = old_trim->Edge(); if (!o_edge) { /* If we didn't have an edge originally, we need to add the 2d curve here */ if (c2_map.find(old_trim->TrimCurveIndexOf()) == c2_map.end()) { ON_Curve *nc = old_trim->TrimCurveOf()->Duplicate(); int c2i = data->planar_obj->local_brep->AddTrimCurve(nc); c2_map[old_trim->TrimCurveIndexOf()] = c2i; } if (vertex_map.find(old_trim->Vertex(0)->m_vertex_index) == vertex_map.end()) { ON_BrepVertex& newvs = data->planar_obj->local_brep->NewVertex(old_trim->Vertex(0)->Point(), old_trim->Vertex(0)->m_tolerance); vertex_map[old_trim->Vertex(0)->m_vertex_index] = newvs.m_vertex_index; ON_BrepTrim &nt = data->planar_obj->local_brep->NewSingularTrim(newvs, new_loop, old_trim->m_iso, c2_map[old_trim->TrimCurveIndexOf()]); nt.m_tolerance[0] = old_trim->m_tolerance[0]; nt.m_tolerance[1] = old_trim->m_tolerance[1]; } else { ON_BrepTrim &nt = data->planar_obj->local_brep->NewSingularTrim(data->planar_obj->local_brep->m_V[vertex_map[old_trim->Vertex(0)->m_vertex_index]], new_loop, old_trim->m_iso, c2_map[old_trim->TrimCurveIndexOf()]); nt.m_tolerance[0] = old_trim->m_tolerance[0]; nt.m_tolerance[1] = old_trim->m_tolerance[1]; } continue; } if (evaluated.find(o_edge->m_edge_index) != evaluated.end()) { bu_log("edge %d already handled, continuing...\n", o_edge->m_edge_index); continue; } // Don't use a trim connected to an edge we are skipping if (skip_edges.find(o_edge->m_edge_index) != skip_edges.end()) { bu_log("edge %d is skipped, continuing...\n", o_edge->m_edge_index); evaluated.insert(o_edge->m_edge_index); continue; } int is_partial = 0; if (partial_edges.find(o_edge->m_edge_index) != partial_edges.end()) is_partial = 1; if (!is_partial) { ON_BrepEdge &n_edge = data->planar_obj->local_brep->m_E[edge_map[o_edge->m_edge_index]]; ON_Curve *ec = o_edge->EdgeCurveOf()->Duplicate(); if (ec->IsLinear()) { ON_BrepTrim &nt = data->planar_obj->local_brep->NewTrim(n_edge, old_trim->m_bRev3d, new_loop, c2_map[old_trim->TrimCurveIndexOf()]); nt.m_tolerance[0] = old_trim->m_tolerance[0]; nt.m_tolerance[1] = old_trim->m_tolerance[1]; nt.m_iso = old_trim->m_iso; } else { // Wasn't linear, but wasn't partial either - replace with a line ON_Curve *c2_orig = old_trim->TrimCurveOf()->Duplicate(); ON_3dPoint p1 = c2_orig->PointAt(c2_orig->Domain().Min()); ON_3dPoint p2 = c2_orig->PointAt(c2_orig->Domain().Max()); ON_Curve *c2 = new ON_LineCurve(p1, p2); c2->ChangeDimension(2); int c2i = data->planar_obj->local_brep->AddTrimCurve(c2); ON_BrepTrim &nt = data->planar_obj->local_brep->NewTrim(n_edge, old_trim->m_bRev3d, new_loop, c2i); nt.m_tolerance[0] = old_trim->m_tolerance[0]; nt.m_tolerance[1] = old_trim->m_tolerance[1]; nt.m_iso = old_trim->m_iso; delete c2_orig; } delete ec; } else { // Partial edge - let the fun begin ON_3dPoint p1, p2; ON_BrepEdge *next_edge; bu_log("working a partial edge: %d\n", o_edge->m_edge_index); int v[2]; v[0] = o_edge->Vertex(0)->m_vertex_index; v[1] = o_edge->Vertex(1)->m_vertex_index; // figure out which trim point we can use, the min or max int pos1 = 0; if (skip_verts.find(v[0]) != skip_verts.end()) { pos1 = 1; } int j_next = j; ON_Curve *c2_orig = old_trim->TrimCurveOf()->Duplicate(); ON_Curve *c2_next = NULL; int walk_dir = 1; // bump the loop iterator to get passed any skipped edges to // the next partial while (!c2_next) { (walk_dir == 1) ? j_next++ : j_next--; if (j_next == old_loop->TrimCount()) { j_next = 0; } if (j_next == -1) { j_next = old_loop->TrimCount() - 1; } const ON_BrepTrim *next_trim = old_loop->Trim(j_next); next_edge = next_trim->Edge(); if (!next_edge) continue; if (skip_edges.find(next_edge->m_edge_index) == skip_edges.end()) { if (partial_edges.find(next_edge->m_edge_index) != partial_edges.end()) { bu_log("found next partial edge %d\n", next_edge->m_edge_index); evaluated.insert(next_edge->m_edge_index); c2_next = next_trim->TrimCurveOf()->Duplicate(); } else { bu_log("partial edge %d followed by non-partial %d, need to go the other way\n", o_edge->m_edge_index, next_edge->m_edge_index); j_next--; walk_dir = -1; } } else { bu_log("skipping fully ignored edge %d\n", next_edge->m_edge_index); evaluated.insert(next_edge->m_edge_index); } } int v2[2]; v2[0] = next_edge->Vertex(0)->m_vertex_index; v2[1] = next_edge->Vertex(1)->m_vertex_index; // figure out which trim point we can use, the min or max int pos2 = 0; if (skip_verts.find(v2[0]) != skip_verts.end()) { pos2 = 1; } int vmapped[2]; if (vertex_map.find(o_edge->Vertex(pos1)->m_vertex_index) == vertex_map.end()) { ON_BrepVertex& newvvi = data->planar_obj->local_brep->NewVertex(o_edge->Vertex(pos1)->Point(), o_edge->Vertex(pos1)->m_tolerance); vertex_map[o_edge->Vertex(pos1)->m_vertex_index] = newvvi.m_vertex_index; } if (vertex_map.find(next_edge->Vertex(pos2)->m_vertex_index) == vertex_map.end()) { ON_BrepVertex& newvvi = data->planar_obj->local_brep->NewVertex(next_edge->Vertex(pos2)->Point(), next_edge->Vertex(pos2)->m_tolerance); vertex_map[next_edge->Vertex(pos2)->m_vertex_index] = newvvi.m_vertex_index; } // If walk_dir is -1, need to flip things around (I think...) the verts and trim points // will be swapped compared to a forward walk if (walk_dir == -1) { vmapped[1] = vertex_map[o_edge->Vertex(pos1)->m_vertex_index]; vmapped[0] = vertex_map[next_edge->Vertex(pos2)->m_vertex_index]; } else { vmapped[0] = vertex_map[o_edge->Vertex(pos1)->m_vertex_index]; vmapped[1] = vertex_map[next_edge->Vertex(pos2)->m_vertex_index]; } // New Edge curve ON_Curve *c3 = new ON_LineCurve(o_edge->Vertex(pos1)->Point(), next_edge->Vertex(pos2)->Point()); int c3i = data->planar_obj->local_brep->AddEdgeCurve(c3); ON_BrepEdge& new_edge = data->planar_obj->local_brep->NewEdge(data->planar_obj->local_brep->m_V[vmapped[0]], data->planar_obj->local_brep->m_V[vmapped[1]], c3i, NULL ,0); // Again, flip if walk_dir is -1 if (walk_dir == -1) { p2 = c2_orig->PointAt(c2_orig->Domain().Min()); p1 = c2_next->PointAt(c2_orig->Domain().Max()); } else { p1 = c2_orig->PointAt(c2_orig->Domain().Min()); p2 = c2_next->PointAt(c2_orig->Domain().Max()); } std::cout << "p1: " << pout(p1) << "\n"; std::cout << "p2: " << pout(p2) << "\n"; ON_Curve *c2 = new ON_LineCurve(p1, p2); c2->ChangeDimension(2); int c2i = data->planar_obj->local_brep->AddTrimCurve(c2); ON_BrepTrim &nt = data->planar_obj->local_brep->NewTrim(new_edge, false, new_loop, c2i); nt.m_tolerance[0] = old_trim->m_tolerance[0]; nt.m_tolerance[1] = old_trim->m_tolerance[1]; nt.m_iso = old_trim->m_iso; delete c2_orig; delete c2_next; } } } // If there is a possibility of a negative volume for the planar solid, do a test. // The only way to get a negative planar solid in this context is if that solid is // "inside" a non-planar shape (it would be "part of" the parent shape if it were // planar and it would be a separate shape altogether if it were not topologically // connected. So we take one partial edge, find its associated non-planar faces, // and collect all the partial and skipped edges from that face and any non-planar // faces associated with the other partial/skipped edges. // // TODO - We still have an unhandled possibility here - the self-intersecting // planar_obj. For example: // // * * // * * * * // * * * * * * // * * * * * * * * // * * * * * * // * * * * * * * * * * * * // if (partial_edges.size() > 0) { std::queue<int> connected_faces; std::set<int> relevant_edges; std::set<int>::iterator re_it; std::set<int> efaces; std::set<int>::iterator f_it; std::set<int> found_faces; const ON_BrepEdge *seed_edge = &(data->brep->m_E[*partial_edges.begin()]); for (int j = 0; j < seed_edge->TrimCount(); j++) { ON_BrepTrim *trim = seed_edge->Trim(j); efaces.insert(trim->Face()->m_face_index); } for(f_it = efaces.begin(); f_it != efaces.end(); f_it++) { surface_t stype = GetSurfaceType(data->brep->m_F[*f_it].SurfaceOf(), NULL); if (stype != SURFACE_PLANE) { connected_faces.push(data->brep->m_F[*f_it].m_face_index); } } while (!connected_faces.empty()) { int face_index = connected_faces.front(); connected_faces.pop(); std::set<int> local_edges; std::set<int>::iterator le_it; found_faces.insert(face_index); const ON_BrepFace *face = &(data->brep->m_F[face_index]); const ON_BrepLoop *loop = NULL; // Find the loop in this face that is associated with this subbrep for (int i = 0; i < face->LoopCount(); i++) { int loop_ind = face->Loop(i)->m_loop_index; if (loops.find(loop_ind) != loops.end()) { loop = &(data->brep->m_L[loop_ind]); break; } } // Collect the edges that are partial or skipped for (int i = 0; i < loop->TrimCount(); i++) { const ON_BrepTrim *trim = loop->Trim(i); ON_BrepEdge *edge = trim->Edge(); if (edge) { if (partial_edges.find(edge->m_edge_index) != partial_edges.end()) { relevant_edges.insert(edge->m_edge_index); local_edges.insert(edge->m_edge_index); } if (skip_edges.find(edge->m_edge_index) != skip_edges.end()) { relevant_edges.insert(edge->m_edge_index); local_edges.insert(edge->m_edge_index); } } } // For each collected partial/skipped edge, add any faces not already // found to the queue. for (le_it = local_edges.begin(); le_it != local_edges.end(); le_it++) { const ON_BrepEdge *edge = &(data->brep->m_E[*le_it]); for (int j = 0; j < edge->TrimCount(); j++) { ON_BrepTrim *trim = edge->Trim(j); if (found_faces.find(trim->Face()->m_face_index) == found_faces.end()) { found_faces.insert(trim->Face()->m_face_index); connected_faces.push(trim->Face()->m_face_index); } } } } // Build two bounding boxes - one with the new verts in planar_obj, and the other with // the edges found above. ON_BoundingBox pbb, ebb; ON_MinMaxInit(&pbb.m_min, &pbb.m_max); ON_MinMaxInit(&ebb.m_min, &ebb.m_max); for (int i = 0; i < data->planar_obj->local_brep->m_V.Count(); i++) { const ON_BrepVertex *v = &(data->planar_obj->local_brep->m_V[i]); pbb.Set(v->Point(), true); } for (re_it = relevant_edges.begin(); re_it != relevant_edges.end(); re_it++) { const ON_BrepEdge *e = &(data->brep->m_E[*re_it]); ON_BoundingBox cbb = e->EdgeCurveOf()->BoundingBox(); ebb.Set(cbb.m_min, true); ebb.Set(cbb.m_max, true); } //std::cout << "in pbb.s rpp " << pout(pbb.m_min) << " " << pout(pbb.m_max) << "\n"; //std::cout << "in ebb.s rpp " << pout(ebb.m_min) << " " << pout(ebb.m_max) << "\n"; if (ebb.Includes(pbb)) { bu_log("negative volume\n"); data->planar_obj->negative_shape = -1; } else { bu_log("positive volume\n"); data->planar_obj->negative_shape = 1; } data->planar_obj->params->bool_op = (data->planar_obj->negative_shape == -1) ? '-' : 'u'; } // Need to preserve the vertex map for this, since we're not done building up the brep map_to_array(&(data->planar_obj->planar_obj_vert_map), &(data->planar_obj->planar_obj_vert_cnt), &vertex_map); data->planar_obj->local_brep->SetTrimTypeFlags(true); }
// Criteria: // // 1. A linear edge associated with a planar face == 0 // 2. All linear edges associated with non-planar faces are part // of the same CSG shape AND all non-linear edges' non-planar faces // are also part of that same CSG shape = 1 // 3. If not 2, 0 int characterize_vert(struct subbrep_object_data *data, const ON_BrepVertex *v) { std::set<int> non_planar_faces; std::set<int>::iterator f_it; std::set<struct filter_obj *> fobjs; std::set<struct filter_obj *>::iterator fo_it; struct filter_obj *control = NULL; for (int i = 0; i < v->m_ei.Count(); i++) { std::set<int> efaces; const ON_BrepEdge *edge = &(data->brep->m_E[v->m_ei[i]]); ON_Curve *tc = edge->EdgeCurveOf()->Duplicate(); int is_linear = tc->IsLinear(); delete tc; // Get the faces associated with the edge for (int j = 0; j < edge->TrimCount(); j++) { ON_BrepTrim *trim = edge->Trim(j); efaces.insert(trim->Face()->m_face_index); } for(f_it = efaces.begin(); f_it != efaces.end(); f_it++) { struct filter_obj *new_obj; BU_GET(new_obj, struct filter_obj); surface_t stype = GetSurfaceType(data->brep->m_F[*f_it].SurfaceOf(), new_obj); if (stype == SURFACE_PLANE) { filter_obj_free(new_obj); BU_PUT(new_obj, struct filter_obj); if (is_linear) { for (fo_it = fobjs.begin(); fo_it != fobjs.end(); fo_it++) { struct filter_obj *obj = (struct filter_obj *)(*fo_it); filter_obj_free(obj); BU_PUT(obj, struct filter_obj); } return 0; } } else { if (!control) { control = new_obj; } else { fobjs.insert(new_obj); } } } } // Can this happen? if (fobjs.size() == 0) { if (control) { filter_obj_free(control); BU_PUT(control, struct filter_obj); } return 0; } int equal = 1; for(fo_it = fobjs.begin(); fo_it != fobjs.end(); fo_it++) { if (equal && !filter_objs_equal(*fo_it, control)) equal = 0; struct filter_obj *obj = (struct filter_obj *)(*fo_it); filter_obj_free(obj); BU_PUT(obj, struct filter_obj); } filter_obj_free(control); BU_PUT(control, struct filter_obj); return equal; }