0026656: ShapeFix_Face introduces extremely high vertex tolerance in the input shape
[occt.git] / src / ShapeUpgrade / ShapeUpgrade_RemoveInternalWires.cxx
CommitLineData
973c2be1 1// Copyright (c) 1999-2014 OPEN CASCADE SAS
b311480e 2//
973c2be1 3// This file is part of Open CASCADE Technology software library.
b311480e 4//
d5f74e42 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
973c2be1 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.
b311480e 10//
973c2be1 11// Alternatively, this file may be used under the terms of Open CASCADE
12// commercial license or contractual agreement.
b311480e 13
42cf5bc1 14
15#include <Precision.hxx>
7fd59977 16#include <ShapeAnalysis.hxx>
42cf5bc1 17#include <ShapeBuild_ReShape.hxx>
7fd59977 18#include <ShapeExtend.hxx>
7fd59977 19#include <ShapeExtend_WireData.hxx>
42cf5bc1 20#include <ShapeUpgrade_RemoveInternalWires.hxx>
21#include <Standard_Type.hxx>
22#include <TopExp.hxx>
23#include <TopExp_Explorer.hxx>
24#include <TopoDS.hxx>
7fd59977 25#include <TopoDS_Edge.hxx>
42cf5bc1 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>
7fd59977 31#include <TopTools_IndexedMapOfShape.hxx>
42cf5bc1 32#include <TopTools_ListIteratorOfListOfShape.hxx>
33#include <TopTools_ListOfShape.hxx>
34#include <TopTools_SequenceOfShape.hxx>
b311480e 35
7fd59977 36//=======================================================================
37//function : ShapeUpgrade_RemoveInternalWires
38//purpose :
39//=======================================================================
7fd59977 40ShapeUpgrade_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
55ShapeUpgrade_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
143void 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
185void 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);
7fd59977 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
274void ShapeUpgrade_RemoveInternalWires::Clear()
275{
276 myRemoveEdges.Clear();
277 myRemovedFaces.Clear();
278 myRemoveWires.Clear();
279 myStatus = ShapeExtend::EncodeStatus (ShapeExtend_OK);
280}
281