0026466: UnifySameDomain creates invalid result shape from valid input shape
[occt.git] / src / ShapeUpgrade / ShapeUpgrade_RemoveInternalWires.cxx
1 // Copyright (c) 1999-2014 OPEN CASCADE SAS
2 //
3 // This file is part of Open CASCADE Technology software library.
4 //
5 // This library is free software; you can redistribute it and/or modify it under
6 // the terms of the GNU Lesser General Public License version 2.1 as published
7 // by the Free Software Foundation, with special exception defined in the file
8 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
9 // distribution for complete text of the license and disclaimer of any warranty.
10 //
11 // Alternatively, this file may be used under the terms of Open CASCADE
12 // commercial license or contractual agreement.
13
14
15 #include <Precision.hxx>
16 #include <ShapeAnalysis.hxx>
17 #include <ShapeBuild_ReShape.hxx>
18 #include <ShapeExtend.hxx>
19 #include <ShapeExtend_WireData.hxx>
20 #include <ShapeUpgrade_RemoveInternalWires.hxx>
21 #include <Standard_Type.hxx>
22 #include <TopExp.hxx>
23 #include <TopExp_Explorer.hxx>
24 #include <TopoDS.hxx>
25 #include <TopoDS_Edge.hxx>
26 #include <TopoDS_Face.hxx>
27 #include <TopoDS_Iterator.hxx>
28 #include <TopoDS_Shape.hxx>
29 #include <TopoDS_Wire.hxx>
30 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
31 #include <TopTools_IndexedMapOfShape.hxx>
32 #include <TopTools_ListIteratorOfListOfShape.hxx>
33 #include <TopTools_ListOfShape.hxx>
34 #include <TopTools_SequenceOfShape.hxx>
35
36 //=======================================================================
37 //function : ShapeUpgrade_RemoveInternalWires
38 //purpose  : 
39 //=======================================================================
40 ShapeUpgrade_RemoveInternalWires::ShapeUpgrade_RemoveInternalWires()
41 {
42   myMinArea =0.;
43   myRemoveFacesMode = Standard_True;
44   myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
45   Handle(ShapeBuild_ReShape) aContext = new ShapeBuild_ReShape;
46   SetContext(aContext);
47   
48 }
49
50 //=======================================================================
51 //function : ShapeUpgrade_RemoveInternalWires
52 //purpose  : 
53 //=======================================================================
54
55 ShapeUpgrade_RemoveInternalWires::ShapeUpgrade_RemoveInternalWires(const TopoDS_Shape& theShape)
56 {
57   Handle(ShapeBuild_ReShape) aContext = new ShapeBuild_ReShape;
58   SetContext(aContext);
59   Init(theShape);
60 }
61
62 //=======================================================================
63 //function : Init
64 //purpose  : 
65 //=======================================================================
66
67  void ShapeUpgrade_RemoveInternalWires::Init(const TopoDS_Shape& theShape) 
68 {
69   myShape = theShape;
70   Context()->Apply(theShape);
71   TopExp::MapShapesAndAncestors(myShape,TopAbs_EDGE,TopAbs_FACE,myEdgeFaces);
72   myStatus = ShapeExtend::EncodeStatus ( ShapeExtend_OK );
73   myMinArea =0.;
74   myRemoveFacesMode = Standard_True;
75 }
76
77 //=======================================================================
78 //function : Perform
79 //purpose  : 
80 //=======================================================================
81
82  Standard_Boolean ShapeUpgrade_RemoveInternalWires::Perform() 
83 {
84   Clear();
85   if(myShape.IsNull()) {
86     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
87     return Standard_False;
88   }
89   TopExp_Explorer aExpF(myShape,TopAbs_FACE);
90   for( ; aExpF.More(); aExpF.Next()) {
91     TopoDS_Face aF = TopoDS::Face(aExpF.Current());
92     removeSmallWire(aF,TopoDS_Wire());
93   }
94   if(myRemoveFacesMode)
95     removeSmallFaces();
96   
97   myResult = Context()->Apply(myShape);
98   return Status( ShapeExtend_DONE );
99 }
100  
101 //=======================================================================
102 //function : Perform
103 //purpose  : 
104 //=======================================================================
105
106  Standard_Boolean ShapeUpgrade_RemoveInternalWires::Perform(const TopTools_SequenceOfShape& theSeqShapes) 
107 {
108   if(myShape.IsNull()) {
109     myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL1);
110     return Standard_False;
111   }
112   Clear();
113   TopTools_IndexedDataMapOfShapeListOfShape aWireFaces;
114   Standard_Integer i =1, nb = theSeqShapes.Length();
115   for( ; i <= nb; i++) {
116     TopoDS_Shape aS = theSeqShapes.Value(i);
117     if(aS.ShapeType() == TopAbs_FACE)
118       removeSmallWire(aS,TopoDS_Wire());
119     else if(aS.ShapeType() == TopAbs_WIRE) {
120       if(!aWireFaces.Extent())
121         TopExp::MapShapesAndAncestors(myShape,TopAbs_WIRE,TopAbs_FACE,aWireFaces);
122       if(aWireFaces.Contains(aS)) {
123         const TopTools_ListOfShape& alfaces = aWireFaces.FindFromKey(aS);
124         TopTools_ListIteratorOfListOfShape liter(alfaces);
125         for( ; liter.More(); liter.Next())
126           removeSmallWire(liter.Value(),aS);
127       }
128         
129     }
130     
131   }
132   if(myRemoveFacesMode)
133       removeSmallFaces();
134   myResult = Context()->Apply(myShape);
135   return Status( ShapeExtend_DONE );
136 }
137
138 //=======================================================================
139 //function : removeSmallWire
140 //purpose  : 
141 //=======================================================================
142
143 void ShapeUpgrade_RemoveInternalWires::removeSmallWire (const TopoDS_Shape& theFace,
144                                                         const TopoDS_Shape& theWire) 
145 {
146   TopoDS_Face aF = TopoDS::Face(theFace);
147   TopoDS_Wire anOutW = ShapeAnalysis::OuterWire(aF);
148   TopoDS_Iterator aIt(aF);
149   for( ; aIt.More(); aIt.Next()) {
150     if(aIt.Value().ShapeType() != TopAbs_WIRE || aIt.Value().IsSame(anOutW))
151       continue;
152     //Handle(ShapeExtend_WireData) asewd = new  ShapeExtend_WireData();
153     TopoDS_Wire aW = TopoDS::Wire(aIt.Value());
154     if(!theWire.IsNull() && !theWire.IsSame(aW))
155       continue;
156     Standard_Real anArea = ShapeAnalysis::ContourArea(aW);
157     if(anArea < myMinArea -Precision::Confusion()) {
158       Context()->Remove(aW);
159       myRemoveWires.Append(aW);
160       myStatus |= ShapeExtend::EncodeStatus(ShapeExtend_DONE1);
161       if(!myRemoveFacesMode )
162         continue;
163       
164       TopoDS_Iterator aIte(aW,Standard_False);
165       for( ; aIte.More(); aIte.Next()) {
166         TopoDS_Shape aE = aIte.Value();
167         if(myRemoveEdges.IsBound(aE))
168           myRemoveEdges.ChangeFind(aE).Append(aF);
169         else {
170           TopTools_ListOfShape alfaces;
171           alfaces.Append(aF);
172           myRemoveEdges.Bind(aE,alfaces);
173         }
174       }
175     }
176     
177   }
178 }
179
180 //=======================================================================
181 //function : removeSmallFaces
182 //purpose  : 
183 //=======================================================================
184
185 void ShapeUpgrade_RemoveInternalWires::removeSmallFaces ()
186 {
187   
188   Standard_Integer i =1;
189   for( ; i <= myRemoveWires.Length() ; i++) {
190     TopoDS_Shape aWire = myRemoveWires.Value(i);
191     TopoDS_Iterator aIte(aWire,Standard_False);
192     TopTools_IndexedMapOfShape aFaceCandidates;
193     //collecting all faces containing edges from removed wire
194     for( ; aIte.More(); aIte.Next()) {
195       
196       TopoDS_Shape aEdge =  aIte.Value();
197       if(!myEdgeFaces.Contains(aEdge)) {
198         myStatus |= ShapeExtend::EncodeStatus (ShapeExtend_FAIL2);
199         continue;
200       }
201       const TopTools_ListOfShape& aLface1 = myEdgeFaces.FindFromKey(aEdge);
202       const TopTools_ListOfShape& aLface2 = myRemoveEdges.Find(aEdge);
203       TopTools_ListIteratorOfListOfShape aliter(aLface1);
204       TopTools_ListIteratorOfListOfShape aliter2(aLface2);
205       for( ; aliter.More(); aliter.Next()) {
206         TopoDS_Shape aF = Context()->Apply(aliter.Value());
207         if(aF.IsNull())
208           continue;
209         Standard_Boolean isFind = Standard_False;
210         for( ; aliter2.More() && !isFind; aliter2.Next()) {
211           TopoDS_Shape aF2 = Context()->Apply(aliter2.Value());
212           isFind = aF.IsSame(aF2);
213         }
214         
215         if(!isFind) {
216           TopoDS_Wire aWout = ShapeAnalysis::OuterWire(TopoDS::Face(aF));
217           Standard_Boolean isOuter = Standard_False;
218           TopoDS_Iterator aIter(aWout,Standard_False);
219           for( ; aIter.More() && !isOuter; aIter.Next())
220             isOuter = aEdge.IsSame(aIter.Value());
221           if(isOuter)
222             aFaceCandidates.Add(aF);
223         }
224       }
225       
226     }
227     
228     //remove faces which have outer wire consist of only
229     //edges from removed wires and
230     //seam edges for faces based on conic surface or 
231     //in the case of a few faces based on the same conic surface
232     //the edges belogining these faces.
233     Standard_Integer k =1;
234     for( ; k <= aFaceCandidates.Extent(); k++) {
235       TopoDS_Shape aF = aFaceCandidates.FindKey(k);
236       TopoDS_Wire anOutW = ShapeAnalysis::OuterWire(TopoDS::Face(aF));
237       Handle(ShapeExtend_WireData) asewd = new ShapeExtend_WireData(anOutW);
238       Standard_Integer n =1, nbE = asewd->NbEdges();
239       Standard_Integer nbNotRemoved =0;
240       for( ; n <= nbE; n++) {
241         if(asewd->IsSeam(n))
242           continue;
243         TopoDS_Edge aE = asewd->Edge(n);
244         if(!myRemoveEdges.IsBound(aE) ) {
245           const TopTools_ListOfShape& aLface3 = myEdgeFaces.FindFromKey(aE);
246           TopTools_ListIteratorOfListOfShape aliter3(aLface3);
247           for( ; aliter3.More();aliter3.Next()) {
248             TopoDS_Shape aF2 = Context()->Apply(aliter3.Value());
249             if(aF2.IsNull())
250               continue;
251             if(!aF.IsSame(aF2) && !aFaceCandidates.Contains(aF2))
252               nbNotRemoved++;
253           }
254         }
255         
256       }
257     
258       if(!nbNotRemoved) {
259         Context()->Remove(aF);
260         myRemovedFaces.Append(aF);
261       }
262     }
263   }
264   
265   if(myRemovedFaces.Length())
266     myStatus |= ShapeExtend::EncodeStatus(ShapeExtend_DONE2);
267 }
268
269 //=======================================================================
270 //function : Clear
271 //purpose  : 
272 //=======================================================================
273
274 void ShapeUpgrade_RemoveInternalWires::Clear()
275 {
276   myRemoveEdges.Clear();
277   myRemovedFaces.Clear();
278   myRemoveWires.Clear();
279   myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
280 }
281