b311480e |
1 | // Created on: 1993-01-18 |
2 | // Created by: Remi LEQUETTE |
3 | // Copyright (c) 1993-1999 Matra Datavision |
973c2be1 |
4 | // Copyright (c) 1999-2014 OPEN CASCADE SAS |
b311480e |
5 | // |
973c2be1 |
6 | // This file is part of Open CASCADE Technology software library. |
b311480e |
7 | // |
d5f74e42 |
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 |
973c2be1 |
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. |
b311480e |
13 | // |
973c2be1 |
14 | // Alternatively, this file may be used under the terms of Open CASCADE |
15 | // commercial license or contractual agreement. |
7fd59977 |
16 | |
17 | #define No_Standard_NoMoreObject |
18 | #define No_Standard_NoSuchObject |
19 | |
20 | #include <TopExp_Explorer.ixx> |
21 | #include <TopoDS_Iterator.hxx> |
22 | #include <TopAbs.hxx> |
23 | #include <Standard.hxx> |
24 | #include <Standard_NoMoreObject.hxx> |
25 | #include <Standard_NoSuchObject.hxx> |
26 | |
27 | // macro to compare two types of shapes |
28 | // always True if the first one is SHAPE |
29 | #define SAMETYPE(x,y) ((x) == (y)) |
30 | #define AVOID(x,y) (((x) == TopAbs_SHAPE) ? Standard_False : (x) == (y)) |
31 | #define LESSCOMPLEX(x,y) ((x) > (y)) |
32 | |
33 | static const Standard_Integer theStackSize = 20; |
34 | |
35 | //======================================================================= |
36 | //function : TopExp_Explorer |
37 | //purpose : |
38 | //======================================================================= |
39 | |
40 | TopExp_Explorer::TopExp_Explorer() : |
41 | myStack(0L),myTop(-1),hasMore(Standard_False) |
42 | { |
43 | myStack = (TopoDS_Iterator*)Standard::Allocate(theStackSize*sizeof(TopoDS_Iterator)); |
44 | mySizeOfStack = theStackSize; |
45 | } |
46 | |
47 | |
48 | //======================================================================= |
49 | //function : TopExp_Explorer |
50 | //purpose : |
51 | //======================================================================= |
52 | |
53 | TopExp_Explorer::TopExp_Explorer(const TopoDS_Shape& S, |
54 | const TopAbs_ShapeEnum ToFind, |
55 | const TopAbs_ShapeEnum ToAvoid): |
56 | myStack(0L),myTop(-1),hasMore(Standard_False) |
57 | |
58 | { |
59 | myStack = (TopoDS_Iterator*)Standard::Allocate(theStackSize*sizeof(TopoDS_Iterator)); |
60 | mySizeOfStack = theStackSize; |
61 | Init(S,ToFind,ToAvoid); |
62 | } |
63 | |
64 | |
65 | //======================================================================= |
66 | //function : Init |
67 | //purpose : |
68 | //======================================================================= |
69 | |
70 | void TopExp_Explorer::Init(const TopoDS_Shape& S, |
71 | const TopAbs_ShapeEnum ToFind, |
72 | const TopAbs_ShapeEnum ToAvoid) |
73 | { |
74 | if(myTop >=0) { |
75 | for(int i=0;i<= myTop; i++) |
76 | myStack[i].~TopoDS_Iterator(); |
77 | } |
78 | |
79 | myTop = -1; |
80 | myShape = S; |
81 | toFind = ToFind; |
82 | toAvoid = ToAvoid; |
83 | |
84 | if (S.IsNull()) { |
85 | hasMore = Standard_False; |
86 | return; |
87 | } |
88 | |
89 | #if 0 |
90 | // for SOLID, FACE, EDGE ignores the initial orientation |
91 | TopAbs_ShapeEnum T = myShape.ShapeType(); |
92 | if ((T == TopAbs_SOLID) || (T == TopAbs_FACE) || (T == TopAbs_EDGE)) |
93 | myShape.Orientation(TopAbs_FORWARD); |
94 | #endif |
95 | |
96 | if (toFind == TopAbs_SHAPE) |
97 | hasMore = Standard_False; |
98 | |
99 | else { |
100 | TopAbs_ShapeEnum ty = S.ShapeType(); |
101 | |
102 | if (LESSCOMPLEX(ty,toFind)) { |
103 | // the first Shape is less complex, nothing to find |
104 | hasMore = Standard_False; |
105 | } |
106 | else if (!SAMETYPE(ty,toFind)) { |
107 | // type is more complex search inside |
108 | hasMore = Standard_True; |
109 | Next(); |
110 | } |
111 | else { |
112 | // type is found |
113 | hasMore = Standard_True; |
114 | } |
115 | } |
116 | } |
117 | |
118 | |
119 | //======================================================================= |
120 | //function : Current |
121 | //purpose : |
122 | //======================================================================= |
123 | |
124 | const TopoDS_Shape& TopExp_Explorer::Current()const |
125 | { |
126 | Standard_NoSuchObject_Raise_if(!hasMore,"TopExp_Explorer::Current"); |
127 | if (myTop >= 0) { |
128 | const TopoDS_Shape& S = myStack[myTop].Value(); |
129 | return S; |
130 | } |
131 | else |
132 | return myShape; |
133 | } |
134 | |
135 | |
136 | //======================================================================= |
137 | //function : Next |
138 | //purpose : |
139 | //======================================================================= |
140 | |
141 | #ifdef WNT |
142 | #pragma warning(push) |
143 | #pragma warning(disable: 4291) // to avoid warning when using new(buffer) syntax |
144 | #endif |
145 | |
146 | void TopExp_Explorer::Next() |
147 | { |
148 | Standard_Integer NewSize; |
149 | TopoDS_Shape ShapTop; |
150 | TopAbs_ShapeEnum ty; |
151 | Standard_NoMoreObject_Raise_if(!hasMore,"TopExp_Explorer::Next"); |
152 | |
153 | if (myTop < 0) { |
154 | // empty stack. Entering the initial shape. |
155 | ty = myShape.ShapeType(); |
156 | |
157 | if (SAMETYPE(toFind,ty)) { |
158 | // already visited once |
159 | hasMore = Standard_False; |
160 | return; |
161 | } |
162 | else if (AVOID(toAvoid,ty)) { |
163 | // avoid the top-level |
164 | hasMore = Standard_False; |
165 | return; |
166 | } |
167 | else { |
168 | // push and try to find |
169 | if(++myTop >= mySizeOfStack) { |
170 | NewSize = mySizeOfStack + theStackSize; |
171 | TopExp_Stack newStack = (TopoDS_Iterator*)Standard::Allocate(NewSize*sizeof(TopoDS_Iterator)); |
172 | Standard_Integer i; |
173 | for ( i =0; i < myTop; i++) { |
174 | new (&newStack[i]) TopoDS_Iterator(myStack[i]); |
175 | myStack[i].~TopoDS_Iterator(); |
176 | } |
547702a1 |
177 | Standard::Free(myStack); |
7fd59977 |
178 | mySizeOfStack = NewSize; |
179 | myStack = newStack; |
180 | } |
181 | new (&myStack[myTop]) TopoDS_Iterator(myShape); |
182 | } |
183 | } |
184 | else myStack[myTop].Next(); |
185 | |
186 | for (;;) { |
187 | if (myStack[myTop].More()) { |
188 | ShapTop = myStack[myTop].Value(); |
189 | ty = ShapTop.ShapeType(); |
190 | if (SAMETYPE(toFind,ty)) { |
191 | hasMore = Standard_True; |
192 | return; |
193 | } |
194 | else if (LESSCOMPLEX(toFind,ty) && !AVOID(toAvoid,ty)) { |
195 | if(++myTop >= mySizeOfStack) { |
196 | NewSize = mySizeOfStack + theStackSize; |
197 | TopExp_Stack newStack = (TopoDS_Iterator*)Standard::Allocate(NewSize*sizeof(TopoDS_Iterator)); |
198 | Standard_Integer i; |
199 | for (i =0; i < myTop; i++) { |
200 | new (&newStack[i]) TopoDS_Iterator(myStack[i]); |
201 | myStack[i].~TopoDS_Iterator(); |
202 | } |
547702a1 |
203 | Standard::Free(myStack); |
7fd59977 |
204 | mySizeOfStack = NewSize; |
205 | myStack = newStack; |
206 | } |
207 | new (&myStack[myTop]) TopoDS_Iterator(ShapTop); |
208 | } |
209 | else { |
210 | myStack[myTop].Next(); |
211 | } |
212 | } |
213 | else { |
214 | myStack[myTop].~TopoDS_Iterator(); |
215 | myTop--; |
216 | if(myTop < 0) break; |
217 | myStack[myTop].Next(); |
218 | } |
219 | } |
220 | hasMore = Standard_False; |
221 | } |
222 | |
223 | #ifdef WNT |
224 | #pragma warning(pop) |
225 | #endif |
226 | |
227 | //======================================================================= |
228 | //function : ReInit |
229 | //purpose : |
230 | //======================================================================= |
231 | |
232 | void TopExp_Explorer::ReInit() |
233 | { |
234 | Init(myShape,toFind,toAvoid); |
235 | } |
236 | |
237 | void TopExp_Explorer::Destroy() |
238 | { |
239 | if (myStack) |
240 | { |
241 | for(int i=0;i<= myTop; i++)myStack[i].~TopoDS_Iterator(); |
547702a1 |
242 | Standard::Free(myStack); |
7fd59977 |
243 | } |
244 | mySizeOfStack = 0; |
245 | myStack = 0L; |
246 | } |
247 | |