void ResultEntry::buildEntryName() { ResultEntry *parentEntry = this; while(parentEntry->parent != 0) { ResultEntry *temp = parentEntry->parent; if (temp->parent == 0) break; parentEntry = parentEntry->parent; } QString stringOut; QTextStream stream(&stringOut); TopTools_IndexedMapOfShape shapeMap; int index(-1); switch (this->shape.ShapeType()) { case TopAbs_COMPOUND: TopExp::MapShapes(parentEntry->shape, TopAbs_COMPOUND, shapeMap); stream << "Compound"; break; case TopAbs_COMPSOLID: TopExp::MapShapes(parentEntry->shape, TopAbs_COMPSOLID, shapeMap); stream << "CompSolid"; break; case TopAbs_SOLID: TopExp::MapShapes(parentEntry->shape, TopAbs_SOLID, shapeMap); stream << "Solid"; break; case TopAbs_SHELL: TopExp::MapShapes(parentEntry->shape, TopAbs_SHELL, shapeMap); stream << "Shell"; break; case TopAbs_WIRE: TopExp::MapShapes(parentEntry->shape, TopAbs_WIRE, shapeMap); stream << "Wire"; break; case TopAbs_FACE: TopExp::MapShapes(parentEntry->shape, TopAbs_FACE, shapeMap); stream << "Face"; break; case TopAbs_EDGE: TopExp::MapShapes(parentEntry->shape, TopAbs_EDGE, shapeMap); stream << "Edge"; break; case TopAbs_VERTEX: TopExp::MapShapes(parentEntry->shape, TopAbs_VERTEX, shapeMap); stream << "Vertex"; break; default: stream << "Unexpected shape type"; break; } index = shapeMap.FindIndex(this->shape); stream << index; this->name = stringOut; }
void DlgFilletEdges::on_shapeObject_activated(int index) { d->object = 0; QStandardItemModel *model = qobject_cast<QStandardItemModel*>(ui->treeView->model()); model->removeRows(0, model->rowCount()); QByteArray name = ui->shapeObject->itemData(index).toByteArray(); App::Document* doc = App::GetApplication().getActiveDocument(); if (!doc) return; App::DocumentObject* part = doc->getObject((const char*)name); if (part && part->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { d->object = part; TopoDS_Shape myShape = static_cast<Part::Feature*>(part)->Shape.getValue(); // build up map edge->face TopTools_IndexedDataMapOfShapeListOfShape edge2Face; TopExp::MapShapesAndAncestors(myShape, TopAbs_EDGE, TopAbs_FACE, edge2Face); TopTools_IndexedMapOfShape mapOfShape; TopExp::MapShapes(myShape, TopAbs_EDGE, mapOfShape); // populate the model d->edge_ids.clear(); for (int i=1; i<= edge2Face.Extent(); ++i) { // set the index value as user data to use it in accept() const TopTools_ListOfShape& los = edge2Face.FindFromIndex(i); if (los.Extent() == 2) { // set the index value as user data to use it in accept() const TopoDS_Shape& edge = edge2Face.FindKey(i); // Now check also the continuity to only allow C0-continious // faces const TopoDS_Shape& face1 = los.First(); const TopoDS_Shape& face2 = los.Last(); GeomAbs_Shape cont = BRep_Tool::Continuity(TopoDS::Edge(edge), TopoDS::Face(face1), TopoDS::Face(face2)); if (cont == GeomAbs_C0) { int id = mapOfShape.FindIndex(edge); d->edge_ids.push_back(id); } } } model->insertRows(0, d->edge_ids.size()); int index = 0; for (std::vector<int>::iterator it = d->edge_ids.begin(); it != d->edge_ids.end(); ++it) { model->setData(model->index(index, 0), QVariant(tr("Edge%1").arg(*it))); model->setData(model->index(index, 0), QVariant(*it), Qt::UserRole); model->setData(model->index(index, 1), QVariant(QLocale::system().toString(1.0,'f',2))); model->setData(model->index(index, 2), QVariant(QLocale::system().toString(1.0,'f',2))); std::stringstream element; element << "Edge" << *it; if (Gui::Selection().isSelected(part, element.str().c_str())) model->setData(model->index(index, 0), Qt::Checked, Qt::CheckStateRole); else model->setData(model->index(index, 0), Qt::Unchecked, Qt::CheckStateRole); index++; } } }
QString PartGui::buildSelectionName(const ResultEntry *entry, const TopoDS_Shape &shape) { const ResultEntry *parentEntry = entry; while(parentEntry->parent != 0) { ResultEntry *temp = parentEntry->parent; if (temp->parent == 0) break; parentEntry = parentEntry->parent; } QString stringOut; QTextStream stream(&stringOut); stream << parentEntry->name; stream << '.'; TopTools_IndexedMapOfShape shapeMap; int index(-1); switch (shape.ShapeType()) { case TopAbs_FACE: TopExp::MapShapes(parentEntry->shape, TopAbs_FACE, shapeMap); stream << "Face"; break; case TopAbs_EDGE: TopExp::MapShapes(parentEntry->shape, TopAbs_EDGE, shapeMap); stream << "Edge"; break; case TopAbs_VERTEX: TopExp::MapShapes(parentEntry->shape, TopAbs_VERTEX, shapeMap); stream << "Vertex"; break; default: stream << "Unexpected shape type"; break; } index = shapeMap.FindIndex(shape); stream << index; return stringOut; }
QString SetupResultBase::selectionName(ResultEntry *entry, const TopoDS_Shape &shape) { ResultEntry *parentEntry = entry; while(parentEntry->name.isEmpty()) parentEntry = parentEntry->parent; QString stringOut; QTextStream stream(&stringOut); stream << parentEntry->name; stream << '.'; TopTools_IndexedMapOfShape shapeMap; int index(-1); switch (shape.ShapeType()) { case TopAbs_FACE: TopExp::MapShapes(parentEntry->shape, TopAbs_FACE, shapeMap); stream << "Face"; break; case TopAbs_EDGE: TopExp::MapShapes(parentEntry->shape, TopAbs_EDGE, shapeMap); stream << "Edge"; break; case TopAbs_VERTEX: TopExp::MapShapes(parentEntry->shape, TopAbs_VERTEX, shapeMap); stream << "Vertex"; break; default: stream << "Unexpected shape type"; break; } index = shapeMap.FindIndex(shape); stream << index; return stringOut; }
App::DocumentObjectExecReturn *MultiFuse::execute(void) { std::vector<TopoDS_Shape> s; std::vector<App::DocumentObject*> obj = Shapes.getValues(); std::vector<App::DocumentObject*>::iterator it; for (it = obj.begin(); it != obj.end(); ++it) { if ((*it)->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId())) { s.push_back(static_cast<Part::Feature*>(*it)->Shape.getValue()); } } bool argumentsAreInCompound = false; TopoDS_Shape compoundOfArguments; //if only one source shape, and it is a compound - fuse children of the compound if (s.size() == 1){ compoundOfArguments = s[0]; if (compoundOfArguments.ShapeType() == TopAbs_COMPOUND){ s.clear(); TopoDS_Iterator it(compoundOfArguments); for (; it.More(); it.Next()) { const TopoDS_Shape& aChild = it.Value(); s.push_back(aChild); } argumentsAreInCompound = true; } } if (s.size() >= 2) { try { std::vector<ShapeHistory> history; #if OCC_VERSION_HEX <= 0x060800 TopoDS_Shape resShape = s.front(); if (resShape.IsNull()) throw Base::Exception("Input shape is null"); for (std::vector<TopoDS_Shape>::iterator it = s.begin()+1; it != s.end(); ++it) { if (it->IsNull()) throw Base::Exception("Input shape is null"); // Let's call algorithm computing a fuse operation: BRepAlgoAPI_Fuse mkFuse(resShape, *it); // Let's check if the fusion has been successful if (!mkFuse.IsDone()) throw Base::Exception("Fusion failed"); resShape = mkFuse.Shape(); ShapeHistory hist1 = buildHistory(mkFuse, TopAbs_FACE, resShape, mkFuse.Shape1()); ShapeHistory hist2 = buildHistory(mkFuse, TopAbs_FACE, resShape, mkFuse.Shape2()); if (history.empty()) { history.push_back(hist1); history.push_back(hist2); } else { for (std::vector<ShapeHistory>::iterator jt = history.begin(); jt != history.end(); ++jt) *jt = joinHistory(*jt, hist1); history.push_back(hist2); } } #else BRepAlgoAPI_Fuse mkFuse; TopTools_ListOfShape shapeArguments,shapeTools; shapeArguments.Append(s.front()); for (std::vector<TopoDS_Shape>::iterator it = s.begin()+1; it != s.end(); ++it) { if (it->IsNull()) throw Base::Exception("Input shape is null"); shapeTools.Append(*it); } mkFuse.SetArguments(shapeArguments); mkFuse.SetTools(shapeTools); mkFuse.Build(); if (!mkFuse.IsDone()) throw Base::Exception("MultiFusion failed"); TopoDS_Shape resShape = mkFuse.Shape(); for (std::vector<TopoDS_Shape>::iterator it = s.begin(); it != s.end(); ++it) { history.push_back(buildHistory(mkFuse, TopAbs_FACE, resShape, *it)); } #endif if (resShape.IsNull()) throw Base::Exception("Resulting shape is null"); Base::Reference<ParameterGrp> hGrp = App::GetApplication().GetUserParameter() .GetGroup("BaseApp")->GetGroup("Preferences")->GetGroup("Mod/Part/Boolean"); if (hGrp->GetBool("CheckModel", false)) { BRepCheck_Analyzer aChecker(resShape); if (! aChecker.IsValid() ) { return new App::DocumentObjectExecReturn("Resulting shape is invalid"); } } if (hGrp->GetBool("RefineModel", false)) { try { TopoDS_Shape oldShape = resShape; BRepBuilderAPI_RefineModel mkRefine(oldShape); resShape = mkRefine.Shape(); ShapeHistory hist = buildHistory(mkRefine, TopAbs_FACE, resShape, oldShape); for (std::vector<ShapeHistory>::iterator jt = history.begin(); jt != history.end(); ++jt) *jt = joinHistory(*jt, hist); } catch (Standard_Failure) { // do nothing } } this->Shape.setValue(resShape); if (argumentsAreInCompound){ //combine histories of every child of source compound into one ShapeHistory overallHist; TopTools_IndexedMapOfShape facesOfCompound; TopAbs_ShapeEnum type = TopAbs_FACE; TopExp::MapShapes(compoundOfArguments, type, facesOfCompound); for (std::size_t iChild = 0; iChild < history.size(); iChild++){ //loop over children of source compound //for each face of a child, find the inex of the face in compound, and assign the corresponding right-hand-size of the history TopTools_IndexedMapOfShape facesOfChild; TopExp::MapShapes(s[iChild], type, facesOfChild); for(std::pair<const int,ShapeHistory::List> &histitem: history[iChild].shapeMap){ //loop over elements of history - that is - over faces of the child of source compound int iFaceInChild = histitem.first; ShapeHistory::List &iFacesInResult = histitem.second; TopoDS_Shape srcFace = facesOfChild(iFaceInChild + 1); //+1 to convert our 0-based to OCC 1-bsed conventions int iFaceInCompound = facesOfCompound.FindIndex(srcFace)-1; overallHist.shapeMap[iFaceInCompound] = iFacesInResult; //this may overwrite existing info if the same face is used in several children of compound. This shouldn't be a problem, because the histories should match anyway... } } history.clear(); history.push_back(overallHist); } this->History.setValues(history); } catch (Standard_Failure& e) { return new App::DocumentObjectExecReturn(e.GetMessageString()); } } else { throw Base::Exception("Not enough shape objects linked"); } return App::DocumentObject::StdReturn; }
void NETGENPlugin_Mesher::PrepareOCCgeometry(netgen::OCCGeometry& occgeo, const TopoDS_Shape& shape, SMESH_Mesh& mesh, list< SMESH_subMesh* > * meshedSM) { BRepTools::Clean (shape); try { #if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100 OCC_CATCH_SIGNALS; #endif BRepMesh_IncrementalMesh::BRepMesh_IncrementalMesh (shape, 0.01, true); } catch (Standard_Failure) { } Bnd_Box bb; BRepBndLib::Add (shape, bb); double x1,y1,z1,x2,y2,z2; bb.Get (x1,y1,z1,x2,y2,z2); MESSAGE("shape bounding box:\n" << "(" << x1 << " " << y1 << " " << z1 << ") " << "(" << x2 << " " << y2 << " " << z2 << ")"); netgen::Point<3> p1 = netgen::Point<3> (x1,y1,z1); netgen::Point<3> p2 = netgen::Point<3> (x2,y2,z2); occgeo.boundingbox = netgen::Box<3> (p1,p2); occgeo.shape = shape; occgeo.changed = 1; //occgeo.BuildFMap(); // fill maps of shapes of occgeo with not yet meshed subshapes // get root submeshes list< SMESH_subMesh* > rootSM; if ( SMESH_subMesh* sm = mesh.GetSubMeshContaining( shape )) { rootSM.push_back( sm ); } else { for ( TopoDS_Iterator it( shape ); it.More(); it.Next() ) rootSM.push_back( mesh.GetSubMesh( it.Value() )); } // add subshapes of empty submeshes list< SMESH_subMesh* >::iterator rootIt = rootSM.begin(), rootEnd = rootSM.end(); for ( ; rootIt != rootEnd; ++rootIt ) { SMESH_subMesh * root = *rootIt; SMESH_subMeshIteratorPtr smIt = root->getDependsOnIterator(/*includeSelf=*/true, /*complexShapeFirst=*/true); // to find a right orientation of subshapes (PAL20462) TopTools_IndexedMapOfShape subShapes; TopExp::MapShapes(root->GetSubShape(), subShapes); while ( smIt->more() ) { SMESH_subMesh* sm = smIt->next(); if ( !meshedSM || sm->IsEmpty() ) { TopoDS_Shape shape = sm->GetSubShape(); if ( shape.ShapeType() != TopAbs_VERTEX ) shape = subShapes( subShapes.FindIndex( shape ));// - shape->index->oriented shape switch ( shape.ShapeType() ) { case TopAbs_FACE : occgeo.fmap.Add( shape ); break; case TopAbs_EDGE : occgeo.emap.Add( shape ); break; case TopAbs_VERTEX: occgeo.vmap.Add( shape ); break; case TopAbs_SOLID :occgeo.somap.Add( shape ); break; default:; } } // collect submeshes of meshed shapes else if (meshedSM) { meshedSM->push_back( sm ); } } } occgeo.facemeshstatus.SetSize (occgeo.fmap.Extent()); occgeo.facemeshstatus = 0; }
int OCCWire::chamfer(std::vector<OCCVertex *> vertices, std::vector<double> distances) { int vertices_size = vertices.size(); int distances_size = distances.size(); BRepFilletAPI_MakeFillet2d MF; try { if (this->getShape().IsNull()) { StdFail_NotDone::Raise("Shapes is Null"); } MF.Init(BRepBuilderAPI_MakeFace(this->getWire())); // creat map of vertices TopTools_IndexedMapOfShape vertMap; for (unsigned i=0; i<vertices.size(); i++) vertMap.Add(vertices[i]->getShape()); bool first = true; TopoDS_Edge firstEdge, nextEdge; TopoDS_Vertex vertex; BRepTools_WireExplorer Ex1; for (Ex1.Init(this->getWire()); Ex1.More(); ) { if(first == true) { firstEdge = Ex1.Current(); first = false; } Ex1.Next(); //if the number of edges is odd don't proceed if(Ex1.More() == Standard_False) break; nextEdge = Ex1.Current(); //get the common vertex of the two edges if (!TopExp::CommonVertex(firstEdge, nextEdge, vertex)) { // disconnected wire first = true; continue; } if (vertMap.Contains(vertex)) { int i = vertMap.FindIndex(vertex) - 1; if (distances_size == 1) { // single distance MF.AddChamfer(firstEdge, nextEdge, distances[0], distances[0]); } else if (distances_size == vertices_size) { // distance given for each vertex MF.AddChamfer(firstEdge, nextEdge, distances[i], distances[i]); } else { StdFail_NotDone::Raise("distances argument has wrong size"); } } firstEdge = nextEdge; } // special case for closed wire if (isClosed()) { // find seam vertex TopoDS_Vertex aV1; TopExp::Vertices(this->getWire(), vertex, aV1); // check if seam vertex has chamfer value if (vertMap.Contains(vertex)) { int i = vertMap.FindIndex(vertex) - 1; // map vertices to edges to find edge pair TopTools_IndexedDataMapOfShapeListOfShape mapVertexEdge; TopExp::MapShapesAndAncestors(this->getWire(), TopAbs_VERTEX, TopAbs_EDGE, mapVertexEdge); const TopTools_ListOfShape& edges = mapVertexEdge.FindFromKey(vertex); firstEdge = TopoDS::Edge(edges.First()); nextEdge = TopoDS::Edge(edges.Last()); if (distances_size == 1) { // single distance MF.AddChamfer(firstEdge, nextEdge, distances[0], distances[0]); } else if (distances_size == vertices_size) { // distance given for each vertex MF.AddChamfer(firstEdge, nextEdge, distances[i], distances[i]); } else { StdFail_NotDone::Raise("distances argument has wrong size"); } } } if(MF.Status() != ChFi2d_IsDone) StdFail_NotDone::Raise("chamfer operation failed"); TopTools_IndexedMapOfShape aMap; TopExp::MapShapes(MF.Shape(), TopAbs_WIRE, aMap); if(aMap.Extent() != 1) StdFail_NotDone::Raise("chamfer result did not result in single wire");; //add edges to the wire BRepBuilderAPI_MakeWire wire; BRepTools_WireExplorer Ex2; for(Ex2.Init(TopoDS::Wire(aMap(1))); Ex2.More(); Ex2.Next()) { wire.Add(Ex2.Current()); } this->setShape(wire.Shape()); // possible fix shape if (!this->fixShape()) StdFail_NotDone::Raise("Shapes not valid"); } catch(Standard_Failure &err) { Handle_Standard_Failure e = Standard_Failure::Caught(); const Standard_CString msg = e->GetMessageString(); if (msg != NULL && strlen(msg) > 1) { setErrorMessage(msg); } else { setErrorMessage("Failed to chamfer wire"); } return 0; } return 1; }
void ViewProviderPartExt::updateVisual(const TopoDS_Shape& inputShape) { // Clear selection Gui::SoSelectionElementAction action(Gui::SoSelectionElementAction::None); action.apply(this->faceset); action.apply(this->lineset); action.apply(this->nodeset); TopoDS_Shape cShape(inputShape); if (cShape.IsNull()) { coords ->point .setNum(0); norm ->vector .setNum(0); faceset ->coordIndex .setNum(0); faceset ->partIndex .setNum(0); lineset ->coordIndex .setNum(0); VisualTouched = false; return; } // time measurement and book keeping Base::TimeInfo start_time; int nbrTriangles=0,nbrNodes=0,nbrNorms=0,nbrFaces=0,nbrEdges=0,nbrLines=0; std::set<int> faceEdges; try { // calculating the deflection value Bnd_Box bounds; BRepBndLib::Add(cShape, bounds); bounds.SetGap(0.0); Standard_Real xMin, yMin, zMin, xMax, yMax, zMax; bounds.Get(xMin, yMin, zMin, xMax, yMax, zMax); Standard_Real deflection = ((xMax-xMin)+(yMax-yMin)+(zMax-zMin))/300.0 * Deviation.getValue(); // create or use the mesh on the data structure BRepMesh_IncrementalMesh myMesh(cShape,deflection); // We must reset the location here because the transformation data // are set in the placement property TopLoc_Location aLoc; cShape.Location(aLoc); // count triangles and nodes in the mesh TopExp_Explorer Ex; for (Ex.Init(cShape,TopAbs_FACE);Ex.More();Ex.Next()) { Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(TopoDS::Face(Ex.Current()), aLoc); // Note: we must also count empty faces if (!mesh.IsNull()) { nbrTriangles += mesh->NbTriangles(); nbrNodes += mesh->NbNodes(); nbrNorms += mesh->NbNodes(); } TopExp_Explorer xp; for (xp.Init(Ex.Current(),TopAbs_EDGE);xp.More();xp.Next()) faceEdges.insert(xp.Current().HashCode(INT_MAX)); nbrFaces++; } // get an indexed map of edges TopTools_IndexedMapOfShape M; TopExp::MapShapes(cShape, TopAbs_EDGE, M); std::set<int> edgeIdxSet; std::vector<int32_t> indxVector; std::vector<int32_t> edgeVector; // count and index the edges for (int i=1; i <= M.Extent(); i++) { edgeIdxSet.insert(i); nbrEdges++; const TopoDS_Edge& aEdge = TopoDS::Edge(M(i)); TopLoc_Location aLoc; // handling of the free edge that are not associated to a face // Note: The assumption that if for an edge BRep_Tool::Polygon3D // returns a valid object is wrong. This e.g. happens for ruled // surfaces which gets created by two edges or wires. // So, we have to store the hashes of the edges associated to a face. // If the hash of a given edge is not in this list we know it's really // a free edge. int hash = aEdge.HashCode(INT_MAX); if (faceEdges.find(hash) == faceEdges.end()) { Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(aEdge, aLoc); if (!aPoly.IsNull()) { int nbNodesInEdge = aPoly->NbNodes(); nbrNodes += nbNodesInEdge; } } } // reserve some memory indxVector.reserve(nbrEdges*8); // handling of the vertices TopTools_IndexedMapOfShape V; TopExp::MapShapes(cShape, TopAbs_VERTEX, V); nbrNodes += V.Extent(); // create memory for the nodes and indexes coords ->point .setNum(nbrNodes); norm ->vector .setNum(nbrNorms); faceset ->coordIndex .setNum(nbrTriangles*4); faceset ->partIndex .setNum(nbrFaces); // get the raw memory for fast fill up SbVec3f* verts = coords ->point .startEditing(); SbVec3f* norms = norm ->vector .startEditing(); int32_t* index = faceset ->coordIndex .startEditing(); int32_t* parts = faceset ->partIndex .startEditing(); // preset the normal vector with null vector for (int i=0;i < nbrNorms;i++) norms[i]= SbVec3f(0.0,0.0,0.0); int ii = 0,FaceNodeOffset=0,FaceTriaOffset=0; for (Ex.Init(cShape, TopAbs_FACE); Ex.More(); Ex.Next(),ii++) { TopLoc_Location aLoc; const TopoDS_Face &actFace = TopoDS::Face(Ex.Current()); // get the mesh of the shape Handle (Poly_Triangulation) mesh = BRep_Tool::Triangulation(actFace,aLoc); if (mesh.IsNull()) continue; // getting the transformation of the shape/face gp_Trsf myTransf; Standard_Boolean identity = true; if (!aLoc.IsIdentity()) { identity = false; myTransf = aLoc.Transformation(); } // getting size of node and triangle array of this face int nbNodesInFace = mesh->NbNodes(); int nbTriInFace = mesh->NbTriangles(); // check orientation TopAbs_Orientation orient = actFace.Orientation(); // cycling through the poly mesh const Poly_Array1OfTriangle& Triangles = mesh->Triangles(); const TColgp_Array1OfPnt& Nodes = mesh->Nodes(); for (int g=1;g<=nbTriInFace;g++) { // Get the triangle Standard_Integer N1,N2,N3; Triangles(g).Get(N1,N2,N3); // change orientation of the triangle if the face is reversed if ( orient != TopAbs_FORWARD ) { Standard_Integer tmp = N1; N1 = N2; N2 = tmp; } // get the 3 points of this triangle gp_Pnt V1(Nodes(N1)), V2(Nodes(N2)), V3(Nodes(N3)); // transform the vertices to the place of the face if (!identity) { V1.Transform(myTransf); V2.Transform(myTransf); V3.Transform(myTransf); } // calculating per vertex normals // Calculate triangle normal gp_Vec v1(V1.X(),V1.Y(),V1.Z()),v2(V2.X(),V2.Y(),V2.Z()),v3(V3.X(),V3.Y(),V3.Z()); gp_Vec Normal = (v2-v1)^(v3-v1); // add the triangle normal to the vertex normal for all points of this triangle norms[FaceNodeOffset+N1-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); norms[FaceNodeOffset+N2-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); norms[FaceNodeOffset+N3-1] += SbVec3f(Normal.X(),Normal.Y(),Normal.Z()); // set the vertices verts[FaceNodeOffset+N1-1].setValue((float)(V1.X()),(float)(V1.Y()),(float)(V1.Z())); verts[FaceNodeOffset+N2-1].setValue((float)(V2.X()),(float)(V2.Y()),(float)(V2.Z())); verts[FaceNodeOffset+N3-1].setValue((float)(V3.X()),(float)(V3.Y()),(float)(V3.Z())); // set the index vector with the 3 point indexes and the end delimiter index[FaceTriaOffset*4+4*(g-1)] = FaceNodeOffset+N1-1; index[FaceTriaOffset*4+4*(g-1)+1] = FaceNodeOffset+N2-1; index[FaceTriaOffset*4+4*(g-1)+2] = FaceNodeOffset+N3-1; index[FaceTriaOffset*4+4*(g-1)+3] = SO_END_FACE_INDEX; } parts[ii] = nbTriInFace; // new part // handling the edges lying on this face TopExp_Explorer Exp; for(Exp.Init(actFace,TopAbs_EDGE);Exp.More();Exp.Next()) { const TopoDS_Edge &actEdge = TopoDS::Edge(Exp.Current()); // get the overall index of this edge int idx = M.FindIndex(actEdge); edgeVector.push_back((int32_t)idx-1); // already processed this index ? if (edgeIdxSet.find(idx)!=edgeIdxSet.end()) { // this holds the indices of the edge's triangulation to the current polygon Handle(Poly_PolygonOnTriangulation) aPoly = BRep_Tool::PolygonOnTriangulation(actEdge, mesh, aLoc); if (aPoly.IsNull()) continue; // polygon does not exist // getting the indexes of the edge polygon const TColStd_Array1OfInteger& indices = aPoly->Nodes(); for (Standard_Integer i=indices.Lower();i <= indices.Upper();i++) { int inx = indices(i); indxVector.push_back(FaceNodeOffset+inx-1); // usually the coordinates for this edge are already set by the // triangles of the face this edge belongs to. However, there are // rare cases where some points are only referenced by the polygon // but not by any triangle. Thus, we must apply the coordinates to // make sure that everything is properly set. gp_Pnt p(Nodes(inx)); if (!identity) p.Transform(myTransf); verts[FaceNodeOffset+inx-1].setValue((float)(p.X()),(float)(p.Y()),(float)(p.Z())); } indxVector.push_back(-1); // remove the handled edge index from the set edgeIdxSet.erase(idx); } } edgeVector.push_back(-1); // counting up the per Face offsets FaceNodeOffset += nbNodesInFace; FaceTriaOffset += nbTriInFace; } // handling of the free edges for (int i=1; i <= M.Extent(); i++) { const TopoDS_Edge& aEdge = TopoDS::Edge(M(i)); Standard_Boolean identity = true; gp_Trsf myTransf; TopLoc_Location aLoc; // handling of the free edge that are not associated to a face int hash = aEdge.HashCode(INT_MAX); if (faceEdges.find(hash) == faceEdges.end()) { Handle(Poly_Polygon3D) aPoly = BRep_Tool::Polygon3D(aEdge, aLoc); if (!aPoly.IsNull()) { if (!aLoc.IsIdentity()) { identity = false; myTransf = aLoc.Transformation(); } const TColgp_Array1OfPnt& aNodes = aPoly->Nodes(); int nbNodesInEdge = aPoly->NbNodes(); gp_Pnt pnt; for (Standard_Integer j=1;j <= nbNodesInEdge;j++) { pnt = aNodes(j); if (!identity) pnt.Transform(myTransf); verts[FaceNodeOffset+j-1].setValue((float)(pnt.X()),(float)(pnt.Y()),(float)(pnt.Z())); indxVector.push_back(FaceNodeOffset+j-1); } indxVector.push_back(-1); FaceNodeOffset += nbNodesInEdge; } } } nodeset->startIndex.setValue(FaceNodeOffset); for (int i=0; i<V.Extent(); i++) { const TopoDS_Vertex& aVertex = TopoDS::Vertex(V(i+1)); gp_Pnt pnt = BRep_Tool::Pnt(aVertex); verts[FaceNodeOffset+i].setValue((float)(pnt.X()),(float)(pnt.Y()),(float)(pnt.Z())); } // normalize all normals for (int i = 0; i< nbrNorms ;i++) norms[i].normalize(); // preset the index vector size nbrLines = indxVector.size(); lineset ->coordIndex .setNum(nbrLines); int32_t* lines = lineset ->coordIndex .startEditing(); int l=0; for (std::vector<int32_t>::const_iterator it=indxVector.begin();it!=indxVector.end();++it,l++) lines[l] = *it; // end the editing of the nodes coords ->point .finishEditing(); norm ->vector .finishEditing(); faceset ->coordIndex .finishEditing(); faceset ->partIndex .finishEditing(); lineset ->coordIndex .finishEditing(); } catch (...) { Base::Console().Error("Cannot compute Inventor representation for the shape of %s.\n",pcObject->getNameInDocument()); } // printing some informations Base::Console().Log("ViewProvider update time: %f s\n",Base::TimeInfo::diffTimeF(start_time,Base::TimeInfo())); Base::Console().Log("Shape tria info: Faces:%d Edges:%d Nodes:%d Triangles:%d IdxVec:%d\n",nbrFaces,nbrEdges,nbrNodes,nbrTriangles,nbrLines); VisualTouched = false; }
void CreateFacesAndEdges(TopoDS_Shape shape, CFaceList* faces, CEdgeList* edges, CVertexList* vertices) { // create index maps TopTools_IndexedMapOfShape faceMap; TopTools_IndexedMapOfShape edgeMap; TopTools_IndexedMapOfShape vertexMap; for (TopExp_Explorer explorer(shape, TopAbs_FACE); explorer.More(); explorer.Next()) { faceMap.Add(explorer.Current()); } for (TopExp_Explorer explorer(shape, TopAbs_EDGE); explorer.More(); explorer.Next()) { edgeMap.Add(explorer.Current()); } for (TopExp_Explorer explorer(shape, TopAbs_VERTEX); explorer.More(); explorer.Next()) { vertexMap.Add(explorer.Current()); } std::vector<CFace*> face_array; face_array.resize(faceMap.Extent() + 1); std::vector<CEdge*> edge_array; edge_array.resize(edgeMap.Extent() + 1); std::vector<CVertex*> vertex_array; vertex_array.resize(vertexMap.Extent() + 1); // create the edge objects for(int i = 1;i<=edgeMap.Extent();i++) { const TopoDS_Shape &s = edgeMap(i); CEdge* new_object = new CEdge(TopoDS::Edge(s)); edge_array[i] = new_object; } // create the vertex objects for(int i = 1;i<=vertexMap.Extent();i++) { const TopoDS_Shape &s = vertexMap(i); CVertex* new_object = new CVertex(TopoDS::Vertex(s)); vertex_array[i] = new_object; } // add the edges in their face loop order std::set<CEdge*> edges_added; std::set<CVertex*> vertices_added; // create the face objects for(int i = 1;i<=faceMap.Extent();i++) { const TopoDS_Shape &s = faceMap(i); CFace* new_face_object = new CFace(TopoDS::Face(s)); faces->Add(new_face_object, NULL); face_array[i] = new_face_object; // create the loop objects TopTools_IndexedMapOfShape loopMap; for (TopExp_Explorer explorer(s, TopAbs_WIRE); explorer.More(); explorer.Next()) { loopMap.Add(explorer.Current()); } TopoDS_Wire outerWire=BRepTools::OuterWire(new_face_object->Face()); int outer_index = loopMap.FindIndex(outerWire); for(int i = 1;i<=loopMap.Extent();i++) { const TopoDS_Shape &s = loopMap(i); CLoop* new_loop_object = new CLoop(TopoDS::Wire(s)); new_face_object->m_loops.push_back(new_loop_object); if(outer_index == i)new_loop_object->m_is_outer = true; new_loop_object->m_pface = new_face_object; // find the loop's edges for(BRepTools_WireExplorer explorer(TopoDS::Wire(s)); explorer.More(); explorer.Next()) { CEdge* e = edge_array[edgeMap.FindIndex(explorer.Current())]; new_loop_object->m_edges.push_back(e); // add the edge if(edges_added.find(e) == edges_added.end()) { edges->Add(e, NULL); edges_added.insert(e); } // add the vertex CVertex* v = vertex_array[vertexMap.FindIndex(explorer.CurrentVertex())]; if(vertices_added.find(v) == vertices_added.end()) { vertices->Add(v, NULL); vertices_added.insert(v); } } } } // find the vertices' edges for(unsigned int i = 1; i<vertex_array.size(); i++) { CVertex* v = vertex_array[i]; TopTools_IndexedMapOfShape vertexEdgeMap; for (TopExp_Explorer expEdge(v->Vertex(), TopAbs_EDGE); expEdge.More(); expEdge.Next()) { vertexEdgeMap.Add(expEdge.Current()); } for(int i = 1; i<=vertexEdgeMap.Extent(); i++) { const TopoDS_Shape &s = vertexEdgeMap(i); CEdge* e = edge_array[edgeMap.FindIndex(s)]; v->m_edges.push_back(e); } } // find the faces' edges for(unsigned int i = 1; i<face_array.size(); i++) { CFace* face = face_array[i]; TopTools_IndexedMapOfShape faceEdgeMap; for (TopExp_Explorer expEdge(face->Face(), TopAbs_EDGE); expEdge.More(); expEdge.Next()) { faceEdgeMap.Add(expEdge.Current()); } for(int i = 1; i<=faceEdgeMap.Extent(); i++) { const TopoDS_Shape &s = faceEdgeMap(i); CEdge* e = edge_array[edgeMap.FindIndex(s)]; face->m_edges.push_back(e); e->m_faces.push_back(face); bool sense = (s.IsEqual(e->Edge()) == Standard_True); e->m_face_senses.push_back(sense); } } }
void OCC_Connect::FaceCutters::Build(TopoDS_Face const &face, TopoDS_Shape &result, int verbose) { clear(); /* First we create some data structures to access the topology */ TopTools_IndexedMapOfShape vertices; std::vector<std::pair<int,int> > e2v; for(unsigned int i = 0; i < edges.size(); i++) { TopExp::MapShapes(edges[i],TopAbs_VERTEX,vertices); TopoDS_Vertex v1, v2; TopExp::Vertices(edges[i],v1,v2); std::pair<int,int> t(vertices.FindIndex(v1),vertices.FindIndex(v2)); e2v.push_back(t); } std::vector<std::set<int> > v2e; for(unsigned int e = 0; e < e2v.size(); e++) { if(e2v[e].first >= (int)v2e.size()) v2e.resize(e2v[e].first+1); v2e[e2v[e].first].insert(e); if(e2v[e].second >= (int)v2e.size()) v2e.resize(e2v[e].second+1); v2e[e2v[e].second].insert(e); } std::set<int> open, odd; for(unsigned int i = 0; i < v2e.size(); i++) { if(v2e[i].size()==0) continue; else if(v2e[i].size()==1) open.insert(i); else if(v2e[i].size()&1) odd.insert(i); } if(open.size()&1) std::cerr << "Inconsistent open loops\n"; if(odd.size()&1) std::cerr << "Inconsistent odd loops\n"; for(;;) { int open_mode = -1; std::set<int> current_vertices; for(unsigned int start = 0; start < v2e.size(); start++) { if(v2e[start].size()==1) { if(verbose&Cutting) std::cout << "start open at " << start << "\n"; current_vertices.insert(start); open_mode=1; break; } } if(!current_vertices.size()) { for(unsigned int start = 0; start < v2e.size(); start++) { if(v2e[start].size()) { if(verbose&Cutting) std::cout << "start closed at " << start << "\n"; current_vertices.insert(start); open_mode=0; break; } } } if(!current_vertices.size()) break; std::map<int,std::deque<int> > wires; std::set<int> processed_edges; do { std::set<int> next_vertices; for(std::set<int>::iterator v=current_vertices.begin(); v!=current_vertices.end(); v++ ) { for(std::set<int>::iterator e=v2e[*v].begin() ; e!=v2e[*v].end(); e++ ) { if(processed_edges.count(*e)) continue; int other=e2v[*e].first==*v? e2v[*e].second:e2v[*e].first; if(open_mode) { if(v2e[other].size()==1) { // Other is open end too, finish wire. wires[*v].push_back(*e); std::deque<int>::const_iterator p; BRepBuilderAPI_MakeWire wire; if(verbose&Cutting) std::cout << "CUT Open wire:"; for(p=wires[*v].begin(); p!=wires[*v].end(); p++ ) { FinishEdge(*p, v2e, e2v); wire.Add(edges[*p]); if(verbose&Cutting) std::cout << ' ' << (*p)+1; } if(verbose&Cutting) std::cout << "\n"; push_back(wire); goto next_vertex; } } else { if( current_vertices.count(other) || next_vertices.count(other) ) { if(verbose&Cutting) std::cout << "CUT Closed wire:"; wires[*v].push_back(*e); while(wires[other].front() ==wires[*v].front() ) { wires[other].pop_front(); wires[*v].pop_front(); } BRepBuilderAPI_MakeWire wire; std::deque<int>::const_iterator p; for(p=wires[other].begin(); p!=wires[other].end(); p++ ) { FinishEdge(*p, v2e, e2v); wire.Add(edges[*p]); if(verbose&Cutting) std::cout << ' ' << (*p)+1; } std::deque<int>::reverse_iterator rp; for(rp=wires[*v].rbegin(); rp!=wires[*v].rend(); rp++ ) { FinishEdge(*rp, v2e, e2v); wire.Add(edges[*rp]); if(verbose&Cutting) std::cout << ' ' << (*rp)+1; } if(verbose&Cutting) std::cout << "\n"; push_back(wire); goto next_vertex; } } if(current_vertices.count(other)==0) { wires[other]=wires[*v]; wires[other].push_back(*e); processed_edges.insert(*e); next_vertices.insert(other); } } } current_vertices=next_vertices; } while(current_vertices.size()); next_vertex: ; } if(size()>1 && verbose&CuttingIntermediate) { if(verbose&Cutting) std::cout << "Saving multiple cuts\n"; BRep_Builder BB; TopoDS_Compound compound; BB.MakeCompound(compound); for(unsigned int i = 0; i < edges.size(); i++) BB.Add(compound,edges[i]); BRepTools::Write(compound,"cutter.brep"); ofstream out("cutter.dot",ios::trunc|ios::out); dump(e2v,out); } }
void CmdPartDesignChamfer::activated(int iMsg) { std::vector<Gui::SelectionObject> selection = getSelection().getSelectionEx(); if (selection.size() != 1) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), QObject::tr("Select an edge, face or body. Only one body is allowed.")); return; } if (!selection[0].isObjectTypeOf(Part::Feature::getClassTypeId())){ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong object type"), QObject::tr("Chamfer works only on parts")); return; } Part::Feature *base = static_cast<Part::Feature*>(selection[0].getObject()); const Part::TopoShape& TopShape = base->Shape.getShape(); if (TopShape._Shape.IsNull()){ QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), QObject::tr("Shape of selected part is empty")); return; } TopTools_IndexedMapOfShape mapOfEdges; TopTools_IndexedDataMapOfShapeListOfShape mapEdgeFace; TopExp::MapShapesAndAncestors(TopShape._Shape, TopAbs_EDGE, TopAbs_FACE, mapEdgeFace); TopExp::MapShapes(TopShape._Shape, TopAbs_EDGE, mapOfEdges); std::vector<std::string> SubNames = std::vector<std::string>(selection[0].getSubNames()); int i = 0; while(i < SubNames.size()) { std::string aSubName = static_cast<std::string>(SubNames.at(i)); if (aSubName.size() > 4 && aSubName.substr(0,4) == "Edge") { TopoDS_Edge edge = TopoDS::Edge(TopShape.getSubShape(aSubName.c_str())); const TopTools_ListOfShape& los = mapEdgeFace.FindFromKey(edge); if(los.Extent() != 2) { SubNames.erase(SubNames.begin()+i); continue; } const TopoDS_Shape& face1 = los.First(); const TopoDS_Shape& face2 = los.Last(); GeomAbs_Shape cont = BRep_Tool::Continuity(TopoDS::Edge(edge), TopoDS::Face(face1), TopoDS::Face(face2)); if (cont != GeomAbs_C0) { SubNames.erase(SubNames.begin()+i); continue; } i++; } else if(aSubName.size() > 4 && aSubName.substr(0,4) == "Face") { TopoDS_Face face = TopoDS::Face(TopShape.getSubShape(aSubName.c_str())); TopTools_IndexedMapOfShape mapOfFaces; TopExp::MapShapes(face, TopAbs_EDGE, mapOfFaces); for(int j = 1; j <= mapOfFaces.Extent(); ++j) { TopoDS_Edge edge = TopoDS::Edge(mapOfFaces.FindKey(j)); int id = mapOfEdges.FindIndex(edge); std::stringstream buf; buf << "Edge"; buf << id; if(std::find(SubNames.begin(),SubNames.end(),buf.str()) == SubNames.end()) { SubNames.push_back(buf.str()); } } SubNames.erase(SubNames.begin()+i); } // empty name or any other sub-element else { SubNames.erase(SubNames.begin()+i); } } if (SubNames.size() == 0) { QMessageBox::warning(Gui::getMainWindow(), QObject::tr("Wrong selection"), QObject::tr("No chamfer possible on selected faces/edges")); return; } std::string SelString; SelString += "(App."; SelString += "ActiveDocument";//getObject()->getDocument()->getName(); SelString += "."; SelString += selection[0].getFeatName(); SelString += ",["; for(std::vector<std::string>::const_iterator it = SubNames.begin();it!=SubNames.end();++it){ SelString += "\""; SelString += *it; SelString += "\""; if(it != --SubNames.end()) SelString += ","; } SelString += "])"; std::string FeatName = getUniqueObjectName("Chamfer"); openCommand("Make Chamfer"); doCommand(Doc,"App.activeDocument().addObject(\"PartDesign::Chamfer\",\"%s\")",FeatName.c_str()); doCommand(Doc,"App.activeDocument().%s.Base = %s",FeatName.c_str(),SelString.c_str()); doCommand(Gui,"Gui.activeDocument().hide(\"%s\")",selection[0].getFeatName()); doCommand(Gui,"Gui.activeDocument().setEdit('%s')",FeatName.c_str()); copyVisual(FeatName.c_str(), "ShapeColor", selection[0].getFeatName()); copyVisual(FeatName.c_str(), "LineColor", selection[0].getFeatName()); copyVisual(FeatName.c_str(), "PointColor", selection[0].getFeatName()); }