// File: TopOpeBRep_ShapeIntersector.cxx // Created: Fri May 7 17:36:28 1993 // Author: Jean Yves LEBEY // #include #include #include #include #include #ifdef DEB Standard_IMPORT Standard_Boolean TopOpeBRep_GettraceSI(); Standard_IMPORT Standard_Boolean TopOpeBRep_GetcontextFFOR(); Standard_IMPORT Standard_Integer SAVFFi1; // FacesIntersector Standard_IMPORT Standard_Integer SAVFFi2; // FacesIntersector Standard_IMPORT void TopOpeBRep_SettraceEEFF(const Standard_Boolean b); Standard_IMPORT Standard_Boolean TopOpeBRep_GettraceEEFF(const Standard_Integer e1,const Standard_Integer e2,const Standard_Integer f1,const Standard_Integer f2); void seteeff(const Standard_Boolean b,const Standard_Integer e1,const Standard_Integer e2, const Standard_Integer f1,const Standard_Integer f2) {cout<<"b,e1,e2,f1,f2 : "< #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include static Standard_Integer OneShapeIsHalfSpace(const TopoDS_Shape& S1,const TopoDS_Shape& S2); static TopoDS_Solid GetNewSolid(const TopoDS_Shape& S, TopoDS_Face& F); // modified by NIZHNY-OFV Thu Apr 18 17:16:45 2002 (F) //======================================================================= //function : TopOpeBRep_ShapeIntersector //purpose : //======================================================================= TopOpeBRep_ShapeIntersector::TopOpeBRep_ShapeIntersector() { Reset(); myFFIntersector.GetTolerances(myTol1,myTol2); myHBoxTool = FBOX_GetHBoxTool(); myFaceScanner.ChangeBoxSort().SetHBoxTool(myHBoxTool); myEdgeScanner.ChangeBoxSort().SetHBoxTool(myHBoxTool); } //======================================================================= //function : Reset //purpose : //======================================================================= void TopOpeBRep_ShapeIntersector::Reset() { myIntersectionDone = Standard_False; myFFDone = Standard_False; myFFSameDomain = Standard_False; myEEFFDone = Standard_False; myEFDone = Standard_False; myFEDone = Standard_False; myEEDone = Standard_False; myFFInit = Standard_False; myEEFFInit = Standard_False; myEFInit = Standard_False; myFEInit = Standard_False; myEEInit = Standard_False; } //======================================================================= //function : Init //purpose : //======================================================================= void TopOpeBRep_ShapeIntersector::Init (const TopoDS_Shape& S1, const TopoDS_Shape& S2) { Reset(); myShape1 = S1; myShape2 = S2; } //======================================================================= //function : SetIntersectionDone //purpose : //======================================================================= void TopOpeBRep_ShapeIntersector::SetIntersectionDone() { myIntersectionDone = (myFFDone || myEEFFDone || myFEDone || myEFDone || myEEDone); } //======================================================================= //function : CurrentGeomShape //purpose : //======================================================================= const TopoDS_Shape& TopOpeBRep_ShapeIntersector::CurrentGeomShape (const Standard_Integer Index) const { if ( myIntersectionDone ) { if (myFFDone) { if ( Index == 1 ) return myFaceScanner.Current(); else if ( Index == 2 ) return myFaceExplorer.Current(); } else if (myEEFFDone) { if ( Index == 1 ) return myEdgeScanner.Current(); else if ( Index == 2 ) return myEdgeExplorer.Current(); } else if (myFEDone) { if ( Index == 1 ) return myFaceScanner.Current(); else if ( Index == 2 ) return myEdgeExplorer.Current(); } else if (myEFDone) { if ( Index == 1 ) return myEdgeScanner.Current(); else if ( Index == 2 ) return myFaceExplorer.Current(); } else if (myEEDone) { if ( Index == 1 ) return myEdgeScanner.Current(); else if ( Index == 2 ) return myEdgeExplorer.Current(); } } Standard_Failure::Raise("CurrentGeomShape : no intersection"); TopoDS_Shape* bid = new TopoDS_Shape(); return *bid; } //modified by NIZNHY-PKV Fri Sep 24 11:02:59 1999 from //======================================================================= //function : RejectedFaces //purpose : //======================================================================= void TopOpeBRep_ShapeIntersector::RejectedFaces (const TopoDS_Shape& anObj, const TopoDS_Shape& aReference, TopTools_ListOfShape& aListOfShape) { Standard_Integer isHalfSpace = OneShapeIsHalfSpace( anObj, aReference ); if( isHalfSpace != 0 ) { TopoDS_Face newRejectFace; TopoDS_Solid newSolid; aListOfShape.Clear(); if( isHalfSpace == 1 ) { newSolid = GetNewSolid( anObj, newRejectFace ); Init( newSolid, aReference ); TopAbs_ShapeEnum tscann = TopAbs_SOLID; TopAbs_ShapeEnum texplo = TopAbs_FACE; myFaceScanner.Clear(); myFaceScanner.AddBoxesMakeCOB( aReference, tscann ); myFaceExplorer.Init( newSolid, texplo ); for(; myFaceExplorer.More(); myFaceExplorer.Next()) { TopOpeBRepTool_BoxSort& aBS = myFaceScanner.ChangeBoxSort(); if(!aBS.Compare(myFaceExplorer.Current()).More()) { const TopoDS_Shape& aS=myFaceExplorer.Current(); aListOfShape.Append (aS); } } texplo = TopAbs_EDGE; myFaceScanner.Clear(); myFaceScanner.AddBoxesMakeCOB( aReference, tscann ); myFaceExplorer.Init( newSolid, texplo ); for(; myFaceExplorer.More(); myFaceExplorer.Next()) { TopOpeBRepTool_BoxSort& aBS = myFaceScanner.ChangeBoxSort(); if(!aBS.Compare(myFaceExplorer.Current()).More()) { const TopoDS_Shape& aS=myFaceExplorer.Current(); aListOfShape.Append (aS); } } } else { newSolid = GetNewSolid( aReference, newRejectFace ); Init( anObj, newSolid ); TopAbs_ShapeEnum tscann = TopAbs_SOLID; TopAbs_ShapeEnum texplo = TopAbs_FACE; myFaceScanner.Clear(); myFaceScanner.AddBoxesMakeCOB( newSolid, tscann ); myFaceExplorer.Init( anObj, texplo); for(; myFaceExplorer.More(); myFaceExplorer.Next()) { TopOpeBRepTool_BoxSort& aBS = myFaceScanner.ChangeBoxSort(); if(!aBS.Compare(myFaceExplorer.Current()).More()) { const TopoDS_Shape& aS=myFaceExplorer.Current(); aListOfShape.Append (aS); } } texplo = TopAbs_EDGE; myFaceScanner.Clear(); myFaceScanner.AddBoxesMakeCOB( newSolid, tscann ); myFaceExplorer.Init( anObj, texplo ); for(; myFaceExplorer.More(); myFaceExplorer.Next()) { TopOpeBRepTool_BoxSort& aBS = myFaceScanner.ChangeBoxSort(); if(!aBS.Compare(myFaceExplorer.Current()).More()) { const TopoDS_Shape& aS=myFaceExplorer.Current(); aListOfShape.Append (aS); } } } // remove all shapes of < newRejectFace > from list TopExp_Explorer ExpRF(newRejectFace, TopAbs_EDGE); for(; ExpRF.More(); ExpRF.Next() ) { const TopoDS_Edge& edgef = TopoDS::Edge( ExpRF.Current() ); TopTools_ListIteratorOfListOfShape it( aListOfShape ); for(; it.More(); it.Next() ) { const TopoDS_Shape& shape = it.Value(); if( shape.ShapeType() != TopAbs_EDGE ) continue; const TopoDS_Edge& edgel = TopoDS::Edge( shape ); if( edgef.IsSame( edgel ) ) { aListOfShape.Remove(it); break; } } } TopTools_ListIteratorOfListOfShape it( aListOfShape ); for(; it.More(); it.Next() ) { const TopoDS_Shape& shape = it.Value(); if( shape.ShapeType() != TopAbs_FACE ) continue; const TopoDS_Face& facel = TopoDS::Face( shape ); if( facel.IsSame( newRejectFace ) ) { aListOfShape.Remove(it); break; } } Init(anObj, aReference); return; } Init(anObj, aReference); aListOfShape.Clear(); //find faces to reject TopAbs_ShapeEnum tscann = TopAbs_SOLID; TopAbs_ShapeEnum texplo = TopAbs_FACE; myFaceScanner.Clear(); myFaceScanner.AddBoxesMakeCOB(aReference,tscann); myFaceExplorer.Init(anObj,texplo); for(; myFaceExplorer.More(); myFaceExplorer.Next()) { TopOpeBRepTool_BoxSort& aBS = myFaceScanner.ChangeBoxSort(); if(!aBS.Compare(myFaceExplorer.Current()).More()) { const TopoDS_Shape& aS=myFaceExplorer.Current(); aListOfShape.Append (aS); } } //modified by NIZHNY-MZV Wed Apr 5 09:45:17 2000 texplo = TopAbs_EDGE; myFaceScanner.Clear(); myFaceScanner.AddBoxesMakeCOB(aReference,tscann); myFaceExplorer.Init(anObj,texplo); for(; myFaceExplorer.More(); myFaceExplorer.Next()) { TopOpeBRepTool_BoxSort& aBS = myFaceScanner.ChangeBoxSort(); if(!aBS.Compare(myFaceExplorer.Current()).More()) { const TopoDS_Shape& aS=myFaceExplorer.Current(); aListOfShape.Append (aS); } } //modified by NIZHNY-MZV Wed Apr 5 09:45:17 2000 /* texplo = TopAbs_VERTEX; myFaceScanner.Clear(); myFaceScanner.AddBoxesMakeCOB(aReference,tscann); myFaceExplorer.Init(anObj,texplo); for(; myFaceExplorer.More(); myFaceExplorer.Next()) { TopOpeBRepTool_BoxSort& aBS = myFaceScanner.ChangeBoxSort(); if(!aBS.Compare(myFaceExplorer.Current()).More()) { const TopoDS_Shape& aS=myFaceExplorer.Current(); aListOfShape.Append (aS); } } */ } //modified by NIZNHY-PKV Fri Sep 24 11:03:02 1999 to //======================================================================= //function : InitIntersection //purpose : //======================================================================= void TopOpeBRep_ShapeIntersector::InitIntersection (const TopoDS_Shape& S1, const TopoDS_Shape& S2) { Init(S1,S2); InitFFIntersection(); if ( MoreFFCouple() ) return; InitFEIntersection(); if ( MoreFECouple() ) return; InitEFIntersection(); if ( MoreEFCouple() ) return; } //======================================================================= //function : InitIntersection //purpose : //======================================================================= void TopOpeBRep_ShapeIntersector::InitIntersection (const TopoDS_Shape& S1, const TopoDS_Shape& S2, const TopoDS_Face& F1, const TopoDS_Face& F2) { Init(S1,S2); myEEFace1 = F1; myEEFace2 = F2; InitEEIntersection(); } //======================================================================= //function : MoreIntersection //purpose : //======================================================================= Standard_Boolean TopOpeBRep_ShapeIntersector::MoreIntersection() const { Standard_Boolean res = myIntersectionDone; #ifdef DEB if (TopOpeBRep_GettraceSI() && res) { if ( myFFDone ) cout<<"FF : "; else if ( myEEFFDone ) cout<<" EE : "; DumpCurrent(1); DumpCurrent(2); if ( myFFDone && myFFSameDomain ) cout<<"(FF SameDomain)"; else if ( myEEFFDone ) cout<<"(EE of FF SameDomain)"; else if ( myEEDone ) cout<<"EE : "; cout<= 2) || (NbFacesSol2 == 1 && NbFacesSol1 >= 2) ) { // if one solid has shell consisted of only a face but other one has valid closed // shell we can detect current boolean operation as operation with half space object. // if shell of second solid is not valid too we cann't detect what kind of objects // we try to perform. in this case we do nothing and just return. // but before we must avoid shperes, toruses and solids with a face biult on spherical surfaces // of revolution (SSRFS) - solids with shell of one face: // sphere (U: 0, 2PI) (V: -PI/2, PI/2), // torus (U: 0, 2PI) (V: 0, 2PI). // SSRFS (U period = (PI), 2PI) (V period = (PI), 2PI) // these solids are not halfspaces. TopExp_Explorer SolidExplorer; TopoDS_Face testFace; if( NbFacesSol1 == 1 ) { for( SolidExplorer.Init(S1, TopAbs_FACE); SolidExplorer.More(); SolidExplorer.Next() ) testFace = TopoDS::Face( SolidExplorer.Current() ); } else { for( SolidExplorer.Init(S2, TopAbs_FACE); SolidExplorer.More(); SolidExplorer.Next() ) testFace = TopoDS::Face( SolidExplorer.Current() ); } BRepAdaptor_Surface FSurf( testFace ); Standard_Boolean SolidIsSphereOrTorus = Standard_False; if( FSurf.GetType() == GeomAbs_Sphere || FSurf.GetType() == GeomAbs_Torus ) { Standard_Real minU = FSurf.FirstUParameter(); Standard_Real maxU = FSurf.LastUParameter(); Standard_Real minV = FSurf.FirstVParameter(); Standard_Real maxV = FSurf.LastVParameter(); Standard_Boolean yesU = ( Abs(minU - 0.) < 1.e-9 && Abs(maxU - 2*PI) < 1.e-9 ); Standard_Boolean yesV = ( FSurf.GetType() == GeomAbs_Sphere ) ? ( Abs(minV - (-PI/2.)) < 1.e-9 && Abs(maxV - PI/2.) < 1.e-9 ) : ( Abs(minV - 0.) < 1.e-9 && Abs(maxV - 2*PI) < 1.e-9 ); SolidIsSphereOrTorus = ( yesU && yesV ); } if( FSurf.GetType() == GeomAbs_SurfaceOfRevolution ) { Standard_Boolean areBothPeriodic = ( FSurf.IsUPeriodic() && FSurf.IsVPeriodic() ); if( areBothPeriodic ) { Standard_Boolean yesU = ( Abs(FSurf.UPeriod() - PI) < 1.e-9 || Abs(FSurf.UPeriod() - 2*PI) < 1.e-9 ); Standard_Boolean yesV = ( Abs(FSurf.VPeriod() - PI) < 1.e-9 || Abs(FSurf.VPeriod() - 2*PI) < 1.e-9 ); SolidIsSphereOrTorus = ( yesU && yesV ); } } if( SolidIsSphereOrTorus ) return result; Standard_Boolean SecondShellOk = Standard_True; TopTools_IndexedDataMapOfShapeListOfShape aMapEF; aMapEF.Clear(); Standard_Integer NbEdges = 0, NbFaces = 0, iE = 0; if( NbFacesSol1 == 1 ) TopExp::MapShapesAndAncestors(S2, TopAbs_EDGE, TopAbs_FACE, aMapEF); else TopExp::MapShapesAndAncestors(S1, TopAbs_EDGE, TopAbs_FACE, aMapEF); NbEdges = aMapEF.Extent(); for( iE = 1; iE <= NbEdges; iE++) { const TopTools_ListOfShape& listFaces = aMapEF.FindFromIndex( iE ); NbFaces = listFaces.Extent(); if( NbFaces != 2 ) { SecondShellOk = Standard_False; break; } } aMapEF.Clear(); if( SecondShellOk ) result = (NbFacesSol1 == 1) ? 1 : 2; } else { // ************************** IMPORTANT !!! ************************************ // both shells are of more than 2 faces. if both solids have invalid shells // we do nothing and just return. on the other hand if only one shell is valid // currently we should suppose that solid with invalid shell is a half space too, // but this is not always true. // // so this suggestion must be developed carefully. while we don't classify it! // ***************************************************************************** } #ifdef DEB if( result != 0 ) cout << "# one of the SOLIDs probably is a HALF SPACE" << endl; #endif } return result; } //======================================================================= //function : GetNewSolid //purpose : rebuild halfspace solid adding new "face on infinity" // to build correct bounding box to classify carefully // "rejected shapes". //======================================================================= static TopoDS_Solid GetNewSolid(const TopoDS_Shape& S, TopoDS_Face& F) { // "new solid" is a new halfspace solid consists of two faces now: the first face is a face // used to build halfspace solid and the second face is a new "face on infinity" specially // created to constuct correct bounding box around halfspace solid with bounds more wide than // previous one. // the following algorithm is used: // 1. get face used to build halfspace solid and calculate its normal, Min/Max (U,V) parameters, // four points lying on the surface of the face inside its restrictions, surface, tolerance // and location. // 2. define the direction into the halfspace solid and project four points along this direction // on infinite distance. then use those points to create "face on infinity". // 3. build new shell with two new faces and new "halfspace solid". // 4. return this solid and "face on infinity" to remove it and all its subshapes from the list // of rejected shapes. TopExp_Explorer ShapeExplorer; TopoDS_Face hsFace; for( ShapeExplorer.Init(S, TopAbs_FACE); ShapeExplorer.More(); ShapeExplorer.Next() ) hsFace = TopoDS::Face( ShapeExplorer.Current() ); BRepAdaptor_Surface ASurf( hsFace ); Standard_Real MinU = ASurf.FirstUParameter(); Standard_Real MaxU = ASurf.LastUParameter(); Standard_Real MinV = ASurf.FirstVParameter(); Standard_Real MaxV = ASurf.LastUParameter(); Standard_Real MidU = (MaxU + MinU) * 0.5; Standard_Real MidV = (MaxV + MinV) * 0.5; gp_Pnt MidP; gp_Vec SurfDU, SurfDV; ASurf.D1( MidU, MidV, MidP, SurfDU, SurfDV ); gp_Vec Normal = SurfDU.Crossed( SurfDV ); if( hsFace.Orientation() == TopAbs_FORWARD ) Normal *= -1.e+10; else Normal *= 1.e+10; Standard_Real Pu1 = MinU + Abs( (MaxU - MinU) / 4. ); Standard_Real Pu2 = MinU + Abs( (MaxU - MinU) / 4. * 3. ); Standard_Real Pv1 = MinV + Abs( (MaxV - MinV) / 4. ); Standard_Real Pv2 = MinV + Abs( (MaxV - MinV) / 4. * 3. ); gp_Pnt P1, P2, P3, P4; ASurf.D0( Pu1, Pv1, P1 ); ASurf.D0( Pu1, Pv2, P2 ); ASurf.D0( Pu2, Pv1, P3 ); ASurf.D0( Pu2, Pv2, P4 ); P1.Translate( Normal ); P2.Translate( Normal ); P3.Translate( Normal ); P4.Translate( Normal ); BRepLib_MakeEdge mke1( P1, P2 ); BRepLib_MakeEdge mke2( P2, P4 ); BRepLib_MakeEdge mke3( P4, P3 ); BRepLib_MakeEdge mke4( P3, P1 ); TopoDS_Edge e1 = mke1.Edge(); TopoDS_Edge e2 = mke2.Edge(); TopoDS_Edge e3 = mke3.Edge(); TopoDS_Edge e4 = mke4.Edge(); BRepLib_MakeWire mkw( e1, e2, e3, e4 ); TopoDS_Wire w = mkw.Wire(); BRepLib_MakeFace mkf( w ); TopoDS_Face infFace = mkf.Face(); TopoDS_Shell newShell; TopoDS_Solid newSolid; BRep_Builder newShellBuilder; newShellBuilder.MakeShell( newShell ); newShellBuilder.Add( newShell, hsFace ); newShellBuilder.Add( newShell, infFace ); BRep_Builder newSolidBuilder; newSolidBuilder.MakeSolid( newSolid ); newSolidBuilder.Add( newSolid, newShell ); F = infFace; return newSolid; }