//! project a single face using HLR - used for section faces TopoDS_Face DrawViewSection::projectFace(const TopoDS_Shape &face, gp_Pnt faceCenter, const Base::Vector3d &direction) { if(face.IsNull()) { throw Base::Exception("DrawViewSection::projectFace - input Face is NULL"); } Base::Vector3d origin(faceCenter.X(),faceCenter.Y(),faceCenter.Z()); gp_Ax2 viewAxis = TechDrawGeometry::getViewAxis(origin,direction); HLRBRep_Algo *brep_hlr = new HLRBRep_Algo(); brep_hlr->Add(face); HLRAlgo_Projector projector( viewAxis ); brep_hlr->Projector(projector); brep_hlr->Update(); brep_hlr->Hide(); HLRBRep_HLRToShape hlrToShape(brep_hlr); TopoDS_Shape hardEdges = hlrToShape.VCompound(); // TopoDS_Shape outEdges = hlrToShape.OutLineVCompound(); std::vector<TopoDS_Edge> faceEdges; TopExp_Explorer expl(hardEdges, TopAbs_EDGE); int i; for (i = 1 ; expl.More(); expl.Next(),i++) { const TopoDS_Edge& edge = TopoDS::Edge(expl.Current()); if (edge.IsNull()) { Base::Console().Log("INFO - DVS::projectFace - hard edge: %d is NULL\n",i); continue; } faceEdges.push_back(edge); } //TODO: verify that outline edges aren't required //if edge is both hard & outline, it will be duplicated? are hard edges enough? // TopExp_Explorer expl2(outEdges, TopAbs_EDGE); // for (i = 1 ; expl2.More(); expl2.Next(),i++) { // const TopoDS_Edge& edge = TopoDS::Edge(expl2.Current()); // if (edge.IsNull()) { // Base::Console().Log("INFO - GO::projectFace - outline edge: %d is NULL\n",i); // continue; // } // bool addEdge = true; // //is edge already in faceEdges? maybe need to use explorer for this for IsSame to work? // for (auto& e:faceEdges) { // if (e.IsPartner(edge)) { // addEdge = false; // Base::Console().Message("TRACE - DVS::projectFace - skipping an edge 1\n"); // } // } // expl.ReInit(); // for (; expl.More(); expl.Next()){ // const TopoDS_Edge& eHard = TopoDS::Edge(expl.Current()); // if (eHard.IsPartner(edge)) { // addEdge = false; // Base::Console().Message("TRACE - DVS::projectFace - skipping an edge 2\n"); // } // } // if (addEdge) { // faceEdges.push_back(edge); // } // } TopoDS_Face projectedFace; if (faceEdges.empty()) { Base::Console().Log("LOG - DVS::projectFace - no faceEdges\n"); return projectedFace; } //recreate the wires for this single face EdgeWalker ew; ew.loadEdges(faceEdges); bool success = ew.perform(); if (success) { std::vector<TopoDS_Wire> fw = ew.getResultNoDups(); if (!fw.empty()) { std::vector<TopoDS_Wire> sortedWires = ew.sortStrip(fw, true); if (sortedWires.empty()) { return projectedFace; } BRepBuilderAPI_MakeFace mkFace(sortedWires.front(),true); //true => only want planes? std::vector<TopoDS_Wire>::iterator itWire = ++sortedWires.begin(); //starting with second face for (; itWire != sortedWires.end(); itWire++) { mkFace.Add(*itWire); } projectedFace = mkFace.Face(); } } else { Base::Console().Warning("DVS::projectFace - input is not planar graph. No face detection\n"); } return projectedFace; }
//! make faces from the existing edge geometry void DrawViewPart::extractFaces() { geometryObject->clearFaceGeom(); const std::vector<TechDrawGeometry::BaseGeom*>& goEdges = geometryObject->getVisibleFaceEdges(SmoothVisible.getValue(),SeamVisible.getValue()); std::vector<TechDrawGeometry::BaseGeom*>::const_iterator itEdge = goEdges.begin(); std::vector<TopoDS_Edge> origEdges; for (;itEdge != goEdges.end(); itEdge++) { origEdges.push_back((*itEdge)->occEdge); } std::vector<TopoDS_Edge> faceEdges; std::vector<TopoDS_Edge> nonZero; for (auto& e:origEdges) { //drop any zero edges (shouldn't be any by now!!!) if (!DrawUtil::isZeroEdge(e)) { nonZero.push_back(e); } else { Base::Console().Message("INFO - DVP::extractFaces for %s found ZeroEdge!\n",getNameInDocument()); } } faceEdges = nonZero; origEdges = nonZero; //HLR algo does not provide all edge intersections for edge endpoints. //need to split long edges touched by Vertex of another edge std::vector<splitPoint> splits; std::vector<TopoDS_Edge>::iterator itOuter = origEdges.begin(); int iOuter = 0; for (; itOuter != origEdges.end(); ++itOuter, iOuter++) { TopoDS_Vertex v1 = TopExp::FirstVertex((*itOuter)); TopoDS_Vertex v2 = TopExp::LastVertex((*itOuter)); Bnd_Box sOuter; BRepBndLib::Add(*itOuter, sOuter); sOuter.SetGap(0.1); if (sOuter.IsVoid()) { Base::Console().Message("DVP::Extract Faces - outer Bnd_Box is void for %s\n",getNameInDocument()); continue; } if (DrawUtil::isZeroEdge(*itOuter)) { Base::Console().Message("DVP::extractFaces - outerEdge: %d is ZeroEdge\n",iOuter); //this is not finding ZeroEdges continue; //skip zero length edges. shouldn't happen ;) } int iInner = 0; std::vector<TopoDS_Edge>::iterator itInner = faceEdges.begin(); for (; itInner != faceEdges.end(); ++itInner,iInner++) { if (iInner == iOuter) { continue; } if (DrawUtil::isZeroEdge((*itInner))) { continue; //skip zero length edges. shouldn't happen ;) } Bnd_Box sInner; BRepBndLib::Add(*itInner, sInner); sInner.SetGap(0.1); if (sInner.IsVoid()) { Base::Console().Log("INFO - DVP::Extract Faces - inner Bnd_Box is void for %s\n",getNameInDocument()); continue; } if (sOuter.IsOut(sInner)) { //bboxes of edges don't intersect, don't bother continue; } double param = -1; if (DrawProjectSplit::isOnEdge((*itInner),v1,param,false)) { gp_Pnt pnt1 = BRep_Tool::Pnt(v1); splitPoint s1; s1.i = iInner; s1.v = Base::Vector3d(pnt1.X(),pnt1.Y(),pnt1.Z()); s1.param = param; splits.push_back(s1); } if (DrawProjectSplit::isOnEdge((*itInner),v2,param,false)) { gp_Pnt pnt2 = BRep_Tool::Pnt(v2); splitPoint s2; s2.i = iInner; s2.v = Base::Vector3d(pnt2.X(),pnt2.Y(),pnt2.Z()); s2.param = param; splits.push_back(s2); } } //inner loop } //outer loop std::vector<splitPoint> sorted = DrawProjectSplit::sortSplits(splits,true); auto last = std::unique(sorted.begin(), sorted.end(), DrawProjectSplit::splitEqual); //duplicates to back sorted.erase(last, sorted.end()); //remove dupl splits std::vector<TopoDS_Edge> newEdges = DrawProjectSplit::splitEdges(faceEdges,sorted); if (newEdges.empty()) { Base::Console().Log("LOG - DVP::extractFaces - no newEdges\n"); return; } newEdges = DrawProjectSplit::removeDuplicateEdges(newEdges); //find all the wires in the pile of faceEdges EdgeWalker ew; ew.loadEdges(newEdges); bool success = ew.perform(); if (!success) { Base::Console().Warning("DVP::extractFaces - input is not planar graph. No face detection\n"); return; } std::vector<TopoDS_Wire> fw = ew.getResultNoDups(); std::vector<TopoDS_Wire> sortedWires = ew.sortStrip(fw,true); std::vector<TopoDS_Wire>::iterator itWire = sortedWires.begin(); for (; itWire != sortedWires.end(); itWire++) { //version 1: 1 wire/face - no voids in face TechDrawGeometry::Face* f = new TechDrawGeometry::Face(); const TopoDS_Wire& wire = (*itWire); TechDrawGeometry::Wire* w = new TechDrawGeometry::Wire(wire); f->wires.push_back(w); geometryObject->addFaceGeom(f); } }