b311480e |
1 | // Created on: 1999-01-13 |
2 | // Created by: Xuan PHAM PHU |
3 | // Copyright (c) 1999-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 | #include <TopOpeBRepTool_CLASSI.ixx> |
18 | #include <TopOpeBRepTool_define.hxx> |
19 | #include <TopOpeBRepTool_EXPORT.hxx> |
20 | #include <TopOpeBRepTool_TOOL.hxx> |
21 | #include <TopOpeBRepTool_2d.hxx> |
22 | #include <TopExp_Explorer.hxx> |
23 | #include <Bnd_Array1OfBox2d.hxx> |
24 | #include <Bnd_Box2d.hxx> |
25 | #include <TColStd_Array2OfReal.hxx> |
26 | #include <BndLib_Add2dCurve.hxx> |
27 | #include <BRepAdaptor_Curve2d.hxx> |
28 | #include <BRepClass3d_SolidExplorer.hxx> |
29 | #include <BRepClass_FaceClassifier.hxx> |
30 | #include <TopoDS.hxx> |
31 | #include <BRep_Tool.hxx> |
32 | |
33 | #define SAME (-1) |
34 | #define DIFF (-2) |
35 | #define UNKNOWN ( 0) |
36 | #define oneINtwo ( 1) |
37 | #define twoINone ( 2) |
38 | |
39 | #define M_IN(st ) (st == TopAbs_IN ) |
40 | #define M_OUT(st) (st == TopAbs_OUT) |
41 | |
42 | //======================================================================= |
43 | //function : TopOpeBRepTool_CLASSI |
44 | //purpose : |
45 | //======================================================================= |
46 | |
47 | TopOpeBRepTool_CLASSI::TopOpeBRepTool_CLASSI() |
48 | { |
49 | } |
50 | |
51 | //======================================================================= |
52 | //function : Init2d |
53 | //purpose : |
54 | //======================================================================= |
55 | |
56 | void TopOpeBRepTool_CLASSI::Init2d(const TopoDS_Face& Fref) |
57 | { |
58 | myFref = Fref; |
59 | } |
60 | |
61 | //======================================================================= |
62 | //function : HasInit2d |
63 | //purpose : |
64 | //======================================================================= |
65 | |
66 | Standard_Boolean TopOpeBRepTool_CLASSI::HasInit2d() const |
67 | { |
68 | return (!myFref.IsNull()); |
69 | } |
70 | |
71 | |
72 | |
73 | //======================================================================= |
74 | //function : Add2d |
75 | //purpose : |
76 | //======================================================================= |
77 | |
78 | Standard_Boolean TopOpeBRepTool_CLASSI::Add2d(const TopoDS_Shape& S) |
79 | { |
80 | if (!HasInit2d()) return Standard_False; |
81 | |
82 | Standard_Boolean isb = mymapsbox2d.Contains(S); |
83 | if (isb) return Standard_True; |
84 | |
85 | Bnd_Box2d B2d; |
86 | TopExp_Explorer exe(S, TopAbs_EDGE); |
87 | for (; exe.More(); exe.Next()){ |
88 | const TopoDS_Edge& E = TopoDS::Edge(exe.Current()); |
89 | Standard_Real tolE = BRep_Tool::Tolerance(E); |
90 | |
91 | Standard_Boolean haspc = FC2D_HasCurveOnSurface(E,myFref); |
92 | if (!haspc) return Standard_False; |
93 | BRepAdaptor_Curve2d BC2d(E,myFref); |
94 | Standard_Real tol2d = BC2d.Resolution(tolE); |
95 | BndLib_Add2dCurve::Add(BC2d,tol2d,B2d); |
96 | } |
97 | mymapsbox2d.Add(S,B2d); |
98 | return Standard_True; |
99 | } |
100 | |
101 | //======================================================================= |
102 | //function : GetBox2d |
103 | //purpose : |
104 | //======================================================================= |
105 | |
106 | Standard_Boolean TopOpeBRepTool_CLASSI::GetBox2d(const TopoDS_Shape& S, Bnd_Box2d& B2d) |
107 | { |
108 | Standard_Boolean isb = mymapsbox2d.Contains(S); |
109 | if (!isb) isb = Add2d(S); |
110 | if (!isb) return Standard_False; |
111 | B2d = mymapsbox2d.FindFromKey(S); |
112 | return Standard_True; |
113 | } |
114 | |
115 | //======================================================================= |
116 | //function : ClassiBnd2d |
117 | //purpose : |
118 | //======================================================================= |
119 | |
120 | Standard_Integer TopOpeBRepTool_CLASSI::ClassiBnd2d(const TopoDS_Shape& S1,const TopoDS_Shape& S2, |
121 | const Standard_Real tol,const Standard_Boolean chklarge) |
122 | { |
123 | Bnd_Array1OfBox2d B(1,2); |
124 | Standard_Boolean isb = mymapsbox2d.Contains(S1); |
125 | if (!isb) isb = Add2d(S1); |
126 | if (!isb) return Standard_False; |
127 | B(1) = mymapsbox2d.FindFromKey(S1); |
128 | isb = mymapsbox2d.Contains(S2); |
129 | if (!isb) isb = Add2d(S2); |
130 | if (!isb) return Standard_False; |
131 | B(2) = mymapsbox2d.FindFromKey(S2); |
132 | |
133 | TColStd_Array2OfReal UV(1,2, 1,4); |
134 | // for (Standard_Integer i = 1; i <= 2; i++) |
135 | Standard_Integer i ; |
136 | for ( i = 1; i <= 2; i++) |
137 | // (Umin(i), Vmin(i), Umax(i), Vmax(i)) |
138 | B(i).Get(UV(i,1), UV(i,3), UV(i,2), UV(i,4)); |
139 | |
0797d9d3 |
140 | #ifdef OCCT_DEBUG |
7fd59977 |
141 | Standard_Boolean trc = Standard_False; |
142 | if (trc) { |
143 | for (Standard_Integer i = 1; i <= 2; i++) |
144 | cout<<"B("<<i<<") = ("<<UV(i,1)<<" "<<UV(i,3)<<" "<<UV(i,2)<<" "<<UV(i,4)<<")"<<endl; |
145 | } |
146 | #endif |
147 | |
148 | for (Standard_Integer k = 1; k <= 3; k+=2) { |
149 | for (i = 1; i <= 2; i++) { |
150 | Standard_Integer ii = i, jj = (i == 1) ? 2 : 1; |
151 | // diff = Umin<ii> - Umax<jj> : k = 1 |
152 | // diff = Vmin<ii> - Vmax<jj> : k = 3 |
153 | Standard_Real diff = UV(ii,k) - UV(jj,k+1); |
154 | // IMPORTANT : for splitted faces sharing same edge, use |
155 | // chklarge = True. |
156 | Standard_Boolean disjoint = chklarge ? (diff >= -tol) : (diff > 0.); |
157 | if (disjoint) return DIFF; |
158 | } |
159 | } |
160 | |
161 | for (i = 1; i <= 2; i++) { |
162 | // comparing Bnd2d(ii) with Bnd2d(jj) |
163 | Standard_Integer ii = i, jj = (i == 1) ? 2 : 1; |
164 | Standard_Boolean smaller=Standard_True, same=Standard_True; |
165 | |
166 | // for (Standard_Integer k = 1; k <= 3; k += 2){ |
167 | Standard_Integer k ; |
168 | for ( k = 1; k <= 3; k += 2){ |
169 | // diff = Umin<ii> - Umin<jj> : k = 1 |
170 | // diff = Vmin<ii> - Vmin<jj> : k = 3 |
171 | Standard_Real diff = UV(ii,k) - UV(jj,k); |
172 | smaller = chklarge ? (smaller && (diff > -tol)) : (smaller && (diff > 0.)); |
173 | same = same && (Abs(diff) <= tol); |
174 | } |
175 | for (k = 2; k <= 4; k +=2){ |
176 | // diff = Umax<ii> - Umax<jj> : k = 2 |
177 | // diff = Vmax<ii> - Vmax<jj> : k = 4 |
178 | Standard_Real diff = UV(ii,k) - UV(jj,k); |
179 | smaller = chklarge ? (smaller && (diff < tol)) : (smaller && (diff < 0.)); |
180 | same = same && (Abs(diff) <= tol); |
181 | } |
182 | |
183 | if (same) return SAME; |
184 | if (smaller) { |
185 | Standard_Integer sta = (ii==1) ? oneINtwo : twoINone; |
186 | return sta; |
187 | } |
188 | } |
189 | return UNKNOWN; |
190 | } |
191 | |
192 | static Standard_Integer FUN_thegreatest(const TopoDS_Face& F1, BRepClass_FaceClassifier& class2) |
193 | // prequesitory : p2d1 IN f2, p2d2 IN f1 |
194 | // class2 for f2 |
195 | // returns oneINtwo || twoINone || UNKNOWN |
196 | { |
197 | TopExp_Explorer ex1(F1, TopAbs_EDGE); |
198 | Standard_Real tolf1 = BRep_Tool::Tolerance(F1); |
199 | for (; ex1.More(); ex1.Next()){ |
200 | const TopoDS_Edge& e1 = TopoDS::Edge(ex1.Current()); |
201 | Standard_Real f1,l1; FUN_tool_bounds(e1,f1,l1); |
202 | Standard_Real x= 0.45678; Standard_Real p1 = (1-x)*f1+x+l1; |
203 | gp_Pnt2d uv1; Standard_Boolean ok1 = FUN_tool_paronEF(e1,p1,F1,uv1,tolf1); |
204 | if (!ok1) continue; |
205 | TopAbs_State sta12 = class2.State(); |
206 | if (M_IN(sta12) ) return oneINtwo; |
207 | else if (M_OUT(sta12)) return twoINone; |
208 | } |
209 | return UNKNOWN; |
210 | } |
211 | |
212 | //======================================================================= |
213 | //function : Classip2d |
214 | //purpose : |
215 | //======================================================================= |
216 | |
217 | Standard_Integer TopOpeBRepTool_CLASSI::Classip2d(const TopoDS_Shape& S1, const TopoDS_Shape& S2, |
218 | const Standard_Integer stabnd2d12) |
219 | { |
220 | if (!HasInit2d()) return UNKNOWN; |
221 | Standard_Boolean bnd2dUNK = (stabnd2d12 == UNKNOWN)||(stabnd2d12 == SAME); |
222 | |
223 | // fa1,ffi1,finite1 : |
224 | TopOpeBRepTool_face fa1; |
225 | Standard_Boolean isb1 = mymapsface.IsBound(S1); |
226 | if (isb1) fa1 = mymapsface.Find(S1); |
227 | else { |
228 | Standard_Boolean ok1 = fa1.Init(TopoDS::Wire(S1), myFref); |
229 | if (!ok1) return UNKNOWN; |
230 | mymapsface.Bind(S1,fa1); |
231 | } |
232 | const TopoDS_Face& ffi1 = fa1.Ffinite(); |
233 | Standard_Boolean finite1 = fa1.Finite(); |
234 | |
235 | // fa2,ffi2,finite2 : |
236 | TopOpeBRepTool_face fa2; |
237 | Standard_Boolean isb2 = mymapsface.IsBound(S2); |
238 | if (isb2) fa2 = mymapsface.Find(S2); |
239 | else { |
240 | Standard_Boolean ok2 = fa2.Init(TopoDS::Wire(S2), myFref); |
241 | if (!ok2) return UNKNOWN; |
242 | mymapsface.Bind(S2,fa2); |
243 | } |
244 | const TopoDS_Face& ffi2 = fa2.Ffinite(); |
245 | Standard_Boolean finite2 = fa2.Finite(); |
246 | |
247 | // p2d1 : |
248 | Standard_Real u1,v1; Standard_Boolean ok1 = BRepClass3d_SolidExplorer::FindAPointInTheFace(ffi1,u1,v1); |
249 | if (!ok1) return UNKNOWN; |
250 | gp_Pnt2d p2d1(u1,v1); |
251 | |
252 | // sta12 = status(p2d1 / ffi2) : |
253 | // recall : ffi1 and ffi2 are built on same face |
254 | // => ffi1(u1,v1) = ffi2(u1,v1) |
255 | // ---------------------------- |
256 | Standard_Real tol2d2 = TopOpeBRepTool_TOOL::TolUV(ffi2,BRep_Tool::Tolerance(ffi2)); |
257 | BRepClass_FaceClassifier class2(ffi2,p2d1,tol2d2); |
258 | TopAbs_State sta12 = class2.State(); |
259 | |
260 | // staffi12 : only if !bnd2dUNK and stabnd2d12!=DIFF |
261 | // PREQUESITORY : the only possible situations are |
262 | // - ffi1 IN ffi2 |
263 | // - ffi2 IN ffi1 |
264 | // - ffi1 and ffi2 are distinct |
265 | Standard_Integer staffi12 = UNKNOWN; |
266 | |
267 | Standard_Boolean try21 = Standard_False; |
268 | if (bnd2dUNK) { |
269 | try21 = Standard_True; |
270 | } |
271 | else if (stabnd2d12 == DIFF) { |
272 | return DIFF; |
273 | } |
274 | else { |
275 | if (sta12 == TopAbs_IN) {// 2 possible states : oneINtwo || twoINone |
276 | if (stabnd2d12 == oneINtwo) staffi12 = oneINtwo; //Bnd2d(S1) IN Bnd2d(S2) |
277 | else if (stabnd2d12 == twoINone) staffi12 = twoINone; //Bnd2d(S2) IN Bnd2d(S1) |
278 | else try21 = Standard_True; |
279 | } |
280 | else if (sta12 == TopAbs_OUT) {// 2 possible states : twoINone || DIFF |
281 | if (stabnd2d12 == twoINone) staffi12 = twoINone; |
282 | // else if (stabnd2d12 == DIFF) staffi12 = DIFF; |
283 | else try21 = Standard_True; |
284 | } |
285 | else return UNKNOWN; // NYIxpu140199 |
286 | } |
287 | |
288 | if (try21) { |
289 | // p2d2 : |
290 | Standard_Real u2,v2; Standard_Boolean ok2 = BRepClass3d_SolidExplorer::FindAPointInTheFace(ffi2,u2,v2); |
291 | if (!ok2) return UNKNOWN; |
292 | gp_Pnt2d p2d2(u2,v2); |
293 | |
294 | // sta21 : |
295 | Standard_Real tol2d1 = TopOpeBRepTool_TOOL::TolUV(ffi1,BRep_Tool::Tolerance(ffi1)); |
296 | BRepClass_FaceClassifier class1(ffi1,p2d2,tol2d1); |
297 | TopAbs_State sta21 = class1.State(); |
298 | |
299 | if (bnd2dUNK) { |
300 | if (M_OUT(sta12)&& M_OUT(sta21)) staffi12 = DIFF; |
301 | else if (M_IN(sta12) && M_OUT(sta21)) staffi12 = oneINtwo; |
302 | else if (M_OUT(sta12)&& M_IN(sta21) ) staffi12 = twoINone; |
303 | else if (M_IN(sta12) && M_IN(sta21) ) staffi12 = ::FUN_thegreatest(ffi1,class2); |
304 | } |
305 | else { |
306 | if (sta12 == TopAbs_IN) {// 2 possible states : oneINtwo || twoINone |
307 | if (sta21 == TopAbs_OUT) staffi12 = oneINtwo; |
308 | } |
309 | else if (sta12 == TopAbs_OUT) {// 2 possible states : twoINone || DIFF |
310 | if (sta21 == TopAbs_OUT) staffi12 = DIFF; |
311 | else if (sta21 == TopAbs_IN) staffi12 = twoINone; |
312 | } |
313 | else return UNKNOWN; // NYIxpu140199 |
314 | } |
315 | }//try21 |
316 | |
317 | |
318 | // classif(S1,S2) knowing staffi12, finite, finite2 : |
319 | if (staffi12 == DIFF) { |
320 | if (finite1 && finite2) return DIFF; |
321 | if (finite1 && !finite2) return twoINone; |
322 | if (!finite1 && finite2) return oneINtwo; |
323 | return oneINtwo; // !!!!!!! or twoINone |
324 | } |
325 | else if (staffi12 == oneINtwo) { |
326 | if (!finite1 && !finite2) return twoINone; |
327 | return oneINtwo; |
328 | } |
329 | else if (staffi12 == twoINone) { |
330 | if (!finite1 && !finite2) return oneINtwo; |
331 | return twoINone; |
332 | } |
333 | return UNKNOWN; |
334 | } |
335 | |
336 | //======================================================================= |
337 | //function : Getface |
338 | //purpose : |
339 | //======================================================================= |
340 | |
341 | Standard_Boolean TopOpeBRepTool_CLASSI::Getface(const TopoDS_Shape& S, TopOpeBRepTool_face& fa) const |
342 | { |
343 | Standard_Boolean isb = mymapsface.IsBound(S); |
344 | if (!isb) return Standard_False; |
345 | fa = mymapsface.Find(S); |
346 | return Standard_True; |
347 | } |
348 | |
349 | |
350 | //======================================================================= |
351 | //function : Classilist |
352 | //purpose : |
353 | //======================================================================= |
354 | |
355 | Standard_EXPORT void FUN_addOwlw(const TopoDS_Shape& Ow, const TopTools_ListOfShape& lw, TopTools_ListOfShape& lresu) |
356 | { |
357 | Standard_Integer nw = lw.Extent(); |
358 | if (nw == 0) lresu.Append(Ow); |
359 | else { |
360 | TopTools_ListIteratorOfListOfShape it(lw); |
361 | for (; it.More(); it.Next()) lresu.Append(it.Value()); |
362 | } |
363 | } |
364 | |
365 | Standard_Boolean TopOpeBRepTool_CLASSI::Classilist(const TopTools_ListOfShape& lS, TopTools_DataMapOfShapeListOfShape& mapgreasma) |
366 | { |
367 | Standard_Real tolref = BRep_Tool::Tolerance(myFref); |
368 | Standard_Real toluv = TopOpeBRepTool_TOOL::TolUV(myFref,tolref);//nyixpu : cdliser?? |
369 | TopTools_ListOfShape null; |
370 | |
371 | TopTools_ListOfShape lw; lw.Assign(lS); |
372 | mapgreasma.Clear(); |
373 | TopTools_ListIteratorOfListOfShape itw(lS); |
374 | for (; itw.More(); itw.Next()) mapgreasma.Bind(itw.Value(),null); |
375 | |
376 | Standard_Integer nw = lw.Extent(); |
377 | if (nw <= 1) return Standard_True; |
378 | |
379 | Standard_Integer nite = 0, nitemax = Standard_Integer(nw*(nw-1)/2); |
380 | while (nite <= nitemax){ |
381 | nw = lw.Extent(); |
382 | if (nw <= 1) break; |
383 | |
384 | // wi1 : |
385 | TopoDS_Shape wi1; |
386 | TopTools_ListIteratorOfListOfShape itw(lw); |
387 | for (; itw.More(); itw.Next()){ |
388 | wi1 = itw.Value(); |
389 | Standard_Boolean isb1 = mapgreasma.IsBound(wi1); |
390 | if (!isb1) continue; // wi1 stored as smaller shape |
391 | break; |
392 | } |
393 | |
394 | while (itw.More()) {// compare wi1 with all wi(k) (k>1) |
395 | Standard_Boolean isb1 = mapgreasma.IsBound(wi1); |
396 | if (!isb1) break; |
397 | |
398 | itw.Next(); |
399 | if (!itw.More()) break; |
400 | |
401 | // wi2, sta12 : |
402 | Standard_Integer sta12 = UNKNOWN; |
403 | Standard_Boolean OUTall = Standard_False; |
404 | TopoDS_Shape wi2; |
405 | for (; itw.More(); itw.Next()){ |
406 | wi2 = itw.Value(); |
407 | Standard_Boolean isb2 = mapgreasma.IsBound(wi2); |
408 | if (!isb2) continue; |
409 | |
410 | Standard_Integer stabnd2d12 = ClassiBnd2d(wi1,wi2,toluv,Standard_True); |
411 | sta12 = Classip2d(wi1,wi2, stabnd2d12); |
412 | if (sta12 == DIFF) {OUTall = Standard_True; continue;} |
413 | break; |
414 | } |
415 | |
416 | // mapgreasma : |
417 | if (sta12 == oneINtwo) {//greater = shape two |
418 | TopTools_ListOfShape& lwgre = mapgreasma.ChangeFind(wi2); |
419 | TopTools_ListOfShape lsma; FUN_addOwlw(wi1,mapgreasma.Find(wi1),lsma); |
420 | mapgreasma.UnBind(wi1); |
421 | lwgre.Append(lsma); |
422 | } |
423 | else if (sta12 == twoINone) {//greater = shape one |
424 | TopTools_ListOfShape& lwgre = mapgreasma.ChangeFind(wi1); |
425 | TopTools_ListOfShape lsma; FUN_addOwlw(wi2,mapgreasma.Find(wi2),lsma); |
426 | mapgreasma.UnBind(wi2); |
427 | lwgre.Append(lsma); |
428 | } |
429 | else if (OUTall) { |
430 | // nothing's done |
431 | } |
432 | else return Standard_False; |
433 | }//itw.More() |
434 | |
435 | lw.RemoveFirst(); |
436 | }//nite<=nmax |
437 | return Standard_True; |
438 | } |
439 | |
440 | |
441 | |
442 | |
443 | |
444 | |