// Created on: 1996-09-03 // Created by: Yves FRICAUD // Copyright (c) 1996-1999 Matra Datavision // Copyright (c) 1999-2014 OPEN CASCADE SAS // // This file is part of Open CASCADE Technology software library. // // This library is free software; you can redistribute it and/or modify it under // the terms of the GNU Lesser General Public License version 2.1 as published // by the Free Software Foundation, with special exception defined in the file // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT // distribution for complete text of the license and disclaimer of any warranty. // // Alternatively, this file may be used under the terms of Open CASCADE // commercial license or contractual agreement. // Modified by skv - Fri Dec 26 12:20:14 2003 OCC4455 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // #include #include // #include //======================================================================= //function : BRepOffset_Inter3d //purpose : //======================================================================= BRepOffset_Inter3d::BRepOffset_Inter3d(const Handle(BRepAlgo_AsDes)& AsDes, const TopAbs_State Side , const Standard_Real Tol) :myAsDes(AsDes), mySide(Side), myTol(Tol) { } //======================================================================= //function : ExtentEdge //purpose : //======================================================================= static void ExtentEdge(const TopoDS_Face& /*F*/, const TopoDS_Edge& E, TopoDS_Edge& NE) { TopoDS_Shape aLocalShape = E.EmptyCopied(); NE = TopoDS::Edge(aLocalShape); // NE = TopoDS::Edge(E.EmptyCopied()); // Enough for analytic edges, in general case reconstruct the // geometry of the edge recalculating the intersection of surfaces. NE.Orientation(TopAbs_FORWARD); Standard_Real f,l; BRep_Tool::Range(E,f,l); Standard_Real length = l-f; f -= 100*length; l += 100*length; BRep_Builder B; B.Range(NE,f,l); BRepAdaptor_Curve CE(E); TopoDS_Vertex V1 = BRepLib_MakeVertex(CE.Value(f)); TopoDS_Vertex V2 = BRepLib_MakeVertex(CE.Value(l)); B.Add(NE,V1.Oriented(TopAbs_FORWARD)); B.Add(NE,V2.Oriented(TopAbs_REVERSED)); NE.Orientation(E.Orientation()); } //======================================================================= //function : CompletInt //purpose : //======================================================================= void BRepOffset_Inter3d::CompletInt (const TopTools_ListOfShape& SetOfFaces, const BRepAlgo_Image& InitOffsetFace, const Message_ProgressRange& theRange) { //--------------------------------------------------------------- // Calculate the intersections of offset faces // Distinction of intersection between faces // tangents. //--------------------------------------------------------------- // Prepare tools for sorting the bounding boxes BOPTools_BoxTree aBBTree; aBBTree.SetSize (SetOfFaces.Extent()); // NCollection_IndexedDataMap aMFaces; // Construct bounding boxes for faces and add them to the tree TopTools_ListIteratorOfListOfShape aItL(SetOfFaces); for (; aItL.More(); aItL.Next()) { const TopoDS_Face& aF = TopoDS::Face(aItL.Value()); // // compute bounding box Bnd_Box aBoxF; BRepBndLib::Add(aF, aBoxF); // Standard_Integer i = aMFaces.Add (aF, aBoxF); // aBBTree.Add(i, Bnd_Tools::Bnd2BVH(aBoxF)); } // Build BVH aBBTree.Build(); // Perform selection of the pairs BOPTools_BoxPairSelector aSelector; aSelector.SetBVHSets (&aBBTree, &aBBTree); aSelector.SetSame (Standard_True); aSelector.Select(); aSelector.Sort(); // Treat the selected pairs const std::vector& aPairs = aSelector.Pairs(); const Standard_Integer aNbPairs = static_cast (aPairs.size()); Message_ProgressScope aPS(theRange, "Complete intersection", aNbPairs); for (Standard_Integer iPair = 0; iPair < aNbPairs; ++iPair, aPS.Next()) { if (!aPS.More()) { return; } const BOPTools_BoxPairSelector::PairIDs& aPair = aPairs[iPair]; const TopoDS_Face& aF1 = TopoDS::Face (aMFaces.FindKey (Min (aPair.ID1, aPair.ID2))); const TopoDS_Face& aF2 = TopoDS::Face (aMFaces.FindKey (Max (aPair.ID1, aPair.ID2))); // intersect faces FaceInter(aF1, aF2, InitOffsetFace); } } //======================================================================= //function : FaceInter //purpose : Performs intersection of the given faces //======================================================================= void BRepOffset_Inter3d::FaceInter(const TopoDS_Face& F1, const TopoDS_Face& F2, const BRepAlgo_Image& InitOffsetFace) { TopTools_ListOfShape LInt1, LInt2; TopoDS_Edge NullEdge; TopoDS_Face NullFace; if (F1.IsSame(F2)) return; if (IsDone(F1,F2)) return; const TopoDS_Shape& InitF1 = InitOffsetFace.ImageFrom(F1); const TopoDS_Shape& InitF2 = InitOffsetFace.ImageFrom(F2); if (InitF1.IsSame(InitF2)) return; Standard_Boolean InterPipes = (InitF2.ShapeType() == TopAbs_EDGE && InitF1.ShapeType() == TopAbs_EDGE ); Standard_Boolean InterFaces = (InitF1.ShapeType() == TopAbs_FACE && InitF2.ShapeType() == TopAbs_FACE); TopTools_ListOfShape LE,LV; LInt1.Clear(); LInt2.Clear(); if (BRepOffset_Tool::FindCommonShapes(F1,F2,LE,LV) || myAsDes->HasCommonDescendant(F1,F2,LE)) { //------------------------------------------------- // F1 and F2 share shapes. //------------------------------------------------- if ( LE.IsEmpty() && !LV.IsEmpty()) { if (InterPipes) { //---------------------- // tubes share a vertex. //---------------------- const TopoDS_Edge& EE1 = TopoDS::Edge(InitF1); const TopoDS_Edge& EE2 = TopoDS::Edge(InitF2); TopoDS_Vertex VE1[2],VE2[2]; TopExp::Vertices(EE1,VE1[0],VE1[1]); TopExp::Vertices(EE2,VE2[0],VE2[1]); TopoDS_Vertex V; for (Standard_Integer i = 0 ; i < 2; i++) { for (Standard_Integer j = 0 ; j < 2; j++) { if (VE1[i].IsSame(VE2[j])) { V = VE1[i]; } } } if (!InitOffsetFace.HasImage(V)) { //no sphere BRepOffset_Tool::PipeInter(F1,F2,LInt1,LInt2,mySide); } } else { //-------------------------------------------------------- // Intersection having only common vertices // and supports having common edges. // UNSUFFICIENT, but a larger criterion shakes too // many sections. //-------------------------------------------------------- if (InterFaces) { if (BRepOffset_Tool::FindCommonShapes(TopoDS::Face(InitF1), TopoDS::Face(InitF2),LE,LV)) { if (!LE.IsEmpty()) { BRepOffset_Tool::Inter3D (F1,F2,LInt1,LInt2,mySide,NullEdge,NullFace,NullFace); } } else { BRepOffset_Tool::Inter3D(F1,F2,LInt1,LInt2,mySide,NullEdge,NullFace,NullFace); } } } } } else { if (InterPipes) { BRepOffset_Tool::PipeInter(F1,F2,LInt1,LInt2,mySide); } else { BRepOffset_Tool::Inter3D (F1,F2,LInt1,LInt2,mySide,NullEdge,NullFace,NullFace); } } Store (F1,F2,LInt1,LInt2); } //======================================================================= //function : ConnexIntByArc //purpose : //======================================================================= void BRepOffset_Inter3d::ConnexIntByArc(const TopTools_ListOfShape& /*SetOfFaces*/, const TopoDS_Shape& ShapeInit, const BRepOffset_Analyse& Analyse, const BRepAlgo_Image& InitOffsetFace, const Message_ProgressRange& theRange) { ChFiDS_TypeOfConcavity OT = ChFiDS_Concave; if (mySide == TopAbs_OUT) OT = ChFiDS_Convex; TopExp_Explorer Exp(ShapeInit,TopAbs_EDGE); TopTools_ListOfShape LInt1,LInt2; TopoDS_Face F1,F2; TopoDS_Edge NullEdge; TopoDS_Face NullFace; Message_ProgressScope aPSOuter(theRange, NULL, 2); Message_ProgressScope aPSIntF(aPSOuter.Next(), "Intersecting offset faces", 1, Standard_True); //--------------------------------------------------------------------- // etape 1 : Intersection of faces // corresponding to the initial faces // separated by a concave edge if offset > 0, otherwise convex. //--------------------------------------------------------------------- for (; Exp.More(); Exp.Next(), aPSIntF.Next()) { if (!aPSIntF.More()) { return; } const TopoDS_Edge& E = TopoDS::Edge(Exp.Current()); const BRepOffset_ListOfInterval& L = Analyse.Type(E); if (!L.IsEmpty() && L.First().Type() == OT) { //----------------------------------------------------------- // edge is of the proper type , return adjacent faces. //----------------------------------------------------------- const TopTools_ListOfShape& Anc = Analyse.Ancestors(E); if (Anc.Extent() == 2) { const TopoDS_Face& InitF1 = TopoDS::Face(Anc.First()); const TopoDS_Face& InitF2 = TopoDS::Face(Anc.Last()); F1 = TopoDS::Face(InitOffsetFace.Image(InitF1).First()); F2 = TopoDS::Face(InitOffsetFace.Image(InitF2).First()); if (!IsDone(F1,F2)) { BRepOffset_Tool::Inter3D (F1,F2,LInt1,LInt2,mySide,E,InitF1,InitF2); Store (F1,F2,LInt1,LInt2); } } } } //--------------------------------------------------------------------- // etape 2 : Intersections of tubes sharing a vertex without sphere with: // - tubes on each other edge sharing the vertex // - faces containing an edge connected to vertex that has no tubes. //--------------------------------------------------------------------- TopoDS_Vertex V[2]; TopTools_ListIteratorOfListOfShape it; Message_ProgressScope aPSIntT(aPSOuter.Next(), "Intersecting tubes", 1, Standard_True); for (Exp.Init(ShapeInit,TopAbs_EDGE); Exp.More(); Exp.Next(), aPSIntT.Next()) { if (!aPSIntT.More()) { return; } const TopoDS_Edge& E1 = TopoDS::Edge(Exp.Current()); if (InitOffsetFace.HasImage(E1)) { //--------------------------- // E1 generated a tube. //--------------------------- F1 = TopoDS::Face(InitOffsetFace.Image(E1).First()); TopExp::Vertices(E1,V[0],V[1]); const TopTools_ListOfShape& AncE1 = Analyse.Ancestors(E1); for (Standard_Integer i = 0; i < 2; i++) { if (!InitOffsetFace.HasImage(V[i])) { //----------------------------- // the vertex has no sphere. //----------------------------- const TopTools_ListOfShape& Anc = Analyse.Ancestors(V[i]); TopTools_ListOfShape TangOnV; Analyse.TangentEdges(E1,V[i],TangOnV); TopTools_MapOfShape MTEV; for (it.Initialize(TangOnV); it.More(); it.Next()) { MTEV.Add(it.Value()); } for (it.Initialize(Anc); it.More(); it.Next()) { const TopoDS_Edge& E2 = TopoDS::Edge(it.Value()); // Modified by skv - Fri Jan 16 16:27:54 2004 OCC4455 Begin // if (E1.IsSame(E2) || MTEV.Contains(E2)) continue; Standard_Boolean isToSkip = Standard_False; if (!E1.IsSame(E2)) { const BRepOffset_ListOfInterval& aL = Analyse.Type(E2); isToSkip = (MTEV.Contains(E2) && (aL.IsEmpty() || (!aL.IsEmpty() && aL.First().Type() != OT))); } if (E1.IsSame(E2) || isToSkip) continue; // Modified by skv - Fri Jan 16 16:27:54 2004 OCC4455 End if (InitOffsetFace.HasImage(E2)) { //----------------------------- // E2 generated a tube. //----------------------------- F2 = TopoDS::Face(InitOffsetFace.Image(E2).First()); if (!IsDone(F1,F2)) { //--------------------------------------------------------------------- // Intersection tube/tube if the edges are not tangent (AFINIR). //---------------------------------------------------------------------- BRepOffset_Tool::PipeInter (F1,F2,LInt1,LInt2,mySide); Store (F1,F2,LInt1,LInt2); } } else { //------------------------------------------------------- // Intersection of the tube of E1 with faces // // to face containing E2 if they are not tangent // to the tube or if E2 is not a tangent edge. //------------------------------------------------------- const BRepOffset_ListOfInterval& L = Analyse.Type(E2); if (!L.IsEmpty() && L.First().Type() == ChFiDS_Tangential) { continue; } const TopTools_ListOfShape& AncE2 = Analyse.Ancestors(E2); Standard_Boolean TangentFaces = Standard_False; if (AncE2.Extent() == 2) { TopoDS_Face InitF2 = TopoDS::Face(AncE2.First ()); TangentFaces = (InitF2.IsSame(AncE1.First()) || InitF2.IsSame(AncE1.Last())); if (!TangentFaces) { F2 = TopoDS::Face(InitOffsetFace.Image(InitF2).First()); if (!IsDone(F1,F2)) { BRepOffset_Tool::Inter3D (F1,F2,LInt1,LInt2,mySide,NullEdge,NullFace,NullFace); Store (F1,F2,LInt1,LInt2); } } InitF2 = TopoDS::Face(AncE2.Last ()); TangentFaces = (InitF2.IsSame(AncE1.First()) || InitF2.IsSame(AncE1.Last())); if (!TangentFaces) { F2 = TopoDS::Face(InitOffsetFace.Image(InitF2).First()); if (!IsDone(F1,F2)) { BRepOffset_Tool::Inter3D (F1,F2,LInt1,LInt2,mySide,NullEdge,NullFace,NullFace); Store (F1,F2,LInt1,LInt2); } } } } } } } } } } //======================================================================= //function : ConnexIntByInt //purpose : //======================================================================= void BRepOffset_Inter3d::ConnexIntByInt (const TopoDS_Shape& SI, const BRepOffset_DataMapOfShapeOffset& MapSF, const BRepOffset_Analyse& Analyse, TopTools_DataMapOfShapeShape& MES, TopTools_DataMapOfShapeShape& Build, TopTools_ListOfShape& Failed, const Message_ProgressRange& theRange, const Standard_Boolean bIsPlanar) { TopTools_IndexedMapOfShape VEmap; TopoDS_Face F1,F2,OF1,OF2,NF1,NF2; TopAbs_State CurSide = mySide; BRep_Builder B; Standard_Boolean bEdge; Standard_Integer i, aNb = 0; TopTools_ListIteratorOfListOfShape it, it1, itF1, itF2; // TopExp::MapShapes (SI, TopAbs_EDGE, VEmap); // Take the vertices for treatment Message_ProgressScope aPSOuter(theRange, NULL, 10); if (bIsPlanar) { aNb = VEmap.Extent(); for (i = 1; i <= aNb; ++i) { const TopoDS_Edge& aE = TopoDS::Edge (VEmap (i)); TopoDS_Shape aFGen = Analyse.Generated (aE); if (!aFGen.IsNull()) TopExp::MapShapes (aFGen, TopAbs_EDGE, VEmap); } // Add vertices for treatment TopExp::MapShapes(SI, TopAbs_VERTEX, VEmap); for (TopTools_ListOfShape::Iterator itNF (Analyse.NewFaces()); itNF.More(); itNF.Next()) TopExp::MapShapes (itNF.Value(), TopAbs_VERTEX, VEmap); } // TopTools_DataMapOfShapeListOfShape aDMVLF1, aDMVLF2, aDMIntFF; TopTools_IndexedDataMapOfShapeListOfShape aDMIntE; // if (bIsPlanar) { // Find internal edges in the faces to skip them while preparing faces // for intersection through vertices NCollection_DataMap aDMFEI; { for (TopExp_Explorer expF (SI, TopAbs_FACE); expF.More(); expF.Next()) { const TopoDS_Shape& aFx = expF.Current(); TopTools_MapOfShape aMEI; for (TopExp_Explorer expE (aFx, TopAbs_EDGE); expE.More(); expE.Next()) { const TopoDS_Shape& aEx = expE.Current(); if (aEx.Orientation() != TopAbs_FORWARD && aEx.Orientation() != TopAbs_REVERSED) aMEI.Add (aEx); } if (!aMEI.IsEmpty()) aDMFEI.Bind (aFx, aMEI); } } // Analyze faces connected through vertices for (i = aNb + 1, aNb = VEmap.Extent(); i <= aNb; ++i) { if (!aPSOuter.More()) { return; } const TopoDS_Shape& aS = VEmap(i); if (aS.ShapeType() != TopAbs_VERTEX) continue; // Find faces connected to the vertex TopTools_ListOfShape aLF; { const TopTools_ListOfShape& aLE = Analyse.Ancestors (aS); for (TopTools_ListOfShape::Iterator itLE (aLE); itLE.More(); itLE.Next()) { const TopTools_ListOfShape& aLEA = Analyse.Ancestors (itLE.Value()); for (TopTools_ListOfShape::Iterator itLEA (aLEA); itLEA.More(); itLEA.Next()) { if (!aLF.Contains (itLEA.Value())) aLF.Append (itLEA.Value()); } } } if (aLF.Extent() < 2) continue; // build lists of faces connected to the same vertex by looking for // the pairs in which the vertex is alone (not connected to shared edges) TopTools_ListOfShape aLF1, aLF2; it.Initialize(aLF); for (; it.More(); it.Next()) { const TopoDS_Shape& aFV1 = it.Value(); // get edges of first face connected to current vertex TopTools_MapOfShape aME; const TopTools_MapOfShape *pF1Internal = aDMFEI.Seek (aFV1); const TopTools_ListOfShape* pLE1 = Analyse.Descendants (aFV1); if (!pLE1) continue; TopTools_ListOfShape::Iterator itLE1 (*pLE1); for (; itLE1.More(); itLE1.Next()) { const TopoDS_Shape& aE = itLE1.Value(); if (pF1Internal && pF1Internal->Contains (aE)) break; for (TopoDS_Iterator aItV(aE); aItV.More(); aItV.Next()) { if (aS.IsSame (aItV.Value())) { aME.Add(aE); break; } } } if (itLE1.More()) continue; // get to the next face in the list it1 = it; for (it1.Next(); it1.More(); it1.Next()) { const TopoDS_Face& aFV2 = TopoDS::Face (it1.Value()); const TopTools_MapOfShape *pF2Internal = aDMFEI.Seek (aFV2); const TopTools_ListOfShape* pLE2 = Analyse.Descendants (aFV2); if (!pLE2) continue; TopTools_ListOfShape::Iterator itLE2 (*pLE2); for (; itLE2.More(); itLE2.Next()) { const TopoDS_Shape& aEV2 = itLE2.Value(); if (!aME.Contains (aEV2)) continue; if (pF2Internal && pF2Internal->Contains (aEV2)) // Avoid intersection of faces connected by internal edge break; if (Analyse.HasAncestor (aEV2) && Analyse.Ancestors (aEV2).Extent() == 2) // Faces will be intersected through the edge break; } if (!itLE2.More()) { aLF1.Append(aFV1); aLF2.Append(aFV2); } } } // if (aLF1.Extent()) { aDMVLF1.Bind(aS, aLF1); aDMVLF2.Bind(aS, aLF2); } } } // aNb = VEmap.Extent(); Message_ProgressScope aPSInter(aPSOuter.Next(8), "Intersecting offset faces", aNb); for (i = 1; i <= aNb; ++i, aPSInter.Next()) { if (!aPSInter.More()) { return; } const TopoDS_Shape& aS = VEmap(i); // TopoDS_Edge E; TopTools_ListOfShape aLF1, aLF2; // bEdge = (aS.ShapeType() == TopAbs_EDGE); if (bEdge) { // faces connected by the edge E = *(TopoDS_Edge*)&aS; // const BRepOffset_ListOfInterval& L = Analyse.Type(E); if (L.IsEmpty()) { continue; } // ChFiDS_TypeOfConcavity OT = L.First().Type(); if (OT != ChFiDS_Convex && OT != ChFiDS_Concave) { continue; } // if (OT == ChFiDS_Concave) CurSide = TopAbs_IN; else CurSide = TopAbs_OUT; //----------------------------------------------------------- // edge is of the proper type, return adjacent faces. //----------------------------------------------------------- const TopTools_ListOfShape& Anc = Analyse.Ancestors(E); if (Anc.Extent() != 2) { continue; } // F1 = TopoDS::Face(Anc.First()); F2 = TopoDS::Face(Anc.Last ()); // aLF1.Append(F1); aLF2.Append(F2); } else { if (!aDMVLF1.IsBound(aS)) { continue; } // aLF1 = aDMVLF1.Find(aS); aLF2 = aDMVLF2.Find(aS); // CurSide = mySide; } // itF1.Initialize(aLF1); itF2.Initialize(aLF2); for (; itF1.More() && itF2.More(); itF1.Next(), itF2.Next()) { F1 = TopoDS::Face(itF1.Value()); F2 = TopoDS::Face(itF2.Value()); // OF1 = TopoDS::Face(MapSF(F1).Face()); OF2 = TopoDS::Face(MapSF(F2).Face()); if (!MES.IsBound(OF1)) { Standard_Boolean enlargeU = Standard_True; Standard_Boolean enlargeVfirst = Standard_True, enlargeVlast = Standard_True; BRepOffset_Tool::CheckBounds( F1, Analyse, enlargeU, enlargeVfirst, enlargeVlast ); BRepOffset_Tool::EnLargeFace(OF1,NF1,Standard_True,Standard_True,enlargeU,enlargeVfirst,enlargeVlast); MES.Bind(OF1,NF1); } else { NF1 = TopoDS::Face(MES(OF1)); } // if (!MES.IsBound(OF2)) { Standard_Boolean enlargeU = Standard_True; Standard_Boolean enlargeVfirst = Standard_True, enlargeVlast = Standard_True; BRepOffset_Tool::CheckBounds( F2, Analyse, enlargeU, enlargeVfirst, enlargeVlast ); BRepOffset_Tool::EnLargeFace(OF2,NF2,Standard_True,Standard_True,enlargeU,enlargeVfirst,enlargeVlast); MES.Bind(OF2,NF2); } else { NF2 = TopoDS::Face(MES(OF2)); } // if (!IsDone(NF1,NF2)) { TopTools_ListOfShape LInt1,LInt2; BRepOffset_Tool::Inter3D (NF1,NF2,LInt1,LInt2,CurSide,E,F1,F2); SetDone(NF1,NF2); if (!LInt1.IsEmpty()) { Store (NF1,NF2,LInt1,LInt2); // TopoDS_Compound C; B.MakeCompound(C); // if (Build.IsBound(aS)) { const TopoDS_Shape& aSE = Build(aS); TopExp_Explorer aExp(aSE, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aNE = aExp.Current(); B.Add(C, aNE); } } // it.Initialize(LInt1); for (; it.More(); it.Next()) { const TopoDS_Shape& aNE = it.Value(); B.Add(C, aNE); // // keep connection from new edge to shape from which it was created TopTools_ListOfShape *pLS = &aDMIntE(aDMIntE.Add(aNE, TopTools_ListOfShape())); pLS->Append(aS); // keep connection to faces created the edge as well TopTools_ListOfShape* pLFF = aDMIntFF.Bound(aNE, TopTools_ListOfShape()); pLFF->Append(F1); pLFF->Append(F2); } // Build.Bind(aS,C); } else { Failed.Append(aS); } } else { // IsDone(NF1,NF2) // Modified by skv - Fri Dec 26 12:20:13 2003 OCC4455 Begin const TopTools_ListOfShape &aLInt1 = myAsDes->Descendant(NF1); const TopTools_ListOfShape &aLInt2 = myAsDes->Descendant(NF2); if (!aLInt1.IsEmpty()) { TopoDS_Compound C; B.MakeCompound(C); // if (Build.IsBound(aS)) { const TopoDS_Shape& aSE = Build(aS); TopExp_Explorer aExp(aSE, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aNE = aExp.Current(); B.Add(C, aNE); } } // for (it.Initialize(aLInt1) ; it.More(); it.Next()) { const TopoDS_Shape &anE1 = it.Value(); // for (it1.Initialize(aLInt2) ; it1.More(); it1.Next()) { const TopoDS_Shape &anE2 = it1.Value(); if (anE1.IsSame(anE2)) { B.Add(C, anE1); // TopTools_ListOfShape *pLS = aDMIntE.ChangeSeek(anE1); if (pLS) { pLS->Append(aS); } } } } Build.Bind(aS,C); } else { Failed.Append(aS); } } } // Modified by skv - Fri Dec 26 12:20:14 2003 OCC4455 End } // // create unique intersection for each localized shared part aNb = aDMIntE.Extent(); Message_ProgressScope aPSPostTreat(aPSOuter.Next(2), "Creating unique intersection", aNb); for (i = 1; i <= aNb; ++i, aPSPostTreat.Next()) { if (!aPSPostTreat.More()) { return; } const TopTools_ListOfShape& aLS = aDMIntE(i); if (aLS.Extent() < 2) { continue; } // // intersection edge const TopoDS_Edge& aE = TopoDS::Edge(aDMIntE.FindKey(i)); // faces created the edge const TopTools_ListOfShape& aLFF = aDMIntFF.Find(aE); const TopoDS_Shape& aF1 = aLFF.First(); const TopoDS_Shape& aF2 = aLFF.Last(); // Build really localized blocks from the original shapes in : // 1. Find edges from original faces connected to two or more shapes in ; // 2. Make connexity blocks from edges in and found connection edges; // 3. Check if the vertices from are not connected by these connection edges: // a. If so - add these vertices to Connexity Block containing the corresponding // connexity edge; // b. If not - add this vertex to list of connexity blocks // 4. Create unique intersection edge for each connexity block // list of vertices TopTools_ListOfShape aLV; // compound of edges to build connexity blocks TopoDS_Compound aCE; B.MakeCompound(aCE); TopTools_MapOfShape aMS; TopTools_ListIteratorOfListOfShape aItLS(aLS); for (; aItLS.More(); aItLS.Next()) { const TopoDS_Shape& aS = aItLS.Value(); aMS.Add(aS); if (aS.ShapeType() == TopAbs_EDGE) { B.Add(aCE, aS); } else { aLV.Append(aS); } } // // look for additional edges to connect the shared parts TopTools_MapOfShape aMEConnection; for (Standard_Integer j = 0; j < 2; ++j) { const TopoDS_Shape& aF = !j ? aF1 : aF2; // TopExp_Explorer aExp(aF, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aEF = aExp.Current(); if (aMS.Contains(aEF) || aMEConnection.Contains(aEF)) { continue; } // TopoDS_Vertex aV1, aV2; TopExp::Vertices(TopoDS::Edge(aEF), aV1, aV2); // // find parts to which the edge is connected Standard_Integer iCounter = 0; aItLS.Initialize(aLS); for (; aItLS.More(); aItLS.Next()) { const TopoDS_Shape& aS = aItLS.Value(); // iterator is not suitable here, because aS may be a vertex TopExp_Explorer aExpV(aS, TopAbs_VERTEX); for (; aExpV.More(); aExpV.Next()) { const TopoDS_Shape& aV = aExpV.Current(); if (aV.IsSame(aV1) || aV.IsSame(aV2)) { ++iCounter; break; } } } // if (iCounter >= 2) { B.Add(aCE, aEF); aMEConnection.Add(aEF); } } } // TopTools_ListOfShape aLCBE; BOPTools_AlgoTools::MakeConnexityBlocks(aCE, TopAbs_VERTEX, TopAbs_EDGE, aLCBE); // // create connexity blocks for alone vertices TopTools_ListOfShape aLCBV; TopTools_ListIteratorOfListOfShape aItLV(aLV); for (; aItLV.More(); aItLV.Next()) { const TopoDS_Shape& aV = aItLV.Value(); // check if this vertex is contained in some connexity block of edges TopTools_ListIteratorOfListOfShape aItLCB(aLCBE); for (; aItLCB.More(); aItLCB.Next()) { TopoDS_Shape& aCB = aItLCB.ChangeValue(); TopExp_Explorer aExpV(aCB, TopAbs_VERTEX); for (; aExpV.More(); aExpV.Next()) { if (aV.IsSame(aExpV.Current())) { B.Add(aCB, aV); break; } } if (aExpV.More()) { break; } } // if (!aItLCB.More()) { TopoDS_Compound aCV; B.MakeCompound(aCV); B.Add(aCV, aV); aLCBV.Append(aCV); } } // aLCBE.Append(aLCBV); // if (aLCBE.Extent() == 1) { continue; } // const TopoDS_Shape& aNF1 = MES(MapSF(aF1).Face()); const TopoDS_Shape& aNF2 = MES(MapSF(aF2).Face()); // TopTools_ListIteratorOfListOfShape aItLCB(aLCBE); for (aItLCB.Next(); aItLCB.More(); aItLCB.Next()) { // make new edge with different tedge instance TopoDS_Edge aNewEdge; TopoDS_Vertex aV1, aV2; Standard_Real aT1, aT2; // TopExp::Vertices(aE, aV1, aV2); BRep_Tool::Range(aE, aT1, aT2); // BOPTools_AlgoTools::MakeSplitEdge(aE, aV1, aT1, aV2, aT2, aNewEdge); // myAsDes->Add(aNF1, aNewEdge); myAsDes->Add(aNF2, aNewEdge); // const TopoDS_Shape& aCB = aItLCB.Value(); TopoDS_Iterator aItCB(aCB); for (; aItCB.More(); aItCB.Next()) { const TopoDS_Shape& aS = aItCB.Value(); if (aMEConnection.Contains(aS)) { continue; } TopoDS_Shape& aCI = Build.ChangeFind(aS); // TopoDS_Compound aNewCI; B.MakeCompound(aNewCI); TopExp_Explorer aExp(aCI, TopAbs_EDGE); for (; aExp.More(); aExp.Next()) { const TopoDS_Shape& aSx = aExp.Current(); if (!aSx.IsSame(aE)) { B.Add(aNewCI, aSx); } } B.Add(aNewCI, aNewEdge); aCI = aNewCI; } } } } //======================================================================= //function : ContextIntByInt //purpose : //======================================================================= void BRepOffset_Inter3d::ContextIntByInt (const TopTools_IndexedMapOfShape& ContextFaces, const Standard_Boolean ExtentContext, const BRepOffset_DataMapOfShapeOffset& MapSF, const BRepOffset_Analyse& Analyse, TopTools_DataMapOfShapeShape& MES, TopTools_DataMapOfShapeShape& Build, TopTools_ListOfShape& Failed, const Message_ProgressRange& theRange, const Standard_Boolean bIsPlanar) { TopTools_MapOfShape MV; TopExp_Explorer exp; TopoDS_Face OF,NF,WCF; TopoDS_Edge OE; TopoDS_Compound C; BRep_Builder B; TopTools_ListIteratorOfListOfShape it, itF; Standard_Integer i, j, aNb, aNbVE; Standard_Boolean bEdge; aNb = ContextFaces.Extent(); for (i = 1; i <= aNb; i++) { const TopoDS_Face& CF = TopoDS::Face(ContextFaces(i)); myTouched.Add(CF); if (ExtentContext) { BRepOffset_Tool::EnLargeFace(CF,NF,0,0); MES.Bind(CF,NF); } } TopAbs_State Side = TopAbs_OUT; Message_ProgressScope aPS(theRange, "Intersecting with deepening faces", aNb); for (i = 1; i <= aNb; i++, aPS.Next()) { if (!aPS.More()) { return; } const TopoDS_Face& CF = TopoDS::Face(ContextFaces(i)); if (ExtentContext) WCF = TopoDS::Face(MES(CF)); else WCF = CF; TopTools_IndexedMapOfShape VEmap; TopExp::MapShapes(CF.Oriented(TopAbs_FORWARD), TopAbs_EDGE , VEmap); // if (bIsPlanar) { TopExp::MapShapes(CF.Oriented(TopAbs_FORWARD), TopAbs_VERTEX, VEmap); } // aNbVE = VEmap.Extent(); for (j = 1; j <= aNbVE; ++j) { const TopoDS_Shape& aS = VEmap(j); // bEdge = (aS.ShapeType() == TopAbs_EDGE); // TopoDS_Edge E; TopTools_ListOfShape Anc; // if (bEdge) { // faces connected by the edge // E = *(TopoDS_Edge*)&aS; if (!Analyse.HasAncestor(E)) { //---------------------------------------------------------------- // the edges of faces of context that are not in the initial shape // can appear in the result. //---------------------------------------------------------------- if (!ExtentContext) { myAsDes->Add(CF,E); myNewEdges.Add(E); } else { if (!MES.IsBound(E)) { TopoDS_Edge NE; Standard_Real f,l,Tol; BRep_Tool::Range(E,f,l); Tol = BRep_Tool::Tolerance(E); ExtentEdge(CF,E,NE); TopoDS_Vertex V1,V2; TopExp::Vertices(E,V1,V2); NE.Orientation(TopAbs_FORWARD); myAsDes->Add(NE,V1.Oriented(TopAbs_REVERSED)); myAsDes->Add(NE,V2.Oriented(TopAbs_FORWARD)); TopoDS_Shape aLocalShape = V1.Oriented(TopAbs_INTERNAL); B.UpdateVertex(TopoDS::Vertex(aLocalShape),f,NE,Tol); aLocalShape = V2.Oriented(TopAbs_INTERNAL); B.UpdateVertex(TopoDS::Vertex(aLocalShape),l,NE,Tol); // B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),f,NE,Tol); // B.UpdateVertex(TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),l,NE,Tol); NE.Orientation(E.Orientation()); myAsDes->Add(CF,NE); myNewEdges.Add(NE); MES.Bind(E,NE); } else { TopoDS_Shape NE = MES(E); TopoDS_Shape aLocalShape = NE.Oriented(E.Orientation()); myAsDes->Add(CF,aLocalShape); // myAsDes->Add(CF,NE.Oriented(E.Orientation())); } } continue; } Anc = Analyse.Ancestors(E); } else { // faces connected by the vertex // if (!Analyse.HasAncestor(aS)) { continue; } // const TopTools_ListOfShape& aLE = Analyse.Ancestors(aS); it.Initialize(aLE); for (; it.More(); it.Next()) { const TopoDS_Edge& aE = *(TopoDS_Edge*)&it.Value(); // if (BRep_Tool::Degenerated(aE)) { continue; } // if (VEmap.Contains(aE)) { continue; } // const TopTools_ListOfShape& aLF = Analyse.Ancestors(aE); itF.Initialize(aLF); for (; itF.More(); itF.Next()) { const TopoDS_Shape& aF = itF.Value(); Standard_Boolean bAdd = Standard_True; exp.Init(aF, TopAbs_EDGE); for (; exp.More() && bAdd; exp.Next()) { const TopoDS_Shape& aEF = exp.Current(); bAdd = !VEmap.Contains(aEF); } if (bAdd) { Anc.Append(aF); } } } } // itF.Initialize(Anc); for (; itF.More(); itF.Next()) { const TopoDS_Face& F = TopoDS::Face(itF.Value()); OF = TopoDS::Face(MapSF(F).Face()); TopoDS_Shape aLocalShape = MapSF(F).Generated(E); OE = TopoDS::Edge(aLocalShape); // OE = TopoDS::Edge(MapSF(F).Generated(E)); if (!MES.IsBound(OF)) { BRepOffset_Tool::EnLargeFace(OF,NF,1,1); MES.Bind(OF,NF); } else { NF = TopoDS::Face(MES(OF)); } if (!IsDone(NF,CF)) { TopTools_ListOfShape LInt1,LInt2; TopTools_ListOfShape LOE; LOE.Append(OE); BRepOffset_Tool::Inter3D (WCF,NF,LInt1,LInt2,Side,E,CF,F); SetDone(NF,CF); if (!LInt1.IsEmpty()) { Store (CF,NF,LInt1,LInt2); if ((LInt1.Extent() == 1) && !Build.IsBound(aS)) { Build.Bind(aS,LInt1.First()); } else { B.MakeCompound(C); if (Build.IsBound(aS)) { const TopoDS_Shape& aSE = Build(aS); exp.Init(aSE, TopAbs_EDGE); for (; exp.More(); exp.Next()) { const TopoDS_Shape& aNE = exp.Current(); B.Add(C, aNE); } } // for (it.Initialize(LInt1) ; it.More(); it.Next()) { B.Add(C,it.Value()); } Build.Bind(aS,C); } } else { Failed.Append(aS); } } } } } } //======================================================================= //function : ContextIntByArc //purpose : //======================================================================= void BRepOffset_Inter3d::ContextIntByArc(const TopTools_IndexedMapOfShape& ContextFaces, const Standard_Boolean InSide, const BRepOffset_Analyse& Analyse, const BRepAlgo_Image& InitOffsetFace, BRepAlgo_Image& InitOffsetEdge, const Message_ProgressRange& theRange) { TopTools_ListOfShape LInt1,LInt2; TopTools_MapOfShape MV; TopExp_Explorer exp; TopoDS_Face OF1,OF2; TopoDS_Edge OE; BRep_Builder B; TopoDS_Edge NullEdge; TopoDS_Face NullFace; Standard_Integer j; for (j = 1; j <= ContextFaces.Extent(); j++) { const TopoDS_Face& CF = TopoDS::Face(ContextFaces(j)); myTouched.Add(CF); } Message_ProgressScope aPS(theRange, "Intersecting with deepening faces", ContextFaces.Extent()); for (j = 1; j <= ContextFaces.Extent(); j++, aPS.Next()) { if (!aPS.More()) { return; } const TopoDS_Face& CF = TopoDS::Face(ContextFaces(j)); for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_EDGE); exp.More(); exp.Next()) { const TopoDS_Edge& E = TopoDS::Edge(exp.Current()); if (!Analyse.HasAncestor(E)) { if (InSide) myAsDes->Add(CF,E); else { TopoDS_Edge NE; if (!InitOffsetEdge.HasImage(E)) { Standard_Real f,l,Tol; BRep_Tool::Range(E,f,l); Tol = BRep_Tool::Tolerance(E); ExtentEdge(CF,E,NE); TopoDS_Vertex V1,V2; TopExp::Vertices(E,V1,V2); NE.Orientation(TopAbs_FORWARD); myAsDes->Add(NE,V1.Oriented(TopAbs_REVERSED)); myAsDes->Add(NE,V2.Oriented(TopAbs_FORWARD)); TopoDS_Shape aLocalShape = V1.Oriented(TopAbs_INTERNAL); B.UpdateVertex(TopoDS::Vertex(aLocalShape),f,NE,Tol); aLocalShape = V2.Oriented(TopAbs_INTERNAL); B.UpdateVertex(TopoDS::Vertex(aLocalShape),l,NE,Tol); // B.UpdateVertex(TopoDS::Vertex(V1.Oriented(TopAbs_INTERNAL)),f,NE,Tol); // B.UpdateVertex(TopoDS::Vertex(V2.Oriented(TopAbs_INTERNAL)),l,NE,Tol); NE.Orientation(E.Orientation()); myAsDes->Add(CF,NE); InitOffsetEdge.Bind(E,NE); } else { NE = TopoDS::Edge(InitOffsetEdge.Image(E).First()); myAsDes->Add(CF,NE.Oriented(E.Orientation())); } } continue; } OE.Nullify(); //--------------------------------------------------- // OF1 parallel facee generated by the ancestor of E. //--------------------------------------------------- const TopoDS_Shape SI = Analyse.Ancestors(E).First(); OF1 = TopoDS::Face(InitOffsetFace.Image(SI).First()); OE = TopoDS::Edge(InitOffsetEdge.Image(E).First()); { //Check if OE has pcurve in CF Standard_Real f,l; Handle (Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(OE,CF,f,l); Handle (Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(OE,OF1,f,l); if(C1.IsNull() || C2.IsNull()) { continue; } } //-------------------------------------------------- // MAJ of OE on cap CF. //-------------------------------------------------- // TopTools_ListOfShape LOE; LOE.Append(OE); // BRepOffset_Tool::TryProject(CF,OF1,LOE,LInt1,LInt2,mySide); // LInt2.Clear(); // StoreInter3d(CF,OF1,myTouched,NewEdges,InterDone,myAsDes, // LInt1,LInt2); LInt1.Clear(); LInt1.Append(OE); LInt2.Clear(); TopAbs_Orientation anOri1, anOri2; BRepOffset_Tool::OrientSection(OE,CF,OF1, anOri1,anOri2); // if (mySide == TopAbs_OUT); anOri1 = TopAbs::Reverse(anOri1); LInt1.First().Orientation(anOri1); Store(CF,OF1,LInt1,LInt2); //------------------------------------------------------ // Processing of offsets on the ancestors of vertices. //------------------------------------------------------ TopoDS_Vertex V[2]; TopExp::Vertices (E,V[0],V[1]); for (Standard_Integer i = 0; i < 2; i++) { if (!MV.Add(V[i])) continue; OF1.Nullify(); const TopTools_ListOfShape& LE = Analyse.Ancestors(V[i]); TopTools_ListIteratorOfListOfShape itLE(LE); for ( ; itLE.More(); itLE.Next()) { const TopoDS_Edge& EV = TopoDS::Edge(itLE.Value()); if (InitOffsetFace.HasImage(EV)) { //------------------------------------------------- // OF1 parallel face generated by an ancester edge of V[i]. //------------------------------------------------- OF1 = TopoDS::Face(InitOffsetFace.Image(EV).First()); OE = TopoDS::Edge(InitOffsetEdge.Image(V[i]).First()); { //Check if OE has pcurve in CF and OF1 Standard_Real f,l; Handle (Geom2d_Curve) C1 = BRep_Tool::CurveOnSurface(OE,CF,f,l); Handle (Geom2d_Curve) C2 = BRep_Tool::CurveOnSurface(OE,OF1,f,l); if(C1.IsNull() || C2.IsNull()) { continue; } } //-------------------------------------------------- // MAj of OE on cap CF. //-------------------------------------------------- // LOE.Clear(); LOE.Append(OE); // BRepOffset_Tool::TryProject(CF,OF1,LOE,LInt1,LInt2,mySide); // LInt2.Clear(); // StoreInter3d(CF,OF1,myTouched,NewEdges,InterDone,myAsDes, // LInt1,LInt2); LInt1.Clear(); LInt1.Append(OE); LInt2.Clear(); TopAbs_Orientation O1,O2; BRepOffset_Tool::OrientSection(OE,CF,OF1,O1,O2); // if (mySide == TopAbs_OUT); O1 = TopAbs::Reverse(O1); LInt1.First().Orientation(O1); Store(CF,OF1,LInt1,LInt2); } } } } for (exp.Init(CF.Oriented(TopAbs_FORWARD),TopAbs_VERTEX); exp.More(); exp.Next()) { const TopoDS_Vertex& V = TopoDS::Vertex(exp.Current()); if (!Analyse.HasAncestor(V)) { continue; } const TopTools_ListOfShape& LE = Analyse.Ancestors(V); TopTools_ListIteratorOfListOfShape itLE(LE); for (; itLE.More(); itLE.Next()) { const TopoDS_Edge& EV = TopoDS::Edge(itLE.Value()); const TopTools_ListOfShape& LF = Analyse.Ancestors(EV); TopTools_ListIteratorOfListOfShape itLF(LF); for ( ; itLF.More(); itLF.Next()) { const TopoDS_Face& FEV = TopoDS::Face(itLF.Value()); //------------------------------------------------- // OF1 parallel face generated by uneFace ancestor of V[i]. //------------------------------------------------- OF1 = TopoDS::Face(InitOffsetFace.Image(FEV).First()); if (!IsDone(OF1,CF)) { //------------------------------------------------------- // Find if one of edges of OF1 has no trace in CF. //------------------------------------------------------- TopTools_ListOfShape LOE; TopExp_Explorer exp2(OF1.Oriented(TopAbs_FORWARD),TopAbs_EDGE); for ( ;exp2.More(); exp2.Next()) { LOE.Append(exp2.Current()); } BRepOffset_Tool::TryProject(CF,OF1,LOE,LInt1,LInt2,mySide,myTol); //------------------------------------------------------- // If no trace try intersection. //------------------------------------------------------- if (LInt1.IsEmpty()) { BRepOffset_Tool::Inter3D (CF,OF1,LInt1,LInt2,mySide,NullEdge,NullFace,NullFace); } Store (CF,OF1,LInt1,LInt2); } } } } } } //======================================================================= //function : SetDone //purpose : //======================================================================= void BRepOffset_Inter3d::SetDone(const TopoDS_Face& F1, const TopoDS_Face& F2) { if (!myDone.IsBound(F1)) { TopTools_ListOfShape empty; myDone.Bind(F1,empty); } myDone(F1).Append(F2); if (!myDone.IsBound(F2)) { TopTools_ListOfShape empty; myDone.Bind(F2,empty); } myDone(F2).Append(F1); } //======================================================================= //function : IsDone //purpose : //======================================================================= Standard_Boolean BRepOffset_Inter3d::IsDone(const TopoDS_Face& F1, const TopoDS_Face& F2) const { if (myDone.IsBound(F1)) { TopTools_ListIteratorOfListOfShape it (myDone(F1)); for (; it.More(); it.Next()) { if (it.Value().IsSame(F2)) return Standard_True; } } return Standard_False; } //======================================================================= //function : Store //purpose : //======================================================================= void BRepOffset_Inter3d::Store(const TopoDS_Face& F1, const TopoDS_Face& F2, const TopTools_ListOfShape& LInt1, const TopTools_ListOfShape& LInt2) { if (!LInt1.IsEmpty()) { myTouched.Add(F1); myTouched.Add(F2); myAsDes->Add( F1,LInt1); myAsDes->Add( F2,LInt2); TopTools_ListIteratorOfListOfShape it(LInt1); for (; it.More(); it.Next()) { myNewEdges.Add(it.Value()); } } SetDone(F1,F2); }