//======================================================================= //function : PrepareHistory //purpose : //======================================================================= void GEOMAlgo_Builder::PrepareHistory() { if(myShape.IsNull()) { return; } // Standard_Boolean bHasImage, bContainsSD; TopAbs_ShapeEnum aType; TopTools_MapOfShape aMS; TopTools_ListIteratorOfListOfShape aIt; TopTools_MapIteratorOfMapOfShape aItM; // // 1. Clearing GEOMAlgo_BuilderShape::PrepareHistory(); // // 2. myMapShape - all shapes of result with theirs sub-shapes MapShapes(myShape, myMapShape); // // 3. MS - all argument shapes with theirs sub-shapes aIt.Initialize(myShapes); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aSx=aIt.Value(); MapShapes(aSx, aMS); } // // 4. Treatment aItM.Initialize(aMS); for (; aItM.More(); aItM.Next()) { const TopoDS_Shape& aSx=aItM.Key(); aType=aSx.ShapeType(); //modified by NIZNHY-PKV Thu Dec 7 11:34:05 2006f // // 4.1 .myImagesResult TopTools_ListOfShape aLSx; // bHasImage=myImages.HasImage(aSx); if (!bHasImage) { if (myMapShape.Contains(aSx)) { aLSx.Append(aSx); myImagesResult.Add(aSx, aLSx); } } else { const TopTools_ListOfShape& aLSp=myImages.Image(aSx); aIt.Initialize(aLSp); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aSp=aIt.Value(); if (myMapShape.Contains(aSp)) { aLSx.Append(aSp); } } myImagesResult.Add(aSx, aLSx); } // //modified by NIZNHY-PKV Thu Dec 7 11:34:10 2006t // // 4.2 As it was if (!myHasDeleted) { myHasDeleted=IsDeleted(aSx);//xx } // if (!myHasGenerated || !myHasModified) { if (aType==TopAbs_EDGE || aType==TopAbs_FACE || aType==TopAbs_VERTEX || aType==TopAbs_SOLID) { //modified by NIZNHY-PKV Thu Dec 7 11:53:01 2006f //bHasImage=myImages.HasImage(aSx); //modified by NIZNHY-PKV Thu Dec 7 11:53:04 2006t if (bHasImage) { const TopTools_ListOfShape& aLSp=myImages.Image(aSx); aIt.Initialize(aLSp); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aSp=aIt.Value(); // if (myMapShape.Contains(aSp)) { bContainsSD=mySameDomainShapes.Contains(aSp); // if (!myHasGenerated) { if (bContainsSD) { myHasGenerated=Standard_True; } } if (!myHasModified) { if (!bContainsSD) { myHasModified=Standard_True; } } } // if (myMapShape.Contains(aSp)) } } } } } }
App::DocumentObjectExecReturn *Sweep::execute(void) { if (Sections.getSize() == 0) return new App::DocumentObjectExecReturn("No sections linked."); App::DocumentObject* spine = Spine.getValue(); if (!(spine && spine->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))) return new App::DocumentObjectExecReturn("No spine linked."); const std::vector<std::string>& subedge = Spine.getSubValues(); TopoDS_Shape path; const Part::TopoShape& shape = static_cast<Part::Feature*>(spine)->Shape.getValue(); if (!shape._Shape.IsNull()) { try { BRepBuilderAPI_MakeWire mkWire; for (std::vector<std::string>::const_iterator it = subedge.begin(); it != subedge.end(); ++it) { TopoDS_Shape subshape = shape.getSubShape(it->c_str()); mkWire.Add(TopoDS::Edge(subshape)); } path = mkWire.Wire(); } catch (Standard_Failure) { if (shape._Shape.ShapeType() == TopAbs_EDGE) path = shape._Shape; else if (shape._Shape.ShapeType() == TopAbs_WIRE) path = shape._Shape; else return new App::DocumentObjectExecReturn("Spine is neither an edge nor a wire."); } } try { TopTools_ListOfShape profiles; const std::vector<App::DocumentObject*>& shapes = Sections.getValues(); std::vector<App::DocumentObject*>::const_iterator it; for (it = shapes.begin(); it != shapes.end(); ++it) { if (!(*it)->isDerivedFrom(Part::Feature::getClassTypeId())) return new App::DocumentObjectExecReturn("Linked object is not a shape."); const TopoDS_Shape& shape = static_cast<Part::Feature*>(*it)->Shape.getValue(); if (shape.IsNull()) return new App::DocumentObjectExecReturn("Linked shape is invalid."); // There is a weird behaviour of BRepOffsetAPI_MakePipeShell when trying to add the wire as is. // If we re-create the wire then everything works fine. // https://sourceforge.net/apps/phpbb/free-cad/viewtopic.php?f=10&t=2673&sid=fbcd2ff4589f0b2f79ed899b0b990648#p20268 if (shape.ShapeType() == TopAbs_WIRE) { BRepBuilderAPI_MakeWire mkWire(TopoDS::Wire(shape)); profiles.Append(mkWire.Wire()); } else if (shape.ShapeType() == TopAbs_EDGE) { BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(shape)); profiles.Append(mkWire.Wire()); } else if (shape.ShapeType() == TopAbs_VERTEX) { profiles.Append(shape); } else { return new App::DocumentObjectExecReturn("Linked shape is not a vertex, edge nor wire."); } } Standard_Boolean isSolid = Solid.getValue() ? Standard_True : Standard_False; Standard_Boolean isFrenet = Frenet.getValue() ? Standard_True : Standard_False; BRepBuilderAPI_TransitionMode transMode; switch (Transition.getValue()) { case 1: transMode = BRepBuilderAPI_RightCorner; break; case 2: transMode = BRepBuilderAPI_RoundCorner; break; default: transMode = BRepBuilderAPI_Transformed; break; } if (path.ShapeType() == TopAbs_EDGE) { BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(path)); path = mkWire.Wire(); } BRepOffsetAPI_MakePipeShell mkPipeShell(TopoDS::Wire(path)); mkPipeShell.SetMode(isFrenet); mkPipeShell.SetTransitionMode(transMode); TopTools_ListIteratorOfListOfShape iter; for (iter.Initialize(profiles); iter.More(); iter.Next()) { mkPipeShell.Add(TopoDS_Shape(iter.Value())); } if (!mkPipeShell.IsReady()) Standard_Failure::Raise("shape is not ready to build"); mkPipeShell.Build(); if (isSolid) mkPipeShell.MakeSolid(); this->Shape.setValue(mkPipeShell.Shape()); return App::DocumentObject::StdReturn; } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); return new App::DocumentObjectExecReturn(e->GetMessageString()); } }
//======================================================================= //function : SortShapes //purpose : //======================================================================= void GEOMUtils::SortShapes (TopTools_ListOfShape& SL, const Standard_Boolean isOldSorting) { #ifdef STD_SORT_ALGO std::vector<TopoDS_Shape> aShapesVec; aShapesVec.reserve(SL.Extent()); TopTools_ListIteratorOfListOfShape it (SL); for (; it.More(); it.Next()) { aShapesVec.push_back(it.Value()); } SL.Clear(); CompareShapes shComp (isOldSorting); std::stable_sort(aShapesVec.begin(), aShapesVec.end(), shComp); //std::sort(aShapesVec.begin(), aShapesVec.end(), shComp); std::vector<TopoDS_Shape>::const_iterator anIter = aShapesVec.begin(); for (; anIter != aShapesVec.end(); ++anIter) { SL.Append(*anIter); } #else // old implementation Standard_Integer MaxShapes = SL.Extent(); TopTools_Array1OfShape aShapes (1,MaxShapes); TColStd_Array1OfInteger OrderInd(1,MaxShapes); TColStd_Array1OfReal MidXYZ (1,MaxShapes); //X,Y,Z; TColStd_Array1OfReal Length (1,MaxShapes); //X,Y,Z; // Computing of CentreOfMass Standard_Integer Index; GProp_GProps GPr; gp_Pnt GPoint; TopTools_ListIteratorOfListOfShape it(SL); for (Index=1; it.More(); Index++) { TopoDS_Shape S = it.Value(); SL.Remove( it ); // == it.Next() aShapes(Index) = S; OrderInd.SetValue (Index, Index); if (S.ShapeType() == TopAbs_VERTEX) { GPoint = BRep_Tool::Pnt( TopoDS::Vertex( S )); Length.SetValue( Index, (Standard_Real) S.Orientation()); } else { // BEGIN: fix for Mantis issue 0020842 if (isOldSorting) { BRepGProp::LinearProperties (S, GPr); } else { if (S.ShapeType() == TopAbs_EDGE || S.ShapeType() == TopAbs_WIRE) { BRepGProp::LinearProperties (S, GPr); } else if (S.ShapeType() == TopAbs_FACE || S.ShapeType() == TopAbs_SHELL) { BRepGProp::SurfaceProperties(S, GPr); } else { BRepGProp::VolumeProperties(S, GPr); } } // END: fix for Mantis issue 0020842 GPoint = GPr.CentreOfMass(); Length.SetValue(Index, GPr.Mass()); } MidXYZ.SetValue(Index, GPoint.X()*999.0 + GPoint.Y()*99.0 + GPoint.Z()*0.9); //cout << Index << " L: " << Length(Index) << "CG: " << MidXYZ(Index) << endl; } // Sorting Standard_Integer aTemp; Standard_Boolean exchange, Sort = Standard_True; Standard_Real tol = Precision::Confusion(); while (Sort) { Sort = Standard_False; for (Index=1; Index < MaxShapes; Index++) { exchange = Standard_False; Standard_Real dMidXYZ = MidXYZ(OrderInd(Index)) - MidXYZ(OrderInd(Index+1)); Standard_Real dLength = Length(OrderInd(Index)) - Length(OrderInd(Index+1)); if ( dMidXYZ >= tol ) { // cout << "MidXYZ: " << MidXYZ(OrderInd(Index))<< " > " <<MidXYZ(OrderInd(Index+1)) // << " d: " << dMidXYZ << endl; exchange = Standard_True; } else if ( Abs(dMidXYZ) < tol && dLength >= tol ) { // cout << "Length: " << Length(OrderInd(Index))<< " > " <<Length(OrderInd(Index+1)) // << " d: " << dLength << endl; exchange = Standard_True; } else if ( Abs(dMidXYZ) < tol && Abs(dLength) < tol && aShapes(OrderInd(Index)).ShapeType() <= TopAbs_FACE) { // PAL17233 // equal values possible on shapes such as two halves of a sphere and // a membrane inside the sphere Bnd_Box box1,box2; BRepBndLib::Add( aShapes( OrderInd(Index) ), box1 ); if ( box1.IsVoid() ) continue; BRepBndLib::Add( aShapes( OrderInd(Index+1) ), box2 ); Standard_Real dSquareExtent = box1.SquareExtent() - box2.SquareExtent(); if ( dSquareExtent >= tol ) { // cout << "SquareExtent: " << box1.SquareExtent()<<" > "<<box2.SquareExtent() << endl; exchange = Standard_True; } else if ( Abs(dSquareExtent) < tol ) { Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax, val1, val2; box1.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); val1 = (aXmin+aXmax)*999 + (aYmin+aYmax)*99 + (aZmin+aZmax)*0.9; box2.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax); val2 = (aXmin+aXmax)*999 + (aYmin+aYmax)*99 + (aZmin+aZmax)*0.9; //exchange = val1 > val2; if ((val1 - val2) >= tol) { exchange = Standard_True; } //cout << "box: " << val1<<" > "<<val2 << endl; } } if (exchange) { // cout << "exchange " << Index << " & " << Index+1 << endl; aTemp = OrderInd(Index); OrderInd(Index) = OrderInd(Index+1); OrderInd(Index+1) = aTemp; Sort = Standard_True; } } } for (Index=1; Index <= MaxShapes; Index++) SL.Append( aShapes( OrderInd(Index) )); #endif }
//======================================================================= // function: MakeConnexityBlock. // purpose: //======================================================================= void GEOMAlgo_Tools3D::MakeConnexityBlock (const TopTools_ListOfShape& theLFIn, const TopTools_IndexedMapOfShape& theMEAvoid, TopTools_ListOfShape& theLCB) { Standard_Integer aNbF, aNbAdd1; TopExp_Explorer aExp; TopTools_IndexedDataMapOfShapeListOfShape aMEF; TopTools_MapIteratorOfMapOfShape aItM, aItM1; TopTools_MapOfShape aMCB, aMAdd, aMAdd1; TopTools_ListIteratorOfListOfShape aIt; // // 1. aMEF aNbF=theLFIn.Extent(); aIt.Initialize(theLFIn); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aF=aIt.Value(); TopExp::MapShapesAndAncestors(aF, TopAbs_EDGE, TopAbs_FACE, aMEF); } // // 2. aMCB const TopoDS_Shape& aF1=theLFIn.First(); aMAdd.Add(aF1); // while(1) { aMAdd1.Clear(); aItM.Initialize(aMAdd); for (; aItM.More(); aItM.Next()) { const TopoDS_Shape& aF=aItM.Key(); // //aMAdd1.Clear(); aExp.Init(aF, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aE=aExp.Current(); if (theMEAvoid.Contains(aE)){ continue; } // const TopTools_ListOfShape& aLF=aMEF.FindFromKey(aE); aIt.Initialize(aLF); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aFx=aIt.Value(); if (aFx.IsSame(aF)) { continue; } if (aMCB.Contains(aFx)) { continue; } aMAdd1.Add(aFx); } }//for (; aExp.More(); aExp.Next()){ aMCB.Add(aF); }// for (; aItM.More(); aItM.Next()) { // aNbAdd1=aMAdd1.Extent(); if (!aNbAdd1) { break; } // aMAdd.Clear(); aItM1.Initialize(aMAdd1); for (; aItM1.More(); aItM1.Next()) { const TopoDS_Shape& aFAdd=aItM1.Key(); aMAdd.Add(aFAdd); } // }//while(1) { // aNbF=aMCB.Extent(); aItM.Initialize(aMCB); for (; aItM.More(); aItM.Next()) { const TopoDS_Shape& aF=aItM.Key(); theLCB.Append(aF); } }
//======================================================================= //function : FindFacePairs //purpose : //======================================================================= Standard_Boolean FindFacePairs (const TopoDS_Edge& theE, const TopTools_ListOfShape& thLF, NMTTools_ListOfCoupleOfShape& theLCFF) { Standard_Boolean bFound; Standard_Integer i, aNbCEF; TopAbs_Orientation aOr, aOrC; TopTools_MapOfShape aMFP; TopoDS_Face aF1, aF2; TopoDS_Edge aEL, aE1; TopTools_ListIteratorOfListOfShape aItLF; NMTTools_CoupleOfShape aCEF, aCFF; NMTTools_ListOfCoupleOfShape aLCEF, aLCEFx; NMTTools_ListIteratorOfListOfCoupleOfShape aIt; // bFound=Standard_True; // // Preface aLCEF aItLF.Initialize(thLF); for (; aItLF.More(); aItLF.Next()) { const TopoDS_Face& aFL=TopoDS::Face(aItLF.Value()); // bFound=GEOMAlgo_Tools3D::GetEdgeOnFace(theE, aFL, aEL); if (!bFound) { return bFound; // it can not be so } // aCEF.SetShape1(aEL); aCEF.SetShape2(aFL); aLCEF.Append(aCEF); } // aNbCEF=aLCEF.Extent(); while(aNbCEF) { // // aLCEFx aLCEFx.Clear(); aIt.Initialize(aLCEF); for (i=0; aIt.More(); aIt.Next(), ++i) { const NMTTools_CoupleOfShape& aCSx=aIt.Value(); const TopoDS_Shape& aEx=aCSx.Shape1(); const TopoDS_Shape& aFx=aCSx.Shape2(); // aOr=aEx.Orientation(); // if (!i) { aOrC=TopAbs::Reverse(aOr); aE1=TopoDS::Edge(aEx); aF1=TopoDS::Face(aFx); aMFP.Add(aFx); continue; } // if (aOr==aOrC) { aLCEFx.Append(aCSx); aMFP.Add(aFx); } } // // F2 GEOMAlgo_Tools3D::GetFaceOff(aE1, aF1, aLCEFx, aF2); // aCFF.SetShape1(aF1); aCFF.SetShape2(aF2); theLCFF.Append(aCFF); // aMFP.Add(aF1); aMFP.Add(aF2); // // refine aLCEF aLCEFx.Clear(); aLCEFx=aLCEF; aLCEF.Clear(); aIt.Initialize(aLCEFx); for (; aIt.More(); aIt.Next()) { const NMTTools_CoupleOfShape& aCSx=aIt.Value(); const TopoDS_Shape& aFx=aCSx.Shape2(); if (!aMFP.Contains(aFx)) { aLCEF.Append(aCSx); } } // aNbCEF=aLCEF.Extent(); }//while(aNbCEF) { // return bFound; }
//======================================================================= //function :PerformShapesToAvoid //purpose : //======================================================================= void GEOMAlgo_BuilderFace::PerformShapesToAvoid() { Standard_Boolean bFound; Standard_Integer i, iCnt, aNbV, aNbE; TopTools_IndexedDataMapOfShapeListOfShape aMVE; TopTools_ListIteratorOfListOfShape aIt; // myShapesToAvoid.Clear(); // iCnt=0; while (1) { ++iCnt; bFound=Standard_False; // // 1. MEF aMVE.Clear(); aIt.Initialize (myShapes); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aE=aIt.Value(); if (!myShapesToAvoid.Contains(aE)) { TopExp::MapShapesAndAncestors(aE, TopAbs_VERTEX, TopAbs_EDGE, aMVE); } // else { // int a=0; // } } aNbV=aMVE.Extent(); // // 2. myEdgesToAvoid for (i=1; i<=aNbV; ++i) { const TopoDS_Vertex& aV=TopoDS::Vertex(aMVE.FindKey(i)); // TopTools_ListOfShape& aLE=aMVE.ChangeFromKey(aV); aNbE=aLE.Extent(); if (!aNbE) { continue; } // const TopoDS_Edge& aE1=TopoDS::Edge(aLE.First()); if (aNbE==1) { if (BRep_Tool::Degenerated(aE1)) { continue; } if (aV.Orientation()==TopAbs_INTERNAL) { continue; } bFound=Standard_True; myShapesToAvoid.Add(aE1); } else if (aNbE==2) { const TopoDS_Edge& aE2=TopoDS::Edge(aLE.Last()); if (aE2.IsSame(aE1)) { TopoDS_Vertex aV1x, aV2x; // TopExp::Vertices(aE1, aV1x, aV2x); if (aV1x.IsSame(aV2x)) { continue; } bFound=Standard_True; myShapesToAvoid.Add(aE1); myShapesToAvoid.Add(aE2); } } }// for (i=1; i<=aNbE; ++i) { // if (!bFound) { break; } // }//while (1) //printf(" EdgesToAvoid=%d, iCnt=%d\n", EdgesToAvoid.Extent(), iCnt); }
bool NETGENPlugin_Mesher::fillNgMesh(netgen::OCCGeometry& occgeom, netgen::Mesh& ngMesh, vector<SMDS_MeshNode*>& nodeVec, const list< SMESH_subMesh* > & meshedSM) { TNode2IdMap nodeNgIdMap; TopTools_MapOfShape visitedShapes; SMESH_MesherHelper helper (*_mesh); int faceID = occgeom.fmap.Extent(); _faceDescriptors.clear(); list< SMESH_subMesh* >::const_iterator smIt, smEnd = meshedSM.end(); for ( smIt = meshedSM.begin(); smIt != smEnd; ++smIt ) { SMESH_subMesh* sm = *smIt; if ( !visitedShapes.Add( sm->GetSubShape() )) continue; SMESHDS_SubMesh * smDS = sm->GetSubMeshDS(); switch ( sm->GetSubShape().ShapeType() ) { case TopAbs_EDGE: { // EDGE // ---------------------- const TopoDS_Edge& geomEdge = TopoDS::Edge( sm->GetSubShape() ); // Add ng segments for each not meshed face the edge bounds TopTools_MapOfShape visitedAncestors; const TopTools_ListOfShape& ancestors = _mesh->GetAncestors( geomEdge ); TopTools_ListIteratorOfListOfShape ancestorIt ( ancestors ); for ( ; ancestorIt.More(); ancestorIt.Next() ) { const TopoDS_Shape & ans = ancestorIt.Value(); if ( ans.ShapeType() != TopAbs_FACE || !visitedAncestors.Add( ans )) continue; const TopoDS_Face& face = TopoDS::Face( ans ); int faceID = occgeom.fmap.FindIndex( face ); if ( faceID < 1 ) continue; // meshed face // find out orientation of geomEdge within face bool isForwad = false; for ( TopExp_Explorer exp( face, TopAbs_EDGE ); exp.More(); exp.Next() ) { if ( geomEdge.IsSame( exp.Current() )) { isForwad = ( exp.Current().Orientation() == geomEdge.Orientation() ); break; } } bool isQuad = smDS->GetElements()->next()->IsQuadratic(); // get all nodes from geomEdge StdMeshers_FaceSide fSide( face, geomEdge, _mesh, isForwad, isQuad ); const vector<UVPtStruct>& points = fSide.GetUVPtStruct(); int i, nbSeg = fSide.NbSegments(); double otherSeamParam = 0; helper.SetSubShape( face ); bool isSeam = helper.IsRealSeam( geomEdge ); if ( isSeam ) otherSeamParam = helper.GetOtherParam( helper.GetPeriodicIndex() == 1 ? points[0].u : points[0].v ); // add segments int prevNgId = ngNodeId( points[0].node, ngMesh, nodeNgIdMap ); for ( i = 0; i < nbSeg; ++i ) { const UVPtStruct& p1 = points[ i ]; const UVPtStruct& p2 = points[ i+1 ]; netgen::Segment seg; // ng node ids seg.pnums[0] = prevNgId; seg.pnums[1] = prevNgId = ngNodeId( p2.node, ngMesh, nodeNgIdMap ); // node param on curve seg.epgeominfo[ 0 ].dist = p1.param; seg.epgeominfo[ 1 ].dist = p2.param; // uv on face seg.epgeominfo[ 0 ].u = p1.u; seg.epgeominfo[ 0 ].v = p1.v; seg.epgeominfo[ 1 ].u = p2.u; seg.epgeominfo[ 1 ].v = p2.v; //seg.epgeominfo[ iEnd ].edgenr = edgeID; // = geom.emap.FindIndex(edge); seg.si = faceID; // = geom.fmap.FindIndex (face); seg.edgenr = ngMesh.GetNSeg() + 1; // segment id ngMesh.AddSegment (seg); if ( isSeam ) { if ( helper.GetPeriodicIndex() == 1 ) { seg.epgeominfo[ 0 ].u = otherSeamParam; seg.epgeominfo[ 1 ].u = otherSeamParam; swap (seg.epgeominfo[0].v, seg.epgeominfo[1].v); } else { seg.epgeominfo[ 0 ].v = otherSeamParam; seg.epgeominfo[ 1 ].v = otherSeamParam; swap (seg.epgeominfo[0].u, seg.epgeominfo[1].u); } swap (seg.pnums[0], seg.pnums[1]); swap (seg.epgeominfo[0].dist, seg.epgeominfo[1].dist); seg.edgenr = ngMesh.GetNSeg() + 1; // segment id ngMesh.AddSegment (seg); } } } // loop on geomEdge ancestors break; } // case TopAbs_EDGE case TopAbs_FACE: { // FACE // ---------------------- const TopoDS_Face& geomFace = TopoDS::Face( sm->GetSubShape() ); helper.SetSubShape( geomFace ); // Find solids the geomFace bounds int solidID1 = 0, solidID2 = 0; const TopTools_ListOfShape& ancestors = _mesh->GetAncestors( geomFace ); TopTools_ListIteratorOfListOfShape ancestorIt ( ancestors ); for ( ; ancestorIt.More(); ancestorIt.Next() ) { const TopoDS_Shape & solid = ancestorIt.Value(); if ( solid.ShapeType() == TopAbs_SOLID ) { int id = occgeom.somap.FindIndex ( solid ); if ( solidID1 && id != solidID1 ) solidID2 = id; else solidID1 = id; } } faceID++; _faceDescriptors[ faceID ].first = solidID1; _faceDescriptors[ faceID ].second = solidID2; // Orient the face correctly in solidID1 (issue 0020206) bool reverse = false; if ( solidID1 ) { TopoDS_Shape solid = occgeom.somap( solidID1 ); for ( TopExp_Explorer f( solid, TopAbs_FACE ); f.More(); f.Next() ) { if ( geomFace.IsSame( f.Current() )) { reverse = SMESH_Algo::IsReversedSubMesh( TopoDS::Face( f.Current()), helper.GetMeshDS() ); break; } } } // Add surface elements SMDS_ElemIteratorPtr faces = smDS->GetElements(); while ( faces->more() ) { const SMDS_MeshElement* f = faces->next(); if ( f->NbNodes() % 3 != 0 ) { // not triangle for ( ancestorIt.Initialize(ancestors); ancestorIt.More(); ancestorIt.Next() ) if ( ancestorIt.Value().ShapeType() == TopAbs_SOLID ) { sm = _mesh->GetSubMesh( ancestorIt.Value() ); break; } SMESH_ComputeErrorPtr& smError = sm->GetComputeError(); smError.reset( new SMESH_ComputeError(COMPERR_BAD_INPUT_MESH,"Not triangle submesh")); smError->myBadElements.push_back( f ); return false; } netgen::Element2d tri(3); tri.SetIndex ( faceID ); for ( int i = 0; i < 3; ++i ) { const SMDS_MeshNode* node = f->GetNode( i ), * inFaceNode=0; if ( helper.IsSeamShape( node->GetPosition()->GetShapeId() )) { if ( helper.IsSeamShape( f->GetNodeWrap( i+1 )->GetPosition()->GetShapeId() )) { inFaceNode = f->GetNodeWrap( i-1 ); } else { inFaceNode = f->GetNodeWrap( i+1 ); } } gp_XY uv = helper.GetNodeUV( geomFace, node, inFaceNode ); if ( reverse ) { tri.GeomInfoPi(3-i).u = uv.X(); tri.GeomInfoPi(3-i).v = uv.Y(); tri.PNum (3-i) = ngNodeId( node, ngMesh, nodeNgIdMap ); } else { tri.GeomInfoPi(i+1).u = uv.X(); tri.GeomInfoPi(i+1).v = uv.Y(); tri.PNum (i+1) = ngNodeId( node, ngMesh, nodeNgIdMap ); } } ngMesh.AddSurfaceElement (tri); } break; } // case TopAbs_VERTEX: { // VERTEX // -------------------------- SMDS_NodeIteratorPtr nodeIt = smDS->GetNodes(); if ( nodeIt->more() ) ngNodeId( nodeIt->next(), ngMesh, nodeNgIdMap ); break; } default:; } // switch } // loop on submeshes // fill nodeVec nodeVec.resize( ngMesh.GetNP() + 1 ); TNode2IdMap::iterator node_NgId, nodeNgIdEnd = nodeNgIdMap.end(); for ( node_NgId = nodeNgIdMap.begin(); node_NgId != nodeNgIdEnd; ++node_NgId) nodeVec[ node_NgId->second ] = (SMDS_MeshNode*) node_NgId->first; return true; }
//======================================================================= //function : CheckGProps //purpose : //======================================================================= void GEOMAlgo_GetInPlace::CheckGProps(const TopoDS_Shape& aS1) { Standard_Boolean bOnlyClosed; Standard_Integer iDim, aNbS2; Standard_Real aMass1, aMass2, aD2, aTolCG2, dM; TopAbs_ShapeEnum aType1; gp_Pnt aCG1, aCG2; TopoDS_Iterator aIt; TopoDS_Compound aC2; BRep_Builder aBB; TopTools_ListIteratorOfListOfShape aItLS; // myErrorStatus=0; // aType1=aS1.ShapeType(); if (aType1==TopAbs_COMPOUND) { aIt.Initialize(aS1); for(; aIt.More(); aIt.Next()) { const TopoDS_Shape& aS1x=aIt.Value(); CheckGProps(aS1x); if (!myFound) { return; } } } // iDim=Dimension(aType1); // if (!myImages.IsBound(aS1)) { // it should not be. return; } const TopTools_ListOfShape& aLS2=myImages.Find(aS1); aNbS2=aLS2.Extent(); if (!aNbS2) { // it should not be. return; } // aBB.MakeCompound(aC2); aItLS.Initialize(aLS2); for (; aItLS.More(); aItLS.Next()) { const TopoDS_Shape& aS2x=aItLS.Value(); aBB.Add(aC2, aS2x); } //------------------------- GProp_GProps aG1, aG2; // aTolCG2=myTolCG*myTolCG; bOnlyClosed=Standard_False; // if (iDim==0) { PointProperties(aS1, aG1); PointProperties(aC2, aG2); } else if (iDim==1) { BRepGProp::LinearProperties(aS1, aG1); BRepGProp::LinearProperties(aC2, aG2); } else if (iDim==2) { BRepGProp::SurfaceProperties(aS1, aG1); BRepGProp::SurfaceProperties(aC2, aG2); } else if (iDim==3) { BRepGProp::VolumeProperties(aS1, aG1, bOnlyClosed); BRepGProp::VolumeProperties(aC2, aG2, bOnlyClosed); } // aMass1=aG1.Mass(); aMass2=aG2.Mass(); aCG1=aG1.CentreOfMass(); aCG2=aG2.CentreOfMass(); // dM=fabs(aMass1-aMass2); if (aMass1 > myTolMass) { dM=dM/aMass1; } // aD2=aCG1.SquareDistance(aCG2); // if ((dM > myTolMass) || (aD2 > aTolCG2)) { myFound=Standard_False; return; } myFound=Standard_True; }
//======================================================================= //function : DetectVertices //purpose : //======================================================================= void GEOMAlgo_GlueDetector::DetectVertices() { Standard_Integer j, i, aNbV, aNbVSD; Standard_Real aTolV; gp_Pnt aPV; TColStd_ListIteratorOfListOfInteger aIt; TopoDS_Shape aVF; TopTools_IndexedMapOfShape aMV; TopTools_MapOfShape aMVProcessed; TopTools_ListIteratorOfListOfShape aItS; TopTools_DataMapIteratorOfDataMapOfShapeListOfShape aItIm; TopTools_DataMapOfShapeListOfShape aMVV; GEOMAlgo_IndexedDataMapOfIntegerShape aMIS; NMTDS_IndexedDataMapOfShapeBndSphere aMSB; // NMTDS_BndSphereTreeSelector aSelector; NMTDS_BndSphereTree aBBTree; NCollection_UBTreeFiller <Standard_Integer, NMTDS_BndSphere> aTreeFiller(aBBTree); // myErrorStatus=0; // TopExp::MapShapes(myArgument, TopAbs_VERTEX, aMV); aNbV=aMV.Extent(); if (!aNbV) { myErrorStatus=2; // no vertices in source shape return; } // for (i=1; i<=aNbV; ++i) { NMTDS_BndSphere aBox; // const TopoDS_Vertex& aV=*((TopoDS_Vertex*)&aMV(i)); aPV=BRep_Tool::Pnt(aV); aTolV=BRep_Tool::Tolerance(aV); // aBox.SetGap(myTolerance); aBox.SetCenter(aPV); aBox.SetRadius(aTolV); // aTreeFiller.Add(i, aBox); // aMIS.Add(i, aV); aMSB.Add(aV, aBox); } // aTreeFiller.Fill(); // //--------------------------------------------------- // Chains for (i=1; i<=aNbV; ++i) { const TopoDS_Shape& aV=aMV(i); // if (aMVProcessed.Contains(aV)) { continue; } // Standard_Integer aNbIP, aIP, aNbIP1, aIP1; TopTools_ListOfShape aLVSD; TColStd_MapOfInteger aMIP, aMIP1, aMIPC; TColStd_MapIteratorOfMapOfInteger aIt1; // aMIP.Add(i); while(1) { aNbIP=aMIP.Extent(); aIt1.Initialize(aMIP); for(; aIt1.More(); aIt1.Next()) { aIP=aIt1.Key(); if (aMIPC.Contains(aIP)) { continue; } // const TopoDS_Shape& aVP=aMIS.FindFromKey(aIP); const NMTDS_BndSphere& aBoxVP=aMSB.FindFromKey(aVP); // aSelector.Clear(); aSelector.SetBox(aBoxVP); // aNbVSD=aBBTree.Select(aSelector); if (!aNbVSD) { continue; // it shoild not be so [at least IP itself] } // const TColStd_ListOfInteger& aLI=aSelector.Indices(); aIt.Initialize(aLI); for (; aIt.More(); aIt.Next()) { aIP1=aIt.Value(); if (aMIP.Contains(aIP1)) { continue; } aMIP1.Add(aIP1); } //for (; aIt.More(); aIt.Next()) { }//for(; aIt1.More(); aIt1.Next()) { // aNbIP1=aMIP1.Extent(); if (!aNbIP1) { break; } // aIt1.Initialize(aMIP); for(; aIt1.More(); aIt1.Next()) { aIP=aIt1.Key(); aMIPC.Add(aIP); } // aMIP.Clear(); aIt1.Initialize(aMIP1); for(; aIt1.More(); aIt1.Next()) { aIP=aIt1.Key(); aMIP.Add(aIP); } aMIP1.Clear(); }// while(1) // // Fill myImages aNbIP=aMIPC.Extent(); // if (!aNbIP) {// no SD vertices is found aMVProcessed.Add(aV); continue; } //else { // SD vertices founded [ aMIPC ] aIt1.Initialize(aMIPC); for(j=0; aIt1.More(); aIt1.Next(), ++j) { aIP=aIt1.Key(); const TopoDS_Shape& aVP=aMIS.FindFromKey(aIP); if (!j) { aVF=aVP; } aLVSD.Append(aVP); aMVProcessed.Add(aVP); } //} myImages.Bind(aVF, aLVSD); }// for (i=1; i<=aNbV; ++i) { //------------------------------ // Origins aItIm.Initialize(myImages); for (; aItIm.More(); aItIm.Next()) { const TopoDS_Shape& aV=aItIm.Key(); const TopTools_ListOfShape& aLVSD=aItIm.Value(); aItS.Initialize(aLVSD); for (; aItS.More(); aItS.Next()) { const TopoDS_Shape& aVSD=aItS.Value(); if (!myOrigins.IsBound(aVSD)) { myOrigins.Bind(aVSD, aV); } } } }
//---------------------------------------------------------------- // Function: TopoDS_Shape level function to update the core Body // for any Boolean operation of the body. // Author: Jane Hu //---------------------------------------------------------------- CubitStatus OCCBody::update_OCC_entity(TopoDS_Shape& old_shape, TopoDS_Shape& new_shape, BRepBuilderAPI_MakeShape *op, LocOpe_SplitShape* sp) { //set the Shells TopTools_IndexedMapOfShape M; TopExp::MapShapes(old_shape, TopAbs_SOLID, M); TopTools_IndexedMapOfShape M_new; TopExp::MapShapes(new_shape, TopAbs_SOLID, M_new); TopTools_ListOfShape shapes; TopoDS_Shape shape; CubitBoolean updated = CUBIT_FALSE; if(!old_shape.IsNull() && old_shape.ShapeType() == TopAbs_COMPOUND && !new_shape.IsNull() && new_shape.ShapeType() == TopAbs_COMPOUND && !old_shape.IsSame(new_shape)) { //By updating underling solids, shells etc., the old_shape will get changed. //trying to make sure the the number of each entity in the old and new //shapes are the same, which means that nothing is delete, that we can //update the map here. Otherwise, when deleting solids, it'll delete the //the old body and create new body. This is Ok for general boolean operation //except imprint when booleans are called, usually the original body are // supposed to be kept. updated = CUBIT_TRUE; OCCQueryEngine::instance()->update_OCC_map(old_shape, new_shape); } DLIList<int> new_solid_nums; DLIList<int> unfound_nums; for(int ii=1; ii<=M.Extent(); ii++) { TopoDS_Solid solid = TopoDS::Solid(M(ii)); TopTools_ListOfShape shapes; if(op) { shapes.Assign(op->Modified(solid)); if(shapes.Extent() == 0) shapes.Assign(op->Generated(solid)); } else if(sp) shapes.Assign(sp->DescendantShapes(solid)); if (shapes.Extent() == 1) shape = shapes.First(); else if(shapes.Extent() > 1) { //update all attributes first. TopTools_ListIteratorOfListOfShape it; it.Initialize(shapes); for(; it.More(); it.Next()) { shape = it.Value(); OCCQueryEngine::instance()->copy_attributes(solid, shape); } shape = shapes.First(); } else if(op->IsDeleted(solid)) { if (M_new.Extent()== 1 && ii == 1) shape = M_new(1); else if(M_new.Extent()== 1 && ii > 1) shape.Nullify(); else if(M_new.Extent() > 1) { GProp_GProps myProps; BRepGProp::VolumeProperties(solid, myProps); double bf_mass = myProps.Mass(); gp_Pnt old_center = myProps.CentreOfMass(); CubitBoolean found = CUBIT_FALSE; for(int l = 1; l <= M_new.Extent(); l++) { BRepGProp::VolumeProperties(M_new(l), myProps); double af_mass = myProps.Mass(); double dTol = OCCQueryEngine::instance()->get_sme_resabs_tolerance(); if(fabs(bf_mass-af_mass) < dTol) //unchanged { gp_Pnt new_center = myProps.CentreOfMass(); if(new_center.IsEqual(old_center, dTol)) { found = CUBIT_TRUE; shape = M_new(l); new_solid_nums.append(l); break; } } } if(!found) { unfound_nums.append(ii); continue; } } else shape.Nullify(); } else { shape = solid; continue; } if(shapes.Extent() > 0 || (op && op->IsDeleted(solid))) OCCLump::update_OCC_entity(solid, shape, op, sp); } if( unfound_nums.size() == 1 ) { TopoDS_Solid solid = TopoDS::Solid(M(unfound_nums.get())); for(int kk = 1; kk <= M_new.Extent(); kk++) { if(!new_solid_nums.move_to(kk)) { shape = M_new(kk); break; } } OCCLump::update_OCC_entity(solid, shape, op, sp); } else if(unfound_nums.size() > 1) { shape.Nullify(); for(int kk = 1; kk <=unfound_nums.size(); kk++) { TopoDS_Solid solid = TopoDS::Solid(M(unfound_nums.get_and_step())); OCCLump::update_OCC_entity(solid, shape, op, sp); } } if(!old_shape.IsSame(new_shape) && !updated) OCCQueryEngine::instance()->update_OCC_map(old_shape, new_shape); return CUBIT_SUCCESS; }
//======================================================================= // function: Perform // purpose: //======================================================================= void GEOMAlgo_WireSplitter::Perform() { myErrorStatus=2; myNothingToDo=Standard_True; Standard_Integer index, i, aNb, aCntIn, aCntOut; Standard_Boolean anIsIn; Standard_Real anAngle; BOP_ListOfEdgeInfo emptyInfo; TopTools_ListIteratorOfListOfShape anItList; // // 1.Filling mySmartMap mySmartMap.Clear(); anItList.Initialize(myEdges); for (; anItList.More(); anItList.Next()) { const TopoDS_Edge& anEdge = TopoDS::Edge(anItList.Value()); // if (!BOPTools_Tools2D::HasCurveOnSurface (anEdge, myFace)) { continue; } // TopExp_Explorer anExpVerts (anEdge, TopAbs_VERTEX); for (; anExpVerts.More(); anExpVerts.Next()) { const TopoDS_Shape& aVertex= anExpVerts.Current(); index = mySmartMap.FindIndex(aVertex); if (!index) { index=mySmartMap.Add(aVertex, emptyInfo); } BOP_ListOfEdgeInfo& aListOfEInfo=mySmartMap(index); BOP_EdgeInfo aEInfo; aEInfo.SetEdge(anEdge); TopAbs_Orientation anOr=aVertex.Orientation(); if (anOr==TopAbs_FORWARD) { aEInfo.SetInFlag(Standard_False); } else if (anOr==TopAbs_REVERSED) { aEInfo.SetInFlag(Standard_True); } aListOfEInfo.Append(aEInfo); } } // aNb=mySmartMap.Extent(); // // 2. myNothingToDo myNothingToDo=Standard_True; for (i=1; i<=aNb; i++) { aCntIn=0; aCntOut=0; const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i); BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo); for (; anIt.More(); anIt.Next()) { const BOP_EdgeInfo& anEdgeInfo=anIt.Value(); anIsIn=anEdgeInfo.IsIn(); if (anIsIn) { aCntIn++; } else { aCntOut++; } } if (aCntIn!=1 || aCntOut!=1) { myNothingToDo=Standard_False; break; } } // // Each vertex has one edge In and one - Out. Good. But it is not enought // to consider that nothing to do with this. We must check edges on TShape // coinsidence. If there are such edges there is something to do with. // if (myNothingToDo) { Standard_Integer aNbE, aNbMapEE; TopTools_IndexedDataMapOfShapeListOfShape aMapEE; aNbE=myEdges.Extent(); anItList.Initialize(myEdges); for (; anItList.More(); anItList.Next()) { const TopoDS_Shape& aE = anItList.Value(); if (!aMapEE.Contains(aE)) { TopTools_ListOfShape aLEx; aLEx.Append(aE); aMapEE.Add(aE, aLEx); } else { TopTools_ListOfShape& aLEx=aMapEE.ChangeFromKey(aE); aLEx.Append(aE); } } Standard_Boolean bFlag; bFlag=Standard_True; aNbMapEE=aMapEE.Extent(); for (i=1; i<=aNbMapEE; i++) { const TopTools_ListOfShape& aLEx=aMapEE(i); aNbE=aLEx.Extent(); if (aNbE==1) { // usual case continue; } else if (aNbE==2){ const TopoDS_Shape& aE1=aLEx.First(); const TopoDS_Shape& aE2=aLEx.Last(); if (aE1.IsSame(aE2)) { bFlag=Standard_False; break; } } else { bFlag=Standard_False; break; } } myNothingToDo=myNothingToDo && bFlag; } // // if (myNothingToDo) { myErrorStatus=0; return; } // // 3. Angles in mySmartMap BRepAdaptor_Surface aBAS(myFace); const GeomAdaptor_Surface& aGAS=aBAS.Surface(); for (i=1; i<=aNb; i++) { const TopoDS_Vertex& aV=TopoDS::Vertex (mySmartMap.FindKey(i)); const BOP_ListOfEdgeInfo& aLEInfo= mySmartMap(i); BOP_ListIteratorOfListOfEdgeInfo anIt(aLEInfo); for (; anIt.More(); anIt.Next()) { BOP_EdgeInfo& anEdgeInfo=anIt.Value(); const TopoDS_Edge& aE=anEdgeInfo.Edge(); // TopoDS_Vertex aVV=aV; // anIsIn=anEdgeInfo.IsIn(); if (anIsIn) { // aVV.Orientation(TopAbs_REVERSED); anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_True); } // else { // OUT // aVV.Orientation(TopAbs_FORWARD); anAngle=Angle2D (aVV, aE, myFace, aGAS, Standard_False); } anEdgeInfo.SetAngle(anAngle); } } // // 4. Do // Standard_Boolean anIsOut, anIsNotPassed; TopTools_SequenceOfShape aLS, aVertVa; TColgp_SequenceOfPnt2d aCoordVa; BOP_ListIteratorOfListOfEdgeInfo anIt; for (i=1; i<=aNb; i++) { const TopoDS_Vertex aVa=TopoDS::Vertex (mySmartMap.FindKey(i)); const BOP_ListOfEdgeInfo& aLEInfo=mySmartMap(i); anIt.Initialize(aLEInfo); for (; anIt.More(); anIt.Next()) { BOP_EdgeInfo& anEdgeInfo=anIt.Value(); const TopoDS_Edge& aEOuta=anEdgeInfo.Edge(); anIsOut=!anEdgeInfo.IsIn(); anIsNotPassed=!anEdgeInfo.Passed(); if (anIsOut && anIsNotPassed) { // aLS.Clear(); aVertVa.Clear(); aCoordVa.Clear(); // Path(aGAS, myFace, aVa, aEOuta, anEdgeInfo, aLS, aVertVa, aCoordVa, myShapes, mySmartMap); } } } // { Standard_Integer aNbV, aNbE; TopoDS_Vertex aV1, aV2; BOPTColStd_ListOfListOfShape aShapes; BOPTColStd_ListIteratorOfListOfListOfShape anItW(myShapes); for (; anItW.More(); anItW.Next()) { TopTools_IndexedMapOfShape aMV, aME; const TopTools_ListOfShape& aLE=anItW.Value(); TopTools_ListIteratorOfListOfShape anItE(aLE); for (; anItE.More(); anItE.Next()) { const TopoDS_Edge& aE=TopoDS::Edge(anItE.Value()); aME.Add(aE); TopExp::Vertices(aE, aV1, aV2); aMV.Add(aV1); aMV.Add(aV2); } aNbV=aMV.Extent(); aNbE=aME.Extent(); if (aNbV<=aNbE) { aShapes.Append(aLE); } } // myShapes.Clear(); anItW.Initialize(aShapes); for (; anItW.More(); anItW.Next()) { const TopTools_ListOfShape& aLE=anItW.Value(); myShapes.Append(aLE); } } // myErrorStatus=0; }
//======================================================================= //function : Perform //purpose : //======================================================================= void Partition_Loop::Perform() { TopTools_DataMapOfShapeListOfShape MVE; TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Mapit, Mapit1; TopTools_ListIteratorOfListOfShape itl; TopoDS_Vertex V1,V2; //----------------------------------- // Construction map vertex => edges //----------------------------------- for (itl.Initialize(myConstEdges); itl.More(); itl.Next()) { TopoDS_Edge& E = TopoDS::Edge(itl.Value()); StoreInMVE(myFace,E,MVE); } //---------------------------------------------- // Construction of all the wires and of all the new faces. //---------------------------------------------- TopTools_MapOfOrientedShape UsedEdges; while (!MVE.IsEmpty()) { TopoDS_Vertex VF,CV; TopoDS_Edge CE,NE,EF; TopoDS_Wire NW; BRep_Builder B; Standard_Boolean End= Standard_False; B.MakeWire(NW); //-------------------------------- // EF first edge. //-------------------------------- Mapit.Initialize(MVE); EF = CE = TopoDS::Edge(Mapit.Value().First()); TopExp::Vertices(CE,V1,V2); //-------------------------------- // VF first vertex //-------------------------------- if (CE.Orientation() == TopAbs_FORWARD) { CV = VF = V1; } else { CV = VF = V2; } if (!MVE.IsBound(CV)) continue; for ( itl.Initialize(MVE(CV)); itl.More(); itl.Next()) { if (itl.Value().IsEqual(CE)) { MVE(CV).Remove(itl); break; } } int i = 0; while (!End) { //------------------------------- // Construction of a wire. //------------------------------- TopExp::Vertices(CE,V1,V2); if (!CV.IsSame(V1)) CV = V1; else CV = V2; B.Add (NW,CE); UsedEdges.Add(CE); //-------------- // stop test //-------------- if (!MVE.IsBound(CV) || MVE(CV).IsEmpty() || CV.IsSame(VF) ) { if (CV.IsSame(VF)) { if (MVE(CV).Extent() == 1 ) MVE.UnBind(CV); else { for ( itl.Initialize(MVE(CV)); itl.More(); itl.Next()) { if (itl.Value().IsEqual(CE)) { MVE(CV).Remove(itl); break; } } } } End=Standard_True; } //-------------- // select edge //-------------- else { Standard_Boolean find = SelectEdge(myFace,CE,CV,NE,MVE(CV)); if (find) { CE=NE; if (MVE(CV).IsEmpty()) MVE.UnBind(CV); if (CE.IsNull() ) { MESSAGE ( " CE is NULL !!! " ) End=Standard_True; } } else { MESSAGE ( " edge doesn't exist " ) End=Standard_True; } } } //----------------------------- // Test if the wire is closed //----------------------------- if (VF.IsSame(CV) && SamePnt2d(VF,EF,CE,myFace)) { } else{ MESSAGE ( "wire not closed" ) } myNewWires.Append (NW); } PurgeNewEdges(myConstEdges,UsedEdges); }
//======================================================================= //function : SelectEdge //purpose : Find the edge <NE> connected <CE> by the vertex <CV> in the list <LE>. // <NE> Is erased of the list. If <CE> is too in the list <LE> // with the same orientation, it's erased of the list //======================================================================= static Standard_Boolean SelectEdge(const TopoDS_Face& F, const TopoDS_Edge& CE, const TopoDS_Vertex& CV, TopoDS_Edge& NE, TopTools_ListOfShape& LE) { TopTools_ListIteratorOfListOfShape itl; NE.Nullify(); for ( itl.Initialize(LE); itl.More(); itl.Next()) { if (itl.Value().IsEqual(CE)) { LE.Remove(itl); break; } } if (LE.Extent() > 1) { //-------------------------------------------------------------- // Several possible edges. // - Test the edges differents of CE //-------------------------------------------------------------- Standard_Real cf, cl, f, l; TopoDS_Face FForward = F; Handle(Geom2d_Curve) Cc, C; FForward.Orientation(TopAbs_FORWARD); Cc = BRep_Tool::CurveOnSurface(CE,FForward,cf,cl); Standard_Real dist,distmin = 100*BRep_Tool::Tolerance(CV); Standard_Real uc,u; if (CE.Orientation () == TopAbs_FORWARD) uc = cl; else uc = cf; gp_Pnt2d P2,PV = Cc->Value(uc); Standard_Real delta = FindDelta(LE,FForward); for ( itl.Initialize(LE); itl.More(); itl.Next()) { const TopoDS_Edge& E = TopoDS::Edge(itl.Value()); if (!E.IsSame(CE)) { C = BRep_Tool::CurveOnSurface(E,FForward,f,l); if (E.Orientation () == TopAbs_FORWARD) u = f; else u = l; P2 = C->Value(u); dist = PV.Distance(P2); if (dist <= distmin){ distmin = dist; } } } Standard_Real anglemax = - PI; TopoDS_Edge SelectedEdge; for ( itl.Initialize(LE); itl.More(); itl.Next()) { const TopoDS_Edge& E = TopoDS::Edge(itl.Value()); if (!E.IsSame(CE)) { C = BRep_Tool::CurveOnSurface(E,FForward,f,l); if (E.Orientation () == TopAbs_FORWARD) u = f; else u = l; P2 = C->Value(u); dist = PV.Distance(P2); if (dist <= distmin + (1./3)*delta){ gp_Pnt2d PC, P; gp_Vec2d CTg1, CTg2, Tg1, Tg2; Cc->D2(uc, PC, CTg1, CTg2); C->D2(u, P, Tg1, Tg2); Standard_Real angle; if (CE.Orientation () == TopAbs_REVERSED && E.Orientation () == TopAbs_FORWARD) { angle = CTg1.Angle(Tg1.Reversed()); } else if (CE.Orientation () == TopAbs_FORWARD && E.Orientation () == TopAbs_REVERSED) { angle = (CTg1.Reversed()).Angle(Tg1); } else if (CE.Orientation () == TopAbs_REVERSED && E.Orientation () == TopAbs_REVERSED) { angle = CTg1.Angle(Tg1); } else if (CE.Orientation () == TopAbs_FORWARD && E.Orientation () == TopAbs_FORWARD) { angle = (CTg1.Reversed()).Angle(Tg1.Reversed()); } if (angle >= anglemax) { anglemax = angle ; SelectedEdge = E; } } } } for ( itl.Initialize(LE); itl.More(); itl.Next()) { const TopoDS_Edge& E = TopoDS::Edge(itl.Value()); if (E.IsEqual(SelectedEdge)) { NE = TopoDS::Edge(E); LE.Remove(itl); break; } } } else if (LE.Extent() == 1) { NE = TopoDS::Edge(LE.First()); LE.RemoveFirst(); } else { return Standard_False; } return Standard_True; }
//======================================================================= //function : PerformLoops //purpose : //======================================================================= void GEOMAlgo_BuilderFace::PerformLoops() { myErrorStatus=0; // Standard_Boolean bFlag; Standard_Integer aNbEA; TopTools_ListIteratorOfListOfShape aIt; TopTools_MapIteratorOfMapOfOrientedShape aItM; TopTools_IndexedDataMapOfShapeListOfShape aVEMap; TopTools_MapOfOrientedShape aMAdded; TopoDS_Iterator aItW; BRep_Builder aBB; GEOMAlgo_WireEdgeSet aWES; GEOMAlgo_WESCorrector aWESCor; // // 1. Usual Wires myLoops.Clear(); aWES.SetFace(myFace); // aIt.Initialize (myShapes); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aE=aIt.Value(); if (!myShapesToAvoid.Contains(aE)) { aWES.AddStartElement(aE); } } // aWESCor.SetWES(aWES); aWESCor.Perform(); // GEOMAlgo_WireEdgeSet& aWESN=aWESCor.NewWES(); const TopTools_ListOfShape& aLW=aWESN.Shapes(); // aIt.Initialize (aLW); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aW=aIt.Value(); myLoops.Append(aW); } //modified by NIZNHY-PKV Tue Aug 5 15:09:29 2008f // Post Treatment TopTools_MapOfOrientedShape aMEP; // // a. collect all edges that are in loops aIt.Initialize (myLoops); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aW=aIt.Value(); aItW.Initialize(aW); for (; aItW.More(); aItW.Next()) { const TopoDS_Shape& aE=aItW.Value(); aMEP.Add(aE); } } // // b. collect all edges that are to avoid aItM.Initialize(myShapesToAvoid); for (; aItM.More(); aItM.Next()) { const TopoDS_Shape& aE=aItM.Key(); aMEP.Add(aE); } // // c. add all edges that are not processed to myShapesToAvoid aIt.Initialize (myShapes); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aE=aIt.Value(); if (!aMEP.Contains(aE)) { myShapesToAvoid.Add(aE); } } //modified by NIZNHY-PKV Tue Aug 5 15:09:35 2008t // // 2. Internal Wires myLoopsInternal.Clear(); // aNbEA=myShapesToAvoid.Extent(); aItM.Initialize(myShapesToAvoid); for (; aItM.More(); aItM.Next()) { const TopoDS_Shape& aEE=aItM.Key(); TopExp::MapShapesAndAncestors(aEE, TopAbs_VERTEX, TopAbs_EDGE, aVEMap); } // bFlag=Standard_True; aItM.Initialize(myShapesToAvoid); for (; aItM.More()&&bFlag; aItM.Next()) { const TopoDS_Shape& aEE=aItM.Key(); if (!aMAdded.Add(aEE)) { continue; } // // make new wire TopoDS_Wire aW; aBB.MakeWire(aW); aBB.Add(aW, aEE); // aItW.Initialize(aW); for (; aItW.More()&&bFlag; aItW.Next()) { const TopoDS_Edge& aE=TopoDS::Edge(aItW.Value()); // TopoDS_Iterator aItE(aE); for (; aItE.More()&&bFlag; aItE.Next()) { const TopoDS_Vertex& aV = TopoDS::Vertex(aItE.Value()); const TopTools_ListOfShape& aLE=aVEMap.FindFromKey(aV); aIt.Initialize(aLE); for (; aIt.More()&&bFlag; aIt.Next()) { const TopoDS_Shape& aEx=aIt.Value(); if (aMAdded.Add(aEx)) { aBB.Add(aW, aEx); if(aMAdded.Extent()==aNbEA) { bFlag=!bFlag; } } }//for (; aIt.More(); aIt.Next()) { }//for (; aItE.More(); aItE.Next()) { }//for (; aItW.More(); aItW.Next()) { myLoopsInternal.Append(aW); }//for (; aItM.More(); aItM.Next()) { }
//======================================================================= // function: BuildSplitFaces // purpose: //======================================================================= void GEOMAlgo_Builder::BuildSplitFaces() { const NMTDS_ShapesDataStructure& aDS=*myPaveFiller->DS(); NMTTools_PaveFiller* pPF=myPaveFiller; NMTDS_InterfPool* pIP=pPF->IP(); BOPTools_CArray1OfSSInterference& aFFs=pIP->SSInterferences(); IntTools_Context& aCtx= pPF->ChangeContext(); // Standard_Boolean bToReverse, bIsClosed, bIsDegenerated; Standard_Integer i, aNb, aNbF, nF; TopTools_MapOfShape aMFence; TColStd_IndexedMapOfInteger aMFP; TopExp_Explorer anExp; TopoDS_Face aFF; TopoDS_Edge aSp, aEE; TopTools_ListIteratorOfListOfShape aIt; TopAbs_Orientation anOriF, anOriE; // mySplitFaces.Clear(); // // 1. Select Faces to process (MFP) aNb=aDS.NumberOfShapesOfTheObject(); for (i=1; i<=aNb; ++i) { const TopoDS_Shape& aF=aDS.Shape(i); if (aF.ShapeType()!=TopAbs_FACE) { continue; } if (!aMFence.Add(aF)) { continue; } // if (myInParts.Contains(aF)) { aMFP.Add(i); continue; } // anExp.Init(aF, TopAbs_EDGE); for (; anExp.More(); anExp.Next()) { const TopoDS_Shape& aE=anExp.Current(); if (myImages.HasImage(aE)) { aMFP.Add(i); break; } } // //=== { Standard_Integer aNbFFs, aNbSE, j, n1, n2; // aNbFFs=aFFs.Extent(); for (j=1; j<=aNbFFs; ++j) { BOPTools_SSInterference& aFFj=aFFs(j); aFFj.Indices(n1, n2); if (!(n1==i || n2==i)) { continue; } // const TColStd_ListOfInteger& aLSE=aFFj.SharedEdges(); aNbSE=aLSE.Extent(); if (aNbSE) { aMFP.Add(i); break; } } } //=== // }// for (i=1; i<=aNb; ++i) // // 2. ProcessFaces aNbF=aMFP.Extent(); for (i=1; i<=aNbF; ++i) { nF=aMFP(i); const TopoDS_Face& aF=TopoDS::Face(aDS.Shape(nF)); anOriF=aF.Orientation(); aFF=aF; aFF.Orientation(TopAbs_FORWARD); // aMFence.Clear(); // // 2.1. Fill WES GEOMAlgo_WireEdgeSet aWES; aWES.SetFace(aFF); // // 2.1.1. Add Split parts anExp.Init(aFF, TopAbs_EDGE); for (; anExp.More(); anExp.Next()) { const TopoDS_Edge& aE=TopoDS::Edge(anExp.Current()); anOriE=aE.Orientation(); // if (!myImages.HasImage(aE)) { if (anOriE==TopAbs_INTERNAL) { aEE=aE; aEE.Orientation(TopAbs_FORWARD); aWES.AddStartElement(aEE); aEE.Orientation(TopAbs_REVERSED); aWES.AddStartElement(aEE); } else { aWES.AddStartElement(aE); } continue; } // bIsDegenerated=BRep_Tool::Degenerated(aE); bIsClosed=BRep_Tool::IsClosed(aE, aF); // const TopTools_ListOfShape& aLIE=myImages.Image(aE); aIt.Initialize(aLIE); for (; aIt.More(); aIt.Next()) { aSp=TopoDS::Edge(aIt.Value()); // if (bIsDegenerated) { aSp.Orientation(anOriE); aWES.AddStartElement(aSp); continue; } // if (anOriE==TopAbs_INTERNAL) { aSp.Orientation(TopAbs_FORWARD); aWES.AddStartElement(aSp); aSp.Orientation(TopAbs_REVERSED); aWES.AddStartElement(aSp); continue; } // if (bIsClosed){ if (aMFence.Add(aSp)) { // if (!BRep_Tool::IsClosed(aSp, aF)){ BOPTools_Tools3D::DoSplitSEAMOnFace(aSp, aF); } // aSp.Orientation(TopAbs_FORWARD); aWES.AddStartElement(aSp); aSp.Orientation(TopAbs_REVERSED); aWES.AddStartElement(aSp); } continue; }// if (aMFence.Add(aSp)) // aSp.Orientation(anOriE); bToReverse=BOPTools_Tools3D::IsSplitToReverse1(aSp, aE, aCtx); if (bToReverse) { aSp.Reverse(); } aWES.AddStartElement(aSp); }// for (; aIt.More(); aIt.Next()) { }// for (; anExp.More(); anExp.Next()) { // // 2.1.2. Add In2D Parts if (myInParts.Contains(aF)) { const TopTools_ListOfShape& aLE=myInParts.FindFromKey(aF); aIt.Initialize(aLE); for (; aIt.More(); aIt.Next()) { aSp=TopoDS::Edge(aIt.Value()); // aSp.Orientation(TopAbs_FORWARD); aWES.AddStartElement(aSp); // aSp.Orientation(TopAbs_REVERSED); aWES.AddStartElement(aSp); } } // // 2.2. Build images Faces TopTools_ListOfShape aLFR; GEOMAlgo_ShapeSet aS1, aS2; // const TopTools_ListOfShape& aSE=aWES.StartElements(); aS1.Add(aSE); aS2.Add(aFF, TopAbs_EDGE); if (aS1.IsEqual(aS2)) { aLFR.Append(aF); } else { GEOMAlgo_BuilderFace aBF; // aBF.SetFace(aFF); aBF.SetContext(aCtx); /* { TopoDS_Compound aCx; BRep_Builder aBBx; TopTools_ListIteratorOfListOfShape aItx; // aBBx.MakeCompound(aCx); aBBx.Add(aCx, aFF); aItx.Initialize(aSE); for (; aItx.More(); aItx.Next()) { TopoDS_Shape& aEx=aItx.Value(); aBBx.Add(aCx, aEx); } int a=0; } */ aBF.SetShapes(aSE); // <-DEB aBF.Perform(); // const TopTools_ListOfShape& aLF=aBF.Areas(); aIt.Initialize(aLF); for (; aIt.More(); aIt.Next()) { TopoDS_Shape& aFR=aIt.Value(); if (anOriF==TopAbs_REVERSED) { aFR.Orientation(TopAbs_REVERSED); } aLFR.Append(aFR); } } // // 2.3. Collect draft images Faces mySplitFaces.Bind(aF, aLFR); }//for (i=1; i<=aNbF; ++i) }
//======================================================================= //function : DetectShapes //purpose : //======================================================================= void GEOMAlgo_GlueDetector::DetectShapes(const TopAbs_ShapeEnum aType) { Standard_Boolean bDegenerated; Standard_Integer i, aNbF, aNbSDF, iErr; TopTools_IndexedMapOfShape aMF; TopTools_ListIteratorOfListOfShape aItLS; GEOMAlgo_PassKeyShape aPKF; GEOMAlgo_IndexedDataMapOfPassKeyShapeListOfShape aMPKLF; // myErrorStatus=0; // TopExp::MapShapes(myArgument, aType, aMF); // aNbF=aMF.Extent(); for (i=1; i<=aNbF; ++i) { const TopoDS_Shape& aS=aMF(i); // if (aType==TopAbs_FACE) { const TopoDS_Face& aF=*((TopoDS_Face*)&aS); FacePassKey(aF, aPKF); } else if (aType==TopAbs_EDGE) { const TopoDS_Edge& aE=*((TopoDS_Edge*)&aS); EdgePassKey(aE, aPKF); } // if (myErrorStatus) { return; } // if (aMPKLF.Contains(aPKF)) { TopTools_ListOfShape& aLSDF=aMPKLF.ChangeFromKey(aPKF); aLSDF.Append(aS); } else { TopTools_ListOfShape aLSDF; // aLSDF.Append(aS); aMPKLF.Add(aPKF, aLSDF); } } // check geometric coincidence if (myCheckGeometry) { iErr=GEOMAlgo_Tools::RefineSDShapes(aMPKLF, myTolerance, myContext); if (iErr) { myErrorStatus=200; return; } } // // Images/Origins aNbF=aMPKLF.Extent(); for (i=1; i<=aNbF; ++i) { const TopTools_ListOfShape& aLSDF=aMPKLF(i); aNbSDF=aLSDF.Extent(); if (!aNbSDF) { myErrorStatus=4; // it must not be } // if (aNbSDF==1) { continue; } // const TopoDS_Shape& aS1=aLSDF.First(); // if (aType==TopAbs_EDGE) { const TopoDS_Edge& aE1=*((TopoDS_Edge*)&aS1); bDegenerated=BRep_Tool::Degenerated(aE1); if (bDegenerated) { continue; } } // myImages.Bind(aS1, aLSDF); // origins aItLS.Initialize(aLSDF); for (; aItLS.More(); aItLS.Next()) { const TopoDS_Shape& aFSD=aItLS.Value(); if (!myOrigins.IsBound(aFSD)) { myOrigins.Bind(aFSD, aS1); } } }// for (i=1; i<=aNbF; ++i) }
//======================================================================= //function : FillIn3DParts //purpose : //======================================================================= void GEOMAlgo_Builder::FillIn3DParts() { myErrorStatus=0; // const NMTDS_ShapesDataStructure& aDS=*myPaveFiller->DS(); NMTTools_PaveFiller* pPF=myPaveFiller; const Handle(IntTools_Context)& aCtx= pPF->Context(); // Standard_Boolean bIsIN, bHasImage; Standard_Integer aNbS, aNbSolids, i, j, aNbFaces, aNbFP, aNbFPx, aNbFIN, aNbLIF; TopAbs_ShapeEnum aType; TopAbs_State aState; TopTools_IndexedMapOfShape aMSolids, aMS, aMFaces, aMFIN; TopTools_MapOfShape aMFDone; TopTools_IndexedDataMapOfShapeListOfShape aMEF; TopTools_ListIteratorOfListOfShape aItS; TopoDS_Iterator aIt, aItF; BRep_Builder aBB; TopoDS_Solid aSolidSp; TopoDS_Face aFP; // myDraftSolids.Clear(); // aNbS=aDS.NumberOfShapesOfTheObject(); for (i=1; i<=aNbS; ++i) { const TopoDS_Shape& aS=aDS.Shape(i); // aType=aS.ShapeType(); if (aType==TopAbs_SOLID) { // all solids from DS aMSolids.Add(aS); } else if (aType==TopAbs_FACE) { // all faces (originals from DS or theirs images) if (myImages.HasImage(aS)) { const TopTools_ListOfShape& aLS=myImages.Image(aS); aItS.Initialize(aLS); for (; aItS.More(); aItS.Next()) { const TopoDS_Shape& aFx=aItS.Value(); // if (mySameDomainShapes.Contains(aFx)) { const TopoDS_Shape& aFSDx=mySameDomainShapes.FindFromKey(aFx); aMFaces.Add(aFSDx); } else { aMFaces.Add(aFx); } } } else { if (mySameDomainShapes.Contains(aS)) { const TopoDS_Shape& aFSDx=mySameDomainShapes.FindFromKey(aS); aMFaces.Add(aFSDx); } else { aMFaces.Add(aS); } } } } // aNbFaces=aMFaces.Extent(); aNbSolids=aMSolids.Extent(); // for (i=1; i<=aNbSolids; ++i) { const TopoDS_Solid& aSolid=TopoDS::Solid(aMSolids(i)); aMFDone.Clear(); aMFIN.Clear(); aMEF.Clear(); // aBB.MakeSolid(aSolidSp); // TopTools_ListOfShape aLIF; // BuildDraftSolid(aSolid, aSolidSp, aLIF); aNbLIF=aLIF.Extent(); // // 1 all faces/edges from aSolid [ aMS ] bHasImage=Standard_False; aMS.Clear(); aIt.Initialize(aSolid); for (; aIt.More(); aIt.Next()) { const TopoDS_Shape& aShell=aIt.Value(); // if (myImages.HasImage(aShell)) { bHasImage=Standard_True; // const TopTools_ListOfShape& aLS=myImages.Image(aShell); aItS.Initialize(aLS); for (; aItS.More(); aItS.Next()) { const TopoDS_Shape& aSx=aItS.Value(); aMS.Add(aSx); TopExp::MapShapes(aSx, TopAbs_FACE, aMS); TopExp::MapShapes(aSx, TopAbs_EDGE, aMS); TopExp::MapShapesAndAncestors(aSx, TopAbs_EDGE, TopAbs_FACE, aMEF); } } else { //aMS.Add(aShell); TopExp::MapShapes(aShell, TopAbs_FACE, aMS); //modified by NIZNHY-PKV Fri Dec 03 11:18:45 2010f TopExp::MapShapes(aShell, TopAbs_EDGE, aMS); //modified by NIZNHY-PKV Fri Dec 03 11:18:51 2010t TopExp::MapShapesAndAncestors(aShell, TopAbs_EDGE, TopAbs_FACE, aMEF); } } // // 2 all faces that are not from aSolid [ aLFP1 ] Standard_Integer aNbEFP; TopTools_IndexedDataMapOfShapeListOfShape aMEFP; TopTools_ListIteratorOfListOfShape aItFP, aItEx; TopTools_MapOfShape aMFence; TopTools_ListOfShape aLFP1, aLFP2, aLFP, aLCBF, aLFIN, aLEx;//*pLFP, // // for all non-solid faces build EF map [ aMEFP ] for (j=1; j<=aNbFaces; ++j) { const TopoDS_Shape& aFace=aMFaces(j); if (!aMS.Contains(aFace)) { TopExp::MapShapesAndAncestors(aFace, TopAbs_EDGE, TopAbs_FACE, aMEFP); } } // // among all faces from aMEFP select these that have same edges // with the solid (i.e aMEF). These faces will be treated first // to prevent the usage of 3D classifier. // The full list of faces to process is aLFP1. aNbEFP=aMEFP.Extent(); for (j=1; j<=aNbEFP; ++j) { const TopoDS_Shape& aE=aMEFP.FindKey(j); // if (aMEF.Contains(aE)) { // !! const TopTools_ListOfShape& aLF=aMEFP(j); aItFP.Initialize(aLF); for (; aItFP.More(); aItFP.Next()) { const TopoDS_Shape& aF=aItFP.Value(); if (aMFence.Add(aF)) { aLFP1.Append(aF); } } } else { aLEx.Append(aE); } } // aItEx.Initialize(aLEx); for (; aItEx.More(); aItEx.Next()) { const TopoDS_Shape& aE=aItEx.Value(); const TopTools_ListOfShape& aLF=aMEFP.FindFromKey(aE); aItFP.Initialize(aLF); for (; aItFP.More(); aItFP.Next()) { const TopoDS_Shape& aF=aItFP.Value(); if (aMFence.Add(aF)) { aLFP2.Append(aF); } } } aLFP1.Append(aLFP2); //========== // // 3 Process faces aLFP1 aNbFP=aLFP1.Extent(); aItFP.Initialize(aLFP1); for (; aItFP.More(); aItFP.Next()) { const TopoDS_Shape& aSP=aItFP.Value(); if (!aMFDone.Add(aSP)) { continue; } // // first face to process aFP=TopoDS::Face(aSP); bIsIN= GEOMAlgo_Tools3D::IsInternalFace(aFP, aSolidSp, aMEF, 1.e-14, aCtx); aState=(bIsIN) ? TopAbs_IN : TopAbs_OUT; // // collect faces to process [ aFP is the first ] aLFP.Clear(); aLFP.Append(aFP); aItS.Initialize(aLFP1); for (; aItS.More(); aItS.Next()) { const TopoDS_Shape& aSk=aItS.Value(); if (!aMFDone.Contains(aSk)) { aLFP.Append(aSk); } } // // Connexity Block that spreads from aFP the Bound // or till the end of the block itself aLCBF.Clear(); GEOMAlgo_Tools3D::MakeConnexityBlock(aLFP, aMS, aLCBF); // // fill states for the Connexity Block aItS.Initialize(aLCBF); for (; aItS.More(); aItS.Next()) { const TopoDS_Shape& aSx=aItS.Value(); aMFDone.Add(aSx); if (aState==TopAbs_IN) { aMFIN.Add(aSx); } } // aNbFPx=aMFDone.Extent(); if (aNbFPx==aNbFP) { break; } }//for (; aItFP.More(); aItFP.Next()) // // faces Inside aSolid aLFIN.Clear(); aNbFIN=aMFIN.Extent(); if (aNbFIN || aNbLIF) { for (j=1; j<=aNbFIN; ++j) { const TopoDS_Shape& aFIN=aMFIN(j); aLFIN.Append(aFIN); } // aItS.Initialize(aLIF); for (; aItS.More(); aItS.Next()) { const TopoDS_Shape& aFIN=aItS.Value(); aLFIN.Append(aFIN); } // myInParts.Add(aSolid, aLFIN); } if (aNbFIN || bHasImage) { myDraftSolids.Add(aSolid, aSolidSp); } }//for (i=1; i<=aNbSolids; ++i) { // next solid }
App::DocumentObjectExecReturn *Sweep::execute(void) { if (Sections.getSize() == 0) return new App::DocumentObjectExecReturn("No sections linked."); App::DocumentObject* spine = Spine.getValue(); if (!(spine && spine->getTypeId().isDerivedFrom(Part::Feature::getClassTypeId()))) return new App::DocumentObjectExecReturn("No spine linked."); const std::vector<std::string>& subedge = Spine.getSubValues(); TopoDS_Shape path; const Part::TopoShape& shape = static_cast<Part::Feature*>(spine)->Shape.getValue(); if (!shape._Shape.IsNull()) { try { if (!subedge.empty()) { BRepBuilderAPI_MakeWire mkWire; for (std::vector<std::string>::const_iterator it = subedge.begin(); it != subedge.end(); ++it) { TopoDS_Shape subshape = shape.getSubShape(it->c_str()); mkWire.Add(TopoDS::Edge(subshape)); } path = mkWire.Wire(); } else if (shape._Shape.ShapeType() == TopAbs_EDGE) { path = shape._Shape; } else if (shape._Shape.ShapeType() == TopAbs_WIRE) { BRepBuilderAPI_MakeWire mkWire(TopoDS::Wire(shape._Shape)); path = mkWire.Wire(); } else if (shape._Shape.ShapeType() == TopAbs_COMPOUND) { TopoDS_Iterator it(shape._Shape); for (; it.More(); it.Next()) { if (it.Value().IsNull()) return new App::DocumentObjectExecReturn("In valid element in spine."); if ((it.Value().ShapeType() != TopAbs_EDGE) && (it.Value().ShapeType() != TopAbs_WIRE)) { return new App::DocumentObjectExecReturn("Element in spine is neither an edge nor a wire."); } } Handle(TopTools_HSequenceOfShape) hEdges = new TopTools_HSequenceOfShape(); Handle(TopTools_HSequenceOfShape) hWires = new TopTools_HSequenceOfShape(); for (TopExp_Explorer xp(shape._Shape, TopAbs_EDGE); xp.More(); xp.Next()) hEdges->Append(xp.Current()); ShapeAnalysis_FreeBounds::ConnectEdgesToWires(hEdges, Precision::Confusion(), Standard_True, hWires); int len = hWires->Length(); if (len != 1) return new App::DocumentObjectExecReturn("Spine is not connected."); path = hWires->Value(1); } else { return new App::DocumentObjectExecReturn("Spine is neither an edge nor a wire."); } } catch (Standard_Failure) { return new App::DocumentObjectExecReturn("Invalid spine."); } } try { TopTools_ListOfShape profiles; const std::vector<App::DocumentObject*>& shapes = Sections.getValues(); std::vector<App::DocumentObject*>::const_iterator it; for (it = shapes.begin(); it != shapes.end(); ++it) { if (!(*it)->isDerivedFrom(Part::Feature::getClassTypeId())) return new App::DocumentObjectExecReturn("Linked object is not a shape."); TopoDS_Shape shape = static_cast<Part::Feature*>(*it)->Shape.getValue(); if (shape.IsNull()) return new App::DocumentObjectExecReturn("Linked shape is invalid."); // Extract first element of a compound if (shape.ShapeType() == TopAbs_COMPOUND) { TopoDS_Iterator it(shape); for (; it.More(); it.Next()) { if (!it.Value().IsNull()) { shape = it.Value(); break; } } } // There is a weird behaviour of BRepOffsetAPI_MakePipeShell when trying to add the wire as is. // If we re-create the wire then everything works fine. // http://forum.freecadweb.org/viewtopic.php?f=10&t=2673&sid=fbcd2ff4589f0b2f79ed899b0b990648#p20268 if (shape.ShapeType() == TopAbs_FACE) { TopoDS_Wire faceouterWire = ShapeAnalysis::OuterWire(TopoDS::Face(shape)); profiles.Append(faceouterWire); } else if (shape.ShapeType() == TopAbs_WIRE) { BRepBuilderAPI_MakeWire mkWire(TopoDS::Wire(shape)); profiles.Append(mkWire.Wire()); } else if (shape.ShapeType() == TopAbs_EDGE) { BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(shape)); profiles.Append(mkWire.Wire()); } else if (shape.ShapeType() == TopAbs_VERTEX) { profiles.Append(shape); } else { return new App::DocumentObjectExecReturn("Linked shape is not a vertex, edge, wire nor face."); } } Standard_Boolean isSolid = Solid.getValue() ? Standard_True : Standard_False; Standard_Boolean isFrenet = Frenet.getValue() ? Standard_True : Standard_False; BRepBuilderAPI_TransitionMode transMode; switch (Transition.getValue()) { case 1: transMode = BRepBuilderAPI_RightCorner; break; case 2: transMode = BRepBuilderAPI_RoundCorner; break; default: transMode = BRepBuilderAPI_Transformed; break; } if (path.ShapeType() == TopAbs_EDGE) { BRepBuilderAPI_MakeWire mkWire(TopoDS::Edge(path)); path = mkWire.Wire(); } BRepOffsetAPI_MakePipeShell mkPipeShell(TopoDS::Wire(path)); mkPipeShell.SetMode(isFrenet); mkPipeShell.SetTransitionMode(transMode); TopTools_ListIteratorOfListOfShape iter; for (iter.Initialize(profiles); iter.More(); iter.Next()) { mkPipeShell.Add(TopoDS_Shape(iter.Value())); } if (!mkPipeShell.IsReady()) Standard_Failure::Raise("shape is not ready to build"); mkPipeShell.Build(); if (isSolid) mkPipeShell.MakeSolid(); this->Shape.setValue(mkPipeShell.Shape()); return App::DocumentObject::StdReturn; } catch (Standard_Failure) { Handle_Standard_Failure e = Standard_Failure::Caught(); return new App::DocumentObjectExecReturn(e->GetMessageString()); } catch (...) { return new App::DocumentObjectExecReturn("A fatal error occurred when making the sweep"); } }