1 // Created on: 1998-11-19
2 // Created by: Jean-Michel BOULCOURT
3 // Copyright (c) 1998-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
8 // This library is free software; you can redistribute it and/or modify it under
9 // the terms of the GNU Lesser General Public License version 2.1 as published
10 // by the Free Software Foundation, with special exception defined in the file
11 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
12 // distribution for complete text of the license and disclaimer of any warranty.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16 
17 
18 #include <BRepTools_Substitution.hxx>
19 #include <Standard_ConstructionError.hxx>
20 #include <Standard_NullObject.hxx>
21 #include <TopExp.hxx>
22 #include <TopExp_Explorer.hxx>
23 #include <TopoDS.hxx>
24 #include <TopoDS_Shape.hxx>
25 #include <TopOpeBRepTool_PurgeInternalEdges.hxx>
26 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
27 #include <TopTools_DataMapOfShapeListOfShape.hxx>
28 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
29 #include <TopTools_ListIteratorOfListOfShape.hxx>
30 #include <TopTools_ListOfShape.hxx>
31 #include <TopTools_MapOfShape.hxx>
32 
33 //=======================================================================
34 //function : TopOpeBRepTool_PurgeInternalEdges
35 //purpose  : Initializes some variables for the algorithm and perform
36 // the computation of the internal edges of the shape
37 //=======================================================================
TopOpeBRepTool_PurgeInternalEdges(const TopoDS_Shape & theShape,const Standard_Boolean PerformNow)38 TopOpeBRepTool_PurgeInternalEdges::TopOpeBRepTool_PurgeInternalEdges(const TopoDS_Shape& theShape,const Standard_Boolean PerformNow):myShape(theShape),myIsDone(Standard_False)
39 {
40 //  if (theShape.ShapeType() != TopAbs_SHELL && theShape.ShapeType() != TopAbs_SOLID)
41 //    throw Standard_ConstructionError("PurgeInternalEdges");
42   Standard_NullObject_Raise_if(theShape.IsNull(),"PurgeInternalEdges");
43 
44   if (PerformNow) {
45     Perform();
46   }
47 }
48 
49 //=======================================================================
50 //function : Faces
51 //purpose  :
52 //=======================================================================
53 
Faces(TopTools_DataMapOfShapeListOfShape & theMapFacLstEdg)54  void TopOpeBRepTool_PurgeInternalEdges::Faces(TopTools_DataMapOfShapeListOfShape& theMapFacLstEdg)
55 {
56 
57   if (!myIsDone) {
58     BuildList();
59   }
60 
61   theMapFacLstEdg = myMapFacLstEdg;
62 }
63 
64 
65 //=======================================================================
66 //function : NbEdges
67 //purpose  :
68 //=======================================================================
69 
NbEdges() const70 Standard_Integer TopOpeBRepTool_PurgeInternalEdges::NbEdges() const
71 {
72 
73   Standard_NullObject_Raise_if(myShape.IsNull(),"PurgeInternalEdges : No Shape");
74   Standard_Integer nbedges = 0;
75 
76   // if we have at least on internal (or external) edge to remove
77   if (myMapFacLstEdg.Extent() > 0) {
78 
79     TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itFacEdg;
80 //    TopTools_ListIteratorOfListOfShape itEdg;
81 
82     for (itFacEdg.Initialize(myMapFacLstEdg); itFacEdg.More(); itFacEdg.Next()) {
83       const TopoDS_Shape& facecur = itFacEdg.Key();
84       const TopTools_ListOfShape& LmapEdg = myMapFacLstEdg.Find(facecur);
85 
86       nbedges += LmapEdg.Extent();
87     }
88 
89   }
90 
91   return nbedges;
92 
93 }
94 
95 
96 
97 
98 //=======================================================================
99 //function : Shape
100 //purpose  :
101 //=======================================================================
102 
Shape()103 TopoDS_Shape& TopOpeBRepTool_PurgeInternalEdges::Shape()
104 {
105 
106   Standard_NullObject_Raise_if(myShape.IsNull(),"PurgeInternalEdges : No Shape");
107 
108   return myShape;
109 
110 }
111 
112 //=======================================================================
113 //function : BuildList
114 //purpose  : Build the map of faces with the list of internal edges.
115 //=======================================================================
116 
BuildList()117 void TopOpeBRepTool_PurgeInternalEdges::BuildList()
118 {
119 
120   TopExp_Explorer ExpEdge;
121   TopAbs_Orientation orien;
122 
123 
124   //--------------------------------------------------------
125   // Step One : Build the map of the faces ancestor of edges
126   //--------------------------------------------------------
127 
128   // Clear the maps
129   myMapEdgLstFac.Clear();
130 
131   TopExp::MapShapesAndAncestors(myShape,TopAbs_EDGE,TopAbs_FACE,myMapEdgLstFac);
132 
133 
134   //----------------------------------------------------------------
135   // Step Two : Explore the map myMapFacLstEdg to keep only the internal
136   // or external edges which have no connex faces
137   //----------------------------------------------------------------
138 
139 
140   Standard_Boolean ToKeep;
141   Standard_Integer iEdg;
142   TopTools_ListIteratorOfListOfShape itFac,itFacToTreat;
143   TopTools_ListOfShape LstFacToTreat;
144 
145   // for each edge of myMapEdgLstFac
146   for (iEdg = 1; iEdg <= myMapEdgLstFac.Extent(); iEdg++) {
147     const TopoDS_Shape& edgecur = myMapEdgLstFac.FindKey(iEdg);
148     const TopTools_ListOfShape& LmapFac = myMapEdgLstFac.FindFromKey(edgecur);
149 
150 
151     // if there are more than on face connex to the edge then examine the orientation of
152     // the edge in the faces to see it is only Internal or External. In that case the edge
153     // can be removed
154 
155     itFac.Initialize(LmapFac);
156     LstFacToTreat.Clear();
157 
158     if (LmapFac.Extent() > 1) {
159 
160       ToKeep = Standard_False;
161       // for each face in the list of the edge
162       while (itFac.More() && !ToKeep) {
163 	const TopoDS_Shape& facecur = itFac.Value();
164 
165 	// find the edge in the face to get its relative orientation to the face
166 	for (ExpEdge.Init(facecur,TopAbs_EDGE); ExpEdge.More(); ExpEdge.Next()) {
167 	  const TopoDS_Shape& edge = ExpEdge.Current();
168 
169 	  orien = edge.Orientation();
170 
171 	  if (edge.IsSame(edgecur)) {
172 	    // we found the edge. Now check if its orientation is internal or external
173 	    // then the face is candidate to be modified. So put it in a temporary List of shapes
174 	    if (orien == TopAbs_INTERNAL || orien == TopAbs_EXTERNAL) {
175 	      LstFacToTreat.Append(facecur);
176 	    }
177 	    else {
178 	      // there is at least one face that contains that edge with a forward
179 	      // or reversed orientation. So we must keep that edge.
180 	      LstFacToTreat.Clear();
181 	      ToKeep = Standard_True;
182 	    }
183 	    break;
184 	  }
185 	}
186 
187 	itFac.Next();
188       }
189 
190     }
191 
192     else {
193        if (edgecur.Orientation() == TopAbs_INTERNAL || edgecur.Orientation() == TopAbs_EXTERNAL) {
194 	 LstFacToTreat.Append(itFac.Value());
195        }
196     }
197 
198     // at that point, we have in the list LstFacToTreat the faces in which edgecur is
199     // connex and is coded only Internal or External.
200     if (!LstFacToTreat.IsEmpty()) {
201       TopTools_MapOfShape mapUniqEdg;
202       for (itFacToTreat.Initialize(LstFacToTreat); itFacToTreat.More(); itFacToTreat.Next()) {
203 	const TopoDS_Shape& face = itFacToTreat.Value();
204 
205 	//we build the resulting map with a face as a key and a list of internal (or external)
206 	// edges to remove from the face.
207 	if (!myMapFacLstEdg.IsBound(face)) {
208 	  TopTools_ListOfShape LmapEdg;
209 	  if (!mapUniqEdg.Contains(edgecur)) {
210 	    mapUniqEdg.Add(edgecur);
211 	    LmapEdg.Append(edgecur);
212 	    myMapFacLstEdg.Bind(face,LmapEdg);
213 	  }
214 	}
215 	else { // just append the edge to the list of edges of the face
216 	  TopTools_ListOfShape& LmapEdg = myMapFacLstEdg.ChangeFind(face);
217 	  if (!mapUniqEdg.Contains(edgecur)) {
218 	    mapUniqEdg.Add(edgecur);
219 	    LmapEdg.Append(edgecur);
220 	  }
221 	}
222 
223       }
224     }
225 
226   }
227 
228   myIsDone = Standard_True;
229 
230 }
231 
232 
233 
234 //=======================================================================
235 //function : Perform
236 //purpose  :
237 //=======================================================================
238 
Perform()239  void TopOpeBRepTool_PurgeInternalEdges::Perform()
240 {
241 
242   // if the list has not been yet built then do it
243   if (!myIsDone) {
244     BuildList();
245   }
246 
247   // if we have at least on internal (or external) edge to remove
248   if (myMapFacLstEdg.Extent() > 0) {
249 
250     TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itFacEdg;
251     TopTools_ListIteratorOfListOfShape itEdg;
252     TopTools_ListOfShape EmptyList;
253     BRepTools_Substitution Bsub;
254 
255     for (itFacEdg.Initialize(myMapFacLstEdg); itFacEdg.More(); itFacEdg.Next()) {
256       const TopoDS_Shape& facecur = itFacEdg.Key();
257       const TopTools_ListOfShape& LmapEdg = myMapFacLstEdg.Find(facecur);
258 
259       for (itEdg.Initialize(LmapEdg); itEdg.More(); itEdg.Next()) {
260 	Bsub.Substitute(itEdg.Value(),EmptyList);
261       }
262     }
263 
264     Bsub.Build(myShape);
265     if (Bsub.IsCopied(myShape)) {
266       myShape=(Bsub.Copy(myShape)).First();
267     }
268   }
269 }
270 
271 
272