Standard_Boolean ShHealOper_RemoveFace::isReplace(const TopoDS_Shape& theShape, TopoDS_Shape& theNewShape) { Standard_Boolean isChange = Standard_False; TopTools_SequenceOfShape aSeqShapes; if(theShape.ShapeType() == TopAbs_COMPOUND || theShape.ShapeType() == TopAbs_COMPSOLID || theShape.ShapeType() == TopAbs_SOLID) { TopoDS_Iterator aEs(theShape); for( ; aEs.More(); aEs.Next()) { TopoDS_Shape aNewShell = aEs.Value(); if(aNewShell.ShapeType()!= TopAbs_SHELL) { aSeqShapes.Append(aNewShell); continue; } TopoDS_Shape as = getResultShell(TopoDS::Shell(aNewShell)); isChange = (as.IsNull() || (as.ShapeType() == TopAbs_FACE)); if(!as.IsNull()) { aSeqShapes.Append(as); } } } else if(theShape.ShapeType() == TopAbs_SHELL) { TopoDS_Shape aSh = getResultShell(TopoDS::Shell(theShape)); isChange = (aSh.IsNull() || (aSh.ShapeType() == TopAbs_FACE)); if(!aSh.IsNull()) aSeqShapes.Append(aSh); } else aSeqShapes.Append(theShape); if(aSeqShapes.IsEmpty()) return Standard_True; if(isChange) { if(aSeqShapes.Length() == 1) theNewShape = aSeqShapes.Value(1); else if (aSeqShapes.Length() > 1) { TopoDS_Compound aComp1; BRep_Builder aBB; aBB.MakeCompound(aComp1); Standard_Integer kk =1; for( ; kk <= aSeqShapes.Length(); kk++) aBB.Add(aComp1,aSeqShapes.Value(kk)); if(aSeqShapes.Length()) theNewShape = aComp1; } } else theNewShape = theShape; return isChange; }
//======================================================================= //function : SupressFaces //purpose : //======================================================================= void SuppressFacesRec (const TopTools_SequenceOfShape& theShapesFaces, const TopoDS_Shape& theOriginalShape, TopoDS_Shape& theOutShape) { if ((theOriginalShape.ShapeType() != TopAbs_COMPOUND && theOriginalShape.ShapeType() != TopAbs_COMPSOLID)) { ShHealOper_RemoveFace aHealer (theOriginalShape); Standard_Boolean aResult = aHealer.Perform(theShapesFaces); if (aResult) theOutShape = aHealer.GetResultShape(); else raiseNotDoneExeption(aHealer.GetErrorStatus()); } else { BRep_Builder BB; TopoDS_Compound CC; BB.MakeCompound(CC); TopTools_MapOfShape mapShape; TopoDS_Iterator It (theOriginalShape, Standard_True, Standard_True); for (; It.More(); It.Next()) { TopoDS_Shape aShape_i = It.Value(); if (mapShape.Add(aShape_i)) { // check, if current shape contains at least one of faces to be removed bool isFound = false; TopTools_IndexedMapOfShape aShapes_i; TopExp::MapShapes(aShape_i, aShapes_i); for (int i = 1; i <= theShapesFaces.Length() && !isFound; i++) { const TopoDS_Shape& aFace_i = theShapesFaces.Value(i); if (aShapes_i.Contains(aFace_i)) isFound = true; } if (isFound) { TopoDS_Shape anOutSh_i; SuppressFacesRec(theShapesFaces, aShape_i, anOutSh_i); if ( !anOutSh_i.IsNull() ) BB.Add(CC, anOutSh_i); } else { // nothing to do BB.Add(CC, aShape_i); } } } theOutShape = CC; } }
Standard_Boolean ShHealOper_Sewing::sewing(const TopTools_SequenceOfShape& theSeqShapes) { myDone = Standard_False; myErrorStatus = ShHealOper_NotError; if(myInitShape.IsNull()) { myErrorStatus = ShHealOper_InvalidParameters; return myDone; } //sewing shape Handle(BRepBuilderAPI_Sewing) aSewing = new BRepBuilderAPI_Sewing; aSewing->Load(myInitShape); aSewing->SetTolerance(myTolerance); aSewing->SetFaceMode(myFacesMode); aSewing->SetFloatingEdgesMode(myEdgesMode); aSewing->SetNonManifoldMode(myNonManifoldMode); Standard_Integer j =1; for( ; j <= theSeqShapes.Length();j++) aSewing->Add(theSeqShapes.Value(j)); aSewing->Perform(); const TopoDS_Shape aSewShape = aSewing->SewedShape(); if(aSewShape.IsNull()) { myErrorStatus = ShHealOper_ErrorExecution; return myDone; } if(aSewShape.IsSame(myInitShape)) return myDone; //analysis either sewing was made by changing number of shells myDone = isSewed(aSewShape); //keep modification of the subshapes in the Context. TopExp_Explorer aExp(myInitShape,TopAbs_FACE); for( ; aExp.More(); aExp.Next()) myDone = (getModifications( aExp.Current(),aSewing) || myDone); TopoDS_Shape aTempShape = myContext->Apply(aSewShape); //obtained shells with fixed orientation for manifold and nonmanifold shells if(myFacesMode) myDone = getShells(aTempShape) || myDone; //obtained manifold wires if sewing edges was performed. if(myEdgesMode) myDone = getWires(aTempShape) || myDone; if(myDone) myResultShape = myContext->Apply(aTempShape); return myDone; }
Standard_Boolean ShHealOper_RemoveFace::Perform(const TopTools_SequenceOfShape& theRemoveFaces) { myDone = Standard_False; myErrorStatus = ShHealOper_NotError; if(myInitShape.IsNull()) { myErrorStatus = ShHealOper_InvalidParameters; return myDone; } if(theRemoveFaces.IsEmpty()) return Standard_False; myMapFaces.Clear(); Standard_Integer i=1; for( ; i <= theRemoveFaces.Length(); i++) myMapFaces.Add(theRemoveFaces.Value(i)); myDone = removeFaces(myInitShape,myResultShape); return myDone; }
//======================================================================= //function : MergeEdges //purpose : auxilary //======================================================================= static Standard_Boolean MergeEdges(const TopTools_SequenceOfShape& SeqEdges, const TopoDS_Face& aFace, const Standard_Real Tol, TopoDS_Edge& anEdge) { // make chain for union BRep_Builder B; ShapeAnalysis_Edge sae; TopoDS_Edge FirstE = TopoDS::Edge(SeqEdges.Value(1)); TopoDS_Edge LastE = FirstE; TopoDS_Vertex VF = sae.FirstVertex(FirstE); TopoDS_Vertex VL = sae.LastVertex(LastE); TopTools_SequenceOfShape aChain; aChain.Append(FirstE); TColStd_MapOfInteger IndUsedEdges; IndUsedEdges.Add(1); Standard_Integer j; for(j=2; j<=SeqEdges.Length(); j++) { for(Standard_Integer k=2; k<=SeqEdges.Length(); k++) { if(IndUsedEdges.Contains(k)) continue; TopoDS_Edge edge = TopoDS::Edge(SeqEdges.Value(k)); TopoDS_Vertex VF2 = sae.FirstVertex(edge); TopoDS_Vertex VL2 = sae.LastVertex(edge); if(sae.FirstVertex(edge).IsSame(VL)) { aChain.Append(edge); LastE = edge; VL = sae.LastVertex(LastE); IndUsedEdges.Add(k); } else if(sae.LastVertex(edge).IsSame(VF)) { aChain.Prepend(edge); FirstE = edge; VF = sae.FirstVertex(FirstE); IndUsedEdges.Add(k); } } } if(aChain.Length()<SeqEdges.Length()) { MESSAGE ("can not create correct chain..."); return Standard_False; } // union edges in chain // first step: union lines and circles TopLoc_Location Loc; Standard_Real fp1,lp1,fp2,lp2; for(j=1; j<aChain.Length(); j++) { TopoDS_Edge edge1 = TopoDS::Edge(aChain.Value(j)); Handle(Geom_Curve) c3d1 = BRep_Tool::Curve(edge1,Loc,fp1,lp1); if(c3d1.IsNull()) break; while(c3d1->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) { Handle(Geom_TrimmedCurve) tc = Handle(Geom_TrimmedCurve)::DownCast(c3d1); c3d1 = tc->BasisCurve(); } TopoDS_Edge edge2 = TopoDS::Edge(aChain.Value(j+1)); Handle(Geom_Curve) c3d2 = BRep_Tool::Curve(edge2,Loc,fp2,lp2); if(c3d2.IsNull()) break; while(c3d2->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) { Handle(Geom_TrimmedCurve) tc = Handle(Geom_TrimmedCurve)::DownCast(c3d2); c3d2 = tc->BasisCurve(); } if( c3d1->IsKind(STANDARD_TYPE(Geom_Line)) && c3d2->IsKind(STANDARD_TYPE(Geom_Line)) ) { // union lines Handle(Geom_Line) L1 = Handle(Geom_Line)::DownCast(c3d1); Handle(Geom_Line) L2 = Handle(Geom_Line)::DownCast(c3d2); gp_Dir Dir1 = L1->Position().Direction(); gp_Dir Dir2 = L2->Position().Direction(); //if(!Dir1.IsEqual(Dir2,Precision::Angular())) { //if(!Dir1.IsParallel(Dir2,Precision::Angular())) { if(!Dir1.IsParallel(Dir2,Tol)) { continue; } // can union lines => create new edge TopoDS_Vertex V1 = sae.FirstVertex(edge1); gp_Pnt PV1 = BRep_Tool::Pnt(V1); TopoDS_Vertex V2 = sae.LastVertex(edge2); gp_Pnt PV2 = BRep_Tool::Pnt(V2); gp_Vec Vec(PV1,PV2); Handle(Geom_Line) L = new Geom_Line(gp_Ax1(PV1,Vec)); Standard_Real dist = PV1.Distance(PV2); Handle(Geom_TrimmedCurve) tc = new Geom_TrimmedCurve(L,0.0,dist); TopoDS_Edge E; B.MakeEdge (E,tc,Precision::Confusion()); B.Add (E,V1); B.Add (E,V2); B.UpdateVertex(V1, 0., E, 0.); B.UpdateVertex(V2, dist, E, 0.); //ShapeFix_Edge sfe; //sfe.FixAddPCurve(E,aFace,Standard_False); //sfe.FixSameParameter(E); aChain.Remove(j); aChain.SetValue(j,E); j--; } if( c3d1->IsKind(STANDARD_TYPE(Geom_Circle)) && c3d2->IsKind(STANDARD_TYPE(Geom_Circle)) ) { // union circles Handle(Geom_Circle) C1 = Handle(Geom_Circle)::DownCast(c3d1); Handle(Geom_Circle) C2 = Handle(Geom_Circle)::DownCast(c3d2); gp_Pnt P01 = C1->Location(); gp_Pnt P02 = C2->Location(); if (P01.Distance(P02) > Precision::Confusion()) continue; // can union circles => create new edge TopoDS_Vertex V1 = sae.FirstVertex(edge1); gp_Pnt PV1 = BRep_Tool::Pnt(V1); TopoDS_Vertex V2 = sae.LastVertex(edge2); gp_Pnt PV2 = BRep_Tool::Pnt(V2); TopoDS_Vertex VM = sae.LastVertex(edge1); gp_Pnt PVM = BRep_Tool::Pnt(VM); GC_MakeCircle MC (PV1,PVM,PV2); Handle(Geom_Circle) C = MC.Value(); TopoDS_Edge E; if (!MC.IsDone() || C.IsNull()) { // jfa for Mantis issue 0020228 if (PV1.Distance(PV2) > Precision::Confusion()) continue; // closed chain C = C1; B.MakeEdge (E,C,Precision::Confusion()); B.Add(E,V1); B.Add(E,V2); } else { gp_Pnt P0 = C->Location(); gp_Dir D1(gp_Vec(P0,PV1)); gp_Dir D2(gp_Vec(P0,PV2)); Standard_Real fpar = C->XAxis().Direction().Angle(D1); if(fabs(fpar)>Precision::Confusion()) { // check orientation gp_Dir ND = C->XAxis().Direction().Crossed(D1); if(ND.IsOpposite(C->Axis().Direction(),Precision::Confusion())) { fpar = -fpar; } } Standard_Real lpar = C->XAxis().Direction().Angle(D2); if(fabs(lpar)>Precision::Confusion()) { // check orientation gp_Dir ND = C->XAxis().Direction().Crossed(D2); if(ND.IsOpposite(C->Axis().Direction(),Precision::Confusion())) { lpar = -lpar; } } if(lpar<fpar) lpar += 2*M_PI; Handle(Geom_TrimmedCurve) tc = new Geom_TrimmedCurve(C,fpar,lpar); B.MakeEdge (E,tc,Precision::Confusion()); B.Add(E,V1); B.Add(E,V2); B.UpdateVertex(V1, fpar, E, 0.); B.UpdateVertex(V2, lpar, E, 0.); } aChain.Remove(j); aChain.SetValue(j,E); j--; } } if (j < aChain.Length()) { MESSAGE ("null curve3d in edge..."); return Standard_False; } if (aChain.Length() > 1) { // second step: union edges with various curves // skl for bug 0020052 from Mantis: perform such unions // only if curves are bspline or bezier bool NeedUnion = true; for(j=1; j<=aChain.Length(); j++) { TopoDS_Edge edge = TopoDS::Edge(aChain.Value(j)); Handle(Geom_Curve) c3d = BRep_Tool::Curve(edge,Loc,fp1,lp1); if(c3d.IsNull()) continue; while(c3d->IsKind(STANDARD_TYPE(Geom_TrimmedCurve))) { Handle(Geom_TrimmedCurve) tc = Handle(Geom_TrimmedCurve)::DownCast(c3d); c3d = tc->BasisCurve(); } if( ( c3d->IsKind(STANDARD_TYPE(Geom_BSplineCurve)) || c3d->IsKind(STANDARD_TYPE(Geom_BezierCurve)) ) ) continue; NeedUnion = false; break; } if(NeedUnion) { MESSAGE ("can not make analitical union => make approximation"); TopoDS_Wire W; B.MakeWire(W); for(j=1; j<=aChain.Length(); j++) { TopoDS_Edge edge = TopoDS::Edge(aChain.Value(j)); B.Add(W,edge); } Handle(BRepAdaptor_HCompCurve) Adapt = new BRepAdaptor_HCompCurve(W); Approx_Curve3d Conv(Adapt,Tol,GeomAbs_C1,9,1000); Handle(Geom_BSplineCurve) bc = Conv.Curve(); TopoDS_Edge E; B.MakeEdge (E,bc,Precision::Confusion()); B.Add (E,VF); B.Add (E,VL); aChain.SetValue(1,E); } else { MESSAGE ("can not make approximation for such types of curves"); return Standard_False; } } anEdge = TopoDS::Edge(aChain.Value(1)); return Standard_True; }
bool StdMeshers_Hexa_3D::Evaluate(SMESH_Mesh & aMesh, const TopoDS_Shape & aShape, MapShapeNbElems& aResMap) { vector < SMESH_subMesh * >meshFaces; TopTools_SequenceOfShape aFaces; for (TopExp_Explorer exp(aShape, TopAbs_FACE); exp.More(); exp.Next()) { aFaces.Append(exp.Current()); SMESH_subMesh *aSubMesh = aMesh.GetSubMeshContaining(exp.Current()); ASSERT(aSubMesh); meshFaces.push_back(aSubMesh); } if (meshFaces.size() != 6) { //return error(COMPERR_BAD_SHAPE, TComm(meshFaces.size())<<" instead of 6 faces in a block"); static StdMeshers_CompositeHexa_3D compositeHexa(-10, 0, aMesh.GetGen()); return compositeHexa.Evaluate(aMesh, aShape, aResMap); } int i = 0; for(; i<6; i++) { //TopoDS_Shape aFace = meshFaces[i]->GetSubShape(); TopoDS_Shape aFace = aFaces.Value(i+1); SMESH_Algo *algo = _gen->GetAlgo(aMesh, aFace); if( !algo ) { std::vector<int> aResVec(SMDSEntity_Last); for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0; SMESH_subMesh * sm = aMesh.GetSubMesh(aShape); aResMap.insert(std::make_pair(sm,aResVec)); SMESH_ComputeErrorPtr& smError = sm->GetComputeError(); smError.reset( new SMESH_ComputeError(COMPERR_ALGO_FAILED,"Submesh can not be evaluated",this)); return false; } string algoName = algo->GetName(); bool isAllQuad = false; if (algoName == "Quadrangle_2D") { MapShapeNbElemsItr anIt = aResMap.find(meshFaces[i]); if( anIt == aResMap.end() ) continue; std::vector<int> aVec = (*anIt).second; int nbtri = Max(aVec[SMDSEntity_Triangle],aVec[SMDSEntity_Quad_Triangle]); if( nbtri == 0 ) isAllQuad = true; } if ( ! isAllQuad ) { return EvaluatePentahedralMesh(aMesh, aShape, aResMap); } } // find number of 1d elems for 1 face int nb1d = 0; TopTools_MapOfShape Edges1; bool IsQuadratic = false; bool IsFirst = true; for (TopExp_Explorer exp(aFaces.Value(1), TopAbs_EDGE); exp.More(); exp.Next()) { Edges1.Add(exp.Current()); SMESH_subMesh *sm = aMesh.GetSubMesh(exp.Current()); if( sm ) { MapShapeNbElemsItr anIt = aResMap.find(sm); if( anIt == aResMap.end() ) continue; std::vector<int> aVec = (*anIt).second; nb1d += Max(aVec[SMDSEntity_Edge],aVec[SMDSEntity_Quad_Edge]); if(IsFirst) { IsQuadratic = (aVec[SMDSEntity_Quad_Edge] > aVec[SMDSEntity_Edge]); IsFirst = false; } } } // find face opposite to 1 face int OppNum = 0; for(i=2; i<=6; i++) { bool IsOpposite = true; for(TopExp_Explorer exp(aFaces.Value(i), TopAbs_EDGE); exp.More(); exp.Next()) { if( Edges1.Contains(exp.Current()) ) { IsOpposite = false; break; } } if(IsOpposite) { OppNum = i; break; } } // find number of 2d elems on side faces int nb2d = 0; for(i=2; i<=6; i++) { if( i == OppNum ) continue; MapShapeNbElemsItr anIt = aResMap.find( meshFaces[i-1] ); if( anIt == aResMap.end() ) continue; std::vector<int> aVec = (*anIt).second; nb2d += Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]); } MapShapeNbElemsItr anIt = aResMap.find( meshFaces[0] ); std::vector<int> aVec = (*anIt).second; int nb2d_face0 = Max(aVec[SMDSEntity_Quadrangle],aVec[SMDSEntity_Quad_Quadrangle]); int nb0d_face0 = aVec[SMDSEntity_Node]; std::vector<int> aResVec(SMDSEntity_Last); for(int i=SMDSEntity_Node; i<SMDSEntity_Last; i++) aResVec[i] = 0; if(IsQuadratic) { aResVec[SMDSEntity_Quad_Hexa] = nb2d_face0 * ( nb2d/nb1d ); int nb1d_face0_int = ( nb2d_face0*4 - nb1d ) / 2; aResVec[SMDSEntity_Node] = nb0d_face0 * ( 2*nb2d/nb1d - 1 ) - nb1d_face0_int * nb2d/nb1d; } else { aResVec[SMDSEntity_Node] = nb0d_face0 * ( nb2d/nb1d - 1 ); aResVec[SMDSEntity_Hexa] = nb2d_face0 * ( nb2d/nb1d ); } SMESH_subMesh * sm = aMesh.GetSubMesh(aShape); aResMap.insert(std::make_pair(sm,aResVec)); return true; }