b311480e |
1 | // Created on: 1999-01-04 |
2 | // Created by: Xuan PHAM PHU |
3 | // Copyright (c) 1997-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 | |
42cf5bc1 |
17 | |
7fd59977 |
18 | #include <BRep_Tool.hxx> |
19 | #include <Precision.hxx> |
7fd59977 |
20 | #include <TopExp.hxx> |
42cf5bc1 |
21 | #include <TopExp_Explorer.hxx> |
22 | #include <TopoDS.hxx> |
23 | #include <TopoDS_Edge.hxx> |
24 | #include <TopoDS_Face.hxx> |
25 | #include <TopoDS_Shape.hxx> |
26 | #include <TopoDS_Shell.hxx> |
7fd59977 |
27 | #include <TopOpeBRepTool_CLASSI.hxx> |
7fd59977 |
28 | #include <TopOpeBRepTool_connexity.hxx> |
42cf5bc1 |
29 | #include <TopOpeBRepTool_define.hxx> |
30 | #include <TopOpeBRepTool_EXPORT.hxx> |
31 | #include <TopOpeBRepTool_REGUS.hxx> |
32 | #include <TopOpeBRepTool_REGUW.hxx> |
33 | #include <TopOpeBRepTool_TOOL.hxx> |
7fd59977 |
34 | |
35 | #ifdef DRAW |
36 | #include <TopOpeBRepTool_DRAW.hxx> |
37 | #endif |
38 | |
39 | #define M_FORWARD(ori) (ori == TopAbs_FORWARD) |
40 | #define M_REVERSED(ori) (ori == TopAbs_REVERSED) |
41 | #define M_INTERNAL(ori) (ori == TopAbs_INTERNAL) |
42 | #define M_EXTERNAL(ori) (ori == TopAbs_EXTERNAL) |
43 | |
44 | #define FORWARD (1) |
45 | #define REVERSED (2) |
46 | #define INTERNAL (3) |
47 | #define EXTERNAL (4) |
48 | #define CLOSING (5) |
49 | |
0797d9d3 |
50 | #ifdef OCCT_DEBUG |
1d0a9d4d |
51 | extern Standard_Boolean TopOpeBRepTool_GettraceREGUSO(); |
7fd59977 |
52 | static TopTools_IndexedMapOfShape STATIC_mape, STATIC_mapf, STATIC_mapw, STATIC_mapsh; |
53 | static Standard_Integer FUN_adds(const TopoDS_Shape& s) { |
54 | TopAbs_ShapeEnum typ = s.ShapeType(); |
55 | TCollection_AsciiString aa; Standard_Integer is = 0; |
56 | if (typ == TopAbs_SHELL) {aa = TCollection_AsciiString("s"); is = STATIC_mapsh.Add(s);} |
57 | if (typ == TopAbs_WIRE) {aa = TCollection_AsciiString("w"); is = STATIC_mapw.Add(s); } |
58 | if (typ == TopAbs_FACE) {aa = TCollection_AsciiString("f"); is = STATIC_mapf.Add(s); } |
59 | if (typ == TopAbs_EDGE) {aa = TCollection_AsciiString("e"); is = STATIC_mape.Add(s); } |
60 | #ifdef DRAW |
61 | Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO(); |
62 | if (trc) FUN_tool_draw(aa,s,is); |
63 | #endif |
64 | return is; |
65 | } |
66 | #endif |
67 | |
68 | static void FUN_Raise() |
69 | { |
0797d9d3 |
70 | #ifdef OCCT_DEBUG |
7fd59977 |
71 | Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO(); |
72 | if (trc) cout<<"***** Failure in REGUS **********"<<endl; |
9775fa61 |
73 | // throw Standard_Failure("REGUS"); |
7fd59977 |
74 | #endif |
75 | } |
76 | |
77 | //======================================================================= |
78 | //function : Create |
79 | //purpose : |
80 | //======================================================================= |
81 | |
82 | TopOpeBRepTool_REGUS::TopOpeBRepTool_REGUS() |
83 | { |
84 | hasnewsplits = Standard_False; |
85 | mynF = myoldnF = 0; |
86 | |
87 | myFsplits.Clear(); |
88 | myOshNsh.Clear(); |
89 | |
90 | myS.Nullify(); |
91 | mymapeFs.Clear(); |
92 | mymapeFsstatic.Clear(); |
93 | mymapemult.Clear(); |
94 | |
95 | myedstoconnect.Clear(); |
96 | } |
97 | |
98 | //======================================================================= |
99 | //function : Init |
100 | //purpose : |
101 | //======================================================================= |
102 | |
103 | void TopOpeBRepTool_REGUS::Init(const TopoDS_Shape& S) |
104 | { |
105 | hasnewsplits = Standard_False; |
106 | |
107 | mynF = myoldnF = 0; |
108 | myS = S; |
109 | |
110 | mymapeFs.Clear(); |
111 | mymapeFsstatic.Clear(); |
112 | mymapemult.Clear(); |
113 | myedstoconnect.Clear(); |
114 | } |
115 | |
116 | //======================================================================= |
117 | //function : S |
118 | //purpose : |
119 | //======================================================================= |
120 | |
121 | const TopoDS_Shape& TopOpeBRepTool_REGUS::S() const |
122 | { |
123 | return myS; |
124 | } |
125 | |
126 | |
127 | //======================================================================= |
128 | //function : SetFsplits |
129 | //purpose : |
130 | //======================================================================= |
131 | |
132 | void TopOpeBRepTool_REGUS::SetFsplits(TopTools_DataMapOfShapeListOfShape& Fsplits) |
133 | { |
134 | myFsplits = Fsplits; |
135 | } |
136 | //======================================================================= |
137 | //function : GetFsplits |
138 | //purpose : |
139 | //======================================================================= |
140 | |
141 | void TopOpeBRepTool_REGUS::GetFsplits(TopTools_DataMapOfShapeListOfShape& Fsplits) const |
142 | { |
143 | Fsplits = myFsplits; |
144 | } |
145 | |
146 | //======================================================================= |
147 | //function : SetOshNsh |
148 | //purpose : |
149 | //======================================================================= |
150 | |
151 | void TopOpeBRepTool_REGUS::SetOshNsh(TopTools_DataMapOfShapeListOfShape& OshNsh) |
152 | { |
153 | myOshNsh = OshNsh; |
154 | } |
155 | //======================================================================= |
156 | //function : GetOshNsh |
157 | //purpose : |
158 | //======================================================================= |
159 | |
160 | void TopOpeBRepTool_REGUS::GetOshNsh(TopTools_DataMapOfShapeListOfShape& OshNsh) const |
161 | { |
162 | OshNsh = myOshNsh; |
163 | } |
164 | |
165 | //======================================================================= |
166 | //function : MapS |
167 | //purpose : |
168 | //======================================================================= |
169 | |
170 | Standard_Boolean TopOpeBRepTool_REGUS::MapS() |
171 | { |
0797d9d3 |
172 | #ifdef OCCT_DEBUG |
7fd59977 |
173 | Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO(); |
174 | Standard_Integer ish = FUN_adds(S()); |
175 | if (trc) cout<<"** MAPPING ** shape"<<ish<<endl; |
176 | #endif |
177 | |
178 | // mymapeFs, myoldnF : |
179 | myoldnF = 0; |
180 | TopExp_Explorer exf(myS, TopAbs_FACE); |
181 | for (; exf.More(); exf.Next()){ |
182 | const TopoDS_Shape& f = exf.Current(); myoldnF++; |
183 | |
184 | TopExp_Explorer exe(f, TopAbs_EDGE); |
185 | for (; exe.More(); exe.Next()){ |
186 | const TopoDS_Shape& e = exe.Current(); |
187 | Standard_Boolean isb = mymapeFs.IsBound(e); |
188 | if (isb) {mymapeFs.ChangeFind(e).Append(f); mymapeFsstatic.ChangeFind(e).Append(f);} |
189 | else {TopTools_ListOfShape lof; lof.Append(f); mymapeFs.Bind(e,lof); mymapeFsstatic.Bind(e,lof);} |
190 | }//exe |
191 | }//exf |
192 | mynF = myoldnF; |
193 | |
194 | // mymapemult : |
195 | TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(mymapeFs); |
196 | for (; itm.More(); itm.Next()){ |
197 | const TopoDS_Shape& e = itm.Key(); |
198 | const TopTools_ListOfShape& lof = itm.Value(); |
199 | Standard_Integer nf = lof.Extent(); |
200 | if (nf > 2) mymapemult.Add(e); |
0797d9d3 |
201 | #ifdef OCCT_DEBUG |
7fd59977 |
202 | if (trc) { |
203 | cout <<"co(e"<<FUN_adds(e)<<")= "; |
204 | TopTools_ListIteratorOfListOfShape it(lof); |
205 | for (; it.More(); it.Next())cout<<" f"<<FUN_adds(it.Value()); |
206 | cout<<endl;} |
207 | #endif |
208 | }//itm(mymapeFs) |
209 | return Standard_True; |
210 | } |
211 | |
212 | //======================================================================= |
213 | //function : WireToFace |
214 | //purpose : |
215 | //======================================================================= |
216 | |
217 | Standard_Boolean TopOpeBRepTool_REGUS::WireToFace(const TopoDS_Face& Fanc, const TopTools_ListOfShape& nWs, TopTools_ListOfShape& nFs) |
218 | { |
0797d9d3 |
219 | #ifdef OCCT_DEBUG |
7fd59977 |
220 | Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO(); |
221 | #endif |
222 | nFs.Clear(); |
223 | TopTools_DataMapOfShapeListOfShape mapWlow; |
224 | TopoDS_Shape aLocalShape = Fanc.Oriented(TopAbs_FORWARD); |
225 | TopoDS_Face aFace = TopoDS::Face(aLocalShape); |
226 | // TopoDS_Face aFace = TopoDS::Face(Fanc.Oriented(TopAbs_FORWARD)); |
227 | TopOpeBRepTool_CLASSI classi; classi.Init2d(aFace); |
228 | |
229 | Standard_Boolean classifok = classi.Classilist(nWs,mapWlow); |
230 | if (!classifok) { |
0797d9d3 |
231 | #ifdef OCCT_DEBUG |
7fd59977 |
232 | if (trc) cout<<"** classif fails"<<endl; |
233 | #endif |
234 | return Standard_False; |
235 | } |
236 | |
237 | Standard_Boolean facesbuilt = TopOpeBRepTool_TOOL::WireToFace(Fanc, mapWlow, nFs); |
238 | if (!facesbuilt) { |
0797d9d3 |
239 | #ifdef OCCT_DEBUG |
7fd59977 |
240 | if (trc) cout<<"** facesbuilt fails"<<endl; |
241 | #endif |
242 | return Standard_False; |
243 | } |
244 | return Standard_True; |
245 | } |
246 | |
247 | |
248 | //======================================================================= |
249 | //function : SplitF |
250 | //purpose : |
251 | //======================================================================= |
252 | |
253 | Standard_Boolean TopOpeBRepTool_REGUS::SplitF(const TopoDS_Face& Fanc, TopTools_ListOfShape& FSplits) |
254 | { |
255 | // prequesitory : All edges have already been splitted, there is no |
256 | // internal vertex on edge, except for internal edge. |
257 | TopAbs_Orientation oAnc = Fanc.Orientation(); |
51740958 |
258 | TopoDS_Shape aLocalShapeFromFace = Fanc.Oriented(TopAbs_FORWARD); |
259 | TopoDS_Face aFace = TopoDS::Face(aLocalShapeFromFace); |
7fd59977 |
260 | // TopoDS_Face aFace = TopoDS::Face(Fanc.Oriented(TopAbs_FORWARD)); |
261 | |
262 | FSplits.Clear(); |
263 | |
264 | TopOpeBRepTool_REGUW REGUW(aFace); |
265 | |
266 | TopTools_ListOfShape nWs; Standard_Boolean hassp = Standard_False; |
267 | TopExp_Explorer exw(aFace, TopAbs_WIRE); |
268 | for (; exw.More(); exw.Next()) { |
269 | const TopoDS_Shape& w = exw.Current(); |
270 | REGUW.Init(w); |
271 | REGUW.MapS(); |
272 | |
273 | TopTools_ListOfShape eIs; |
274 | // -------- |
275 | TopExp_Explorer exe(w, TopAbs_EDGE); |
276 | for (; exe.More(); exe.Next()){ |
277 | const TopoDS_Shape& e = exe.Current(); |
278 | if (M_INTERNAL(e.Orientation())) eIs.Append(e); |
279 | }//exe |
280 | |
281 | TopTools_ListIteratorOfListOfShape ite(eIs); |
282 | // if (!ite.More()) {nWs.Append(w); continue;} |
283 | |
284 | while (ite.More()) { |
285 | const TopoDS_Edge& eI = TopoDS::Edge(ite.Value()); |
286 | TopoDS_Vertex vf,vl; |
287 | TopoDS_Shape aLocalShape = eI.Oriented(TopAbs_FORWARD); |
288 | TopExp::Vertices(TopoDS::Edge(aLocalShape),vf,vl); |
289 | // TopExp::Vertices(TopoDS::Edge(eI.Oriented(TopAbs_FORWARD)),vf,vl); |
290 | TopOpeBRepTool_connexity cof; REGUW.Connexity(vf,cof); TopTools_ListOfShape lef; Standard_Integer nef = cof.AllItems(lef); |
291 | TopOpeBRepTool_connexity col; REGUW.Connexity(vl,col); TopTools_ListOfShape lel; Standard_Integer nel = col.AllItems(lel); |
292 | if ((nef <= 1)||(nel <= 1)) {eIs.Remove(ite);continue;} |
293 | |
294 | // prequesitory : we do not have internal vertices in edges oriented FOR |
295 | aLocalShape = eI.Oriented(TopAbs_REVERSED); |
296 | TopoDS_Edge eR = TopoDS::Edge(aLocalShape); |
297 | aLocalShape = eI.Oriented(TopAbs_FORWARD); |
298 | TopoDS_Edge eF = TopoDS::Edge(aLocalShape); |
299 | // TopoDS_Edge eR = TopoDS::Edge(eI.Oriented(TopAbs_REVERSED)); |
300 | // TopoDS_Edge eF = TopoDS::Edge(eI.Oriented(TopAbs_FORWARD)); |
301 | |
302 | TopExp_Explorer exv(eI, TopAbs_VERTEX); |
303 | for (; exv.More(); exv.Next()){ |
304 | const TopoDS_Vertex& v = TopoDS::Vertex(exv.Current()); |
305 | Standard_Boolean ok = REGUW.RemoveOldConnexity(v,INTERNAL,eI); |
306 | if (!ok) return Standard_False; |
307 | Standard_Integer ivF = TopOpeBRepTool_TOOL::OriinSor(v,eF); |
308 | ok = REGUW.AddNewConnexity(v,ivF,eF); |
309 | if (!ok) return Standard_False; |
310 | Standard_Integer ivR = TopOpeBRepTool_TOOL::OriinSor(v,eR); |
311 | ok = REGUW.AddNewConnexity(v,ivR,eR); |
312 | if (!ok) return Standard_False; |
313 | ok = REGUW.UpdateMultiple(v); |
314 | if (!ok) return Standard_False; |
315 | }//exv |
316 | ite.Next(); |
317 | }//ite(eIs) |
318 | |
319 | // now all edges of <eIs> are INTERNAL edges of <w> |
320 | // their 2 bounds are of connexity > 1. |
321 | // if (eIs.IsEmpty()) {nWs.Append(w); continue;} |
322 | |
323 | TopTools_ListOfShape spW; |
324 | // -------- |
325 | Standard_Boolean spok = REGUW.REGU(); // only first step |
326 | if (!spok) {FUN_Raise(); return Standard_False;} |
327 | REGUW.GetSplits(spW); |
328 | if (!spW.IsEmpty()) {nWs.Append(spW); hassp = Standard_True;} |
329 | }//exw |
330 | |
331 | if (!hassp) return Standard_False; |
332 | TopTools_ListOfShape nFs; Standard_Boolean ok = TopOpeBRepTool_REGUS::WireToFace(aFace, nWs,nFs); |
333 | if (!ok) {FUN_Raise(); return Standard_False;} |
334 | |
335 | TopTools_ListIteratorOfListOfShape itf(nFs); |
336 | for (; itf.More(); itf.Next()) FSplits.Append(itf.Value().Oriented(oAnc)); |
337 | return Standard_True; |
338 | } |
339 | |
340 | //======================================================================= |
341 | //function : SplitFaces |
342 | //purpose : |
343 | //======================================================================= |
344 | |
345 | Standard_Boolean TopOpeBRepTool_REGUS::SplitFaces() |
346 | { |
0797d9d3 |
347 | #ifdef OCCT_DEBUG |
7fd59977 |
348 | Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO(); |
349 | Standard_Integer ish = FUN_adds(S()); |
350 | if (trc) cout<<"** SPLITTING FACES ** shape"<<ish<<endl; |
351 | #endif |
352 | TopExp_Explorer exf(myS, TopAbs_FACE); |
353 | for (; exf.More(); exf.Next()){ |
354 | |
355 | // splitting face : |
356 | const TopoDS_Face& f = TopoDS::Face(exf.Current()); |
357 | TopTools_ListOfShape lfsp; Standard_Boolean issp = TopOpeBRepTool_REGUS::SplitF(f,lfsp); |
6e6cd5d9 |
358 | |
7fd59977 |
359 | if (!issp) continue; |
360 | |
361 | myFsplits.Bind(f,lfsp); |
362 | |
363 | // updating the map of connexity : |
364 | // f -> lfsp = {fsp} |
365 | mynF--; |
366 | TopTools_ListIteratorOfListOfShape itf(lfsp); |
367 | for (; itf.More(); itf.Next()){ |
368 | const TopoDS_Shape& fsp = itf.Value(); mynF++; |
369 | |
370 | TopExp_Explorer exe(fsp, TopAbs_EDGE); |
371 | for (; exe.More(); exe.Next()) { |
372 | // fsp -> {e} |
373 | const TopoDS_Shape& e = exe.Current(); |
374 | Standard_Boolean isb = mymapeFs.IsBound(e); |
375 | if (!isb) {FUN_Raise(); return Standard_False;} |
376 | |
377 | // <mymapeFs> |
378 | TopTools_ListOfShape& lof = mymapeFs.ChangeFind(e); |
379 | TopOpeBRepTool_TOOL::Remove(lof,f); |
380 | lof.Append(fsp); |
381 | |
382 | // <mymapemult> |
383 | Standard_Integer nf = lof.Extent(); |
384 | if (nf > 2) mymapemult.Add(e); |
385 | }//exe(fsp) |
386 | }//itf(lfsp) |
387 | |
0797d9d3 |
388 | #ifdef OCCT_DEBUG |
7fd59977 |
389 | if (trc) { |
390 | cout <<"split(f"<<FUN_adds(f)<<")= "; |
391 | TopTools_ListIteratorOfListOfShape it(lfsp); |
392 | for (; it.More(); it.Next()) cout<<" f"<<FUN_adds(it.Value()); |
393 | cout<<endl;} |
394 | #endif |
395 | }//exf(myS) |
396 | return Standard_True; |
397 | } |
398 | |
399 | static void FUN_update(const TopoDS_Shape& fcur, TopTools_MapOfShape& edstoconnect) |
400 | // purpose : <e> edge of <fcur> |
401 | // 1. <e> is INTERNAL or EXTERNAL -> nothing is done |
402 | // 2. <e> is closing edge of <fcur> -> nothing is done |
403 | // 3. <e> is already bound in <edstoconnect> -> remove it from the map |
404 | // (then has 2 ancestor faces stored in the current Block) |
405 | // 4. elsewhere, add it in the map. |
406 | // |
407 | // !! if <fcur> is INTERNAL/EXTERNAL -> nothing is done |
408 | { |
409 | TopAbs_Orientation ofcur = fcur.Orientation(); |
410 | if (M_INTERNAL(ofcur) || M_EXTERNAL(ofcur)) return; |
411 | |
412 | TopExp_Explorer exe(fcur, TopAbs_EDGE); |
413 | for (; exe.More(); exe.Next()){ |
414 | const TopoDS_Shape& e = exe.Current(); |
415 | TopAbs_Orientation oe = e.Orientation(); |
416 | if (M_INTERNAL(oe) || M_EXTERNAL(oe)) continue; |
417 | |
418 | Standard_Boolean isclo = TopOpeBRepTool_TOOL::IsClosingE(TopoDS::Edge(e),TopoDS::Face(fcur)); |
419 | if (isclo) continue; |
420 | |
421 | Standard_Boolean isb = edstoconnect.Contains(e); |
422 | if (isb) edstoconnect.Remove(e); |
423 | else edstoconnect.Add(e); |
424 | }//exe |
425 | } |
426 | |
427 | //======================================================================= |
428 | //function : REGU |
429 | //purpose : |
430 | //======================================================================= |
431 | |
432 | Standard_Boolean TopOpeBRepTool_REGUS::REGU() |
433 | { |
0797d9d3 |
434 | #ifdef OCCT_DEBUG |
7fd59977 |
435 | Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO(); |
436 | Standard_Integer ishe = FUN_adds(myS); |
437 | if (trc) cout<<"** REGU **"<<ishe<<endl; |
438 | #endif |
439 | TopTools_ListOfShape Splits; |
440 | Standard_Boolean toregu = !mymapemult.IsEmpty() || (mynF != myoldnF); |
441 | if (!toregu) return Standard_False; |
442 | |
443 | // purpose : myS -> {Blocks}, |
444 | // a Block is a closed shell with "valid" edges. |
445 | // - a valid edge in a Block has at most two ancestor faces - |
446 | // |
447 | // Give us the starting couple (<ei>, <fi>) : |
448 | // * If <ei> has only one untouched ancestor face <fj> left, fj+1 <- fj |
449 | // Else among the untouched ancestors faces, we choose the one for which |
450 | // angle (<veci>, <vecj>) is the smallest; providing face <fj> reduces |
451 | // the matter described by <fi>. |
452 | // * update <mymapeFs> for <ei> (<fj> as touched). |
453 | // * Update <mymapemult> for <fi>'s bound edges : |
454 | // - if bound edge is not in the map, add it. |
455 | // - else if bound edge has two ancestor faces in current list <mylFinBlock>, |
456 | // delete it form the map. |
457 | // |
458 | // TopTools_ListOfShape lFinBlock; // <lFinBlock> describes a valid closed shell when <myedstoconnect> is emptied. |
459 | mylFinBlock.Clear(); |
460 | Standard_Integer nite = 0; |
461 | while (nite <= mynF) { |
462 | Standard_Boolean startBlock = mylFinBlock.IsEmpty(); |
463 | Standard_Boolean endBlock = myedstoconnect.IsEmpty() && (!startBlock); |
464 | |
0797d9d3 |
465 | #ifdef OCCT_DEBUG |
7fd59977 |
466 | Standard_Boolean tr=Standard_False; |
467 | if (tr) { |
468 | TopTools_MapIteratorOfMapOfShape it(myedstoconnect); |
469 | cout<<"still to connect : "; |
470 | for (; it.More(); it.Next()) cout<<" e"<<FUN_adds(it.Key()); |
471 | cout<<endl; |
472 | } |
473 | #endif |
474 | |
475 | //* endBlock |
476 | // --------- |
477 | if (endBlock) { |
478 | // building up shell on <mylFinBlock> |
479 | Standard_Integer nFcur = mylFinBlock.Extent(); |
480 | Standard_Boolean unchanged = (nFcur==myoldnF) && (mynF==myoldnF); |
481 | if (unchanged) { |
0797d9d3 |
482 | #ifdef OCCT_DEBUG |
7fd59977 |
483 | if (trc) cout<<"#** shell"<<ishe<<" valid\n"; |
484 | #endif |
485 | return Standard_False; // nyi analysis if we should raise or not |
486 | } |
487 | else { |
488 | TopoDS_Shell newShe; TopOpeBRepTool_TOOL::MkShell(mylFinBlock,newShe); |
489 | Splits.Append(newShe); |
0797d9d3 |
490 | #ifdef OCCT_DEBUG |
7fd59977 |
491 | if (trc) {cout<<"#** shell "<<ishe<<" gives new shell "<<FUN_adds(newShe)<<endl; |
492 | for (TopTools_ListIteratorOfListOfShape it(mylFinBlock); it.More(); it.Next()) cout <<";dins f"<<FUN_adds(it.Value()); |
493 | cout<<endl<<endl;} |
494 | #endif |
495 | mylFinBlock.Clear(); |
496 | startBlock = Standard_True; |
497 | } |
498 | }//endBlock |
499 | |
500 | //* all faces touched |
501 | // ------------------ |
502 | Standard_Boolean FINI = (nite == mynF); |
503 | if (FINI) break; |
504 | |
505 | Standard_Integer advance=Standard_False; |
506 | //* initializing a new Block |
507 | // ------------------------- |
508 | if (startBlock || endBlock) { |
509 | advance = InitBlock(); |
510 | if (!advance) return Standard_False; |
511 | }//startBlock||endBlock |
512 | |
513 | //* choosing next face |
514 | // ------------------- |
515 | else { |
516 | advance = NextinBlock(); |
517 | } |
518 | |
519 | // ** updating connexity |
520 | ::FUN_update(myf,myedstoconnect); |
521 | |
522 | if (!advance) { |
523 | endBlock = myedstoconnect.IsEmpty() && (!startBlock); |
524 | if (!endBlock) return Standard_False; |
525 | else continue; |
526 | } |
527 | |
528 | TopExp_Explorer exe(myf, TopAbs_EDGE); |
529 | for (; exe.More(); exe.Next()){ |
530 | const TopoDS_Shape& e = exe.Current(); |
531 | Standard_Boolean isb = mymapeFs.IsBound(e); |
532 | if (!isb) continue; // ancestors faces of <e> are stored in Blocks |
533 | TopOpeBRepTool_TOOL::Remove(mymapeFs.ChangeFind(e),myf); |
534 | }//exe |
535 | |
536 | mylFinBlock.Append(myf); nite++; |
537 | }//nite <= mynF |
538 | |
539 | myOshNsh.Bind(S(), Splits); |
540 | return Standard_True; |
541 | } |
542 | |
543 | //======================================================================= |
544 | //function : InitBlock |
545 | //purpose : |
546 | //======================================================================= |
547 | |
548 | Standard_Boolean TopOpeBRepTool_REGUS::InitBlock() |
549 | { |
550 | Standard_Integer nec = myedstoconnect.Extent(); |
551 | if (nec != 0) return Standard_False; // should be empty |
552 | |
553 | TopTools_ListOfShape eds; |
554 | TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itm(mymapeFs); |
555 | for (; itm.More(); itm.Next()) eds.Append(itm.Key()); |
556 | |
557 | TopTools_ListIteratorOfListOfShape ite(eds); |
558 | for (; ite.More(); ite.Next()){ |
559 | const TopoDS_Shape& e = ite.Value(); |
560 | const TopTools_ListOfShape& lof = mymapeFs.Find(e); |
561 | if (lof.IsEmpty()) {mymapeFs.UnBind(e); continue;} |
562 | myf = lof.First(); |
0797d9d3 |
563 | #ifdef OCCT_DEBUG |
7fd59977 |
564 | Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO(); |
565 | if (trc) cout<<"* Block : first face = f"<<FUN_adds(myf)<<endl; |
566 | #endif |
567 | return Standard_True; |
568 | } |
569 | return Standard_False; |
570 | } |
571 | |
572 | //======================================================================= |
573 | //function : NextinBlock |
574 | //purpose : |
575 | //======================================================================= |
576 | |
577 | Standard_Boolean TopOpeBRepTool_REGUS::NextinBlock() |
578 | { |
0797d9d3 |
579 | #ifdef OCCT_DEBUG |
7fd59977 |
580 | Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO(); |
581 | #endif |
582 | // we try to connect first edge of <myf> bound in <myedstoconnect> |
583 | TopTools_ListOfShape eds; |
584 | TopExp_Explorer exe(myf, TopAbs_EDGE); |
585 | for (; exe.More(); exe.Next()){ |
586 | const TopoDS_Shape& e = exe.Current(); |
587 | Standard_Boolean isb = myedstoconnect.Contains(e); |
588 | if (isb) eds.Append(e); |
589 | }//exe |
590 | Standard_Boolean alleftouched = eds.IsEmpty(); |
591 | if (alleftouched) { |
592 | TopTools_MapIteratorOfMapOfShape itc(myedstoconnect); |
593 | for (; itc.More(); itc.Next()){ |
594 | const TopoDS_Shape& e = itc.Key(); |
51740958 |
595 | Standard_Boolean isBound = mymapeFs.IsBound(e); |
7fd59977 |
596 | // all ancestor faces of <e> have been stored |
51740958 |
597 | if (!isBound) {myedstoconnect.Remove(e); continue;} |
7fd59977 |
598 | |
599 | const TopTools_ListOfShape& lof = mymapeFs.Find(e); Standard_Integer nf = lof.Extent(); |
600 | if (nf == 0) {myedstoconnect.Remove(e); mymapeFs.UnBind(e); |
601 | continue;} |
602 | |
603 | // myf = lof.First(); 130499 |
604 | if (lof.Extent() == 1) myf = lof.First(); |
605 | else { |
606 | // looking for first face stored in the current block |
607 | // connexed to e |
608 | |
609 | TopTools_ListIteratorOfListOfShape itff(mylFinBlock); |
610 | TopTools_MapOfShape mapf;for (; itff.More(); itff.Next()) mapf.Add(itff.Value()); |
611 | // lofc : the list of faces connexed to e in <myS> |
612 | // lof : the list of untouched faces connexed to e in <myS> |
613 | const TopTools_ListOfShape& lofc = mymapeFsstatic.Find(e); |
6e6cd5d9 |
614 | |
7fd59977 |
615 | itff.Initialize(lofc); |
616 | TopoDS_Face fref; |
617 | for (; itff.More(); itff.Next()) { |
618 | const TopoDS_Face& fc = TopoDS::Face(itff.Value()); |
619 | Standard_Boolean isb = mapf.Contains(fc); |
620 | if (isb) {fref = fc; break;} |
621 | } // itff(lofc) |
622 | if (fref.IsNull()) { |
623 | return Standard_False; // !!!!!!!!!! a revoir 130499 |
624 | } |
625 | else { |
626 | myf = fref; |
627 | TopoDS_Face ffound; Standard_Boolean ok = NearestF(TopoDS::Edge(e),lof,ffound); |
628 | if (!ok) return Standard_False; |
629 | myf = ffound; |
630 | } |
631 | } |
632 | |
633 | return Standard_True; |
634 | } |
635 | return Standard_False; |
636 | } |
637 | |
638 | TopTools_ListIteratorOfListOfShape ite(eds); |
639 | for (; ite.More(); ite.Next()){ |
640 | const TopoDS_Shape& e = ite.Value(); |
641 | Standard_Boolean isb = mymapeFs.IsBound(e); |
642 | // all ancestor faces of <e> have been stored |
643 | if (!isb) {myedstoconnect.Remove(e); continue;} |
644 | |
645 | const TopTools_ListOfShape& lof = mymapeFs.Find(e); Standard_Integer nf = lof.Extent(); |
646 | if (nf == 0) {myedstoconnect.Remove(e); mymapeFs.UnBind(e); |
647 | continue;} |
0797d9d3 |
648 | #ifdef OCCT_DEBUG |
7fd59977 |
649 | if (trc) {cout<<"e"<<FUN_adds(e)<<" on "<<nf<<" untouched f:"<<endl;} |
650 | #endif |
651 | if (nf == 1) myf = lof.First(); |
652 | else { |
653 | TopoDS_Face ffound; Standard_Boolean ok = NearestF(TopoDS::Edge(e),lof,ffound); |
654 | if (!ok) return Standard_False; |
655 | myf = ffound; |
656 | } |
0797d9d3 |
657 | #ifdef OCCT_DEBUG |
7fd59977 |
658 | if (trc) cout<<"->myf = f"<<FUN_adds(myf)<<endl; |
659 | #endif |
660 | return Standard_True; |
661 | }//itm(myedstoconnect) |
662 | return Standard_False; |
663 | } |
664 | |
665 | static Standard_Boolean FUN_vectors(const TopoDS_Face& f, const TopoDS_Edge& e, const Standard_Real pare, |
666 | gp_Dir& nt, gp_Dir& xx, const Standard_Real tola, const Standard_Boolean approx) |
667 | { |
668 | // <nt> : |
669 | if (approx) { |
670 | Standard_Boolean ok = TopOpeBRepTool_TOOL::tryNgApp(pare,e,f,tola,nt); |
671 | if (!ok) return Standard_False; |
672 | } |
673 | else { |
674 | gp_Vec tmp; Standard_Boolean ok = FUN_tool_nggeomF(pare,e,f,tmp); |
675 | if (!ok) return Standard_False; |
676 | nt = gp_Dir(tmp); |
677 | } |
678 | if (M_REVERSED(f.Orientation())) nt.Reverse(); |
679 | // <xx> : |
680 | Standard_Boolean ok = FUN_tool_getxx(f,e,pare,xx); |
681 | if (!ok) return Standard_False; |
682 | return Standard_True; |
683 | } |
684 | |
685 | //======================================================================= |
686 | //function : NearestF |
687 | //purpose : |
688 | //======================================================================= |
689 | |
690 | Standard_Boolean TopOpeBRepTool_REGUS::NearestF(const TopoDS_Edge& e, const TopTools_ListOfShape& lof, TopoDS_Face& ffound) const |
691 | // prequesitory : <e> is shared by <myf> and faces of <lof>. |
692 | // |
693 | // NYIXPU!!!!!!!! if (xx1 tg xx2) -> use curvatures |
694 | // |
695 | { |
0797d9d3 |
696 | #ifdef OCCT_DEBUG |
7fd59977 |
697 | Standard_Boolean trc = TopOpeBRepTool_GettraceREGUSO(); |
698 | #endif |
699 | ffound.Nullify(); |
700 | TopoDS_Face fref = TopoDS::Face(myf); |
7fd59977 |
701 | |
702 | // Give us egde <e>, and a reference face <fref> (= <myf>) |
703 | // - parameter on <e> = <pare>. |
704 | // - xxi = tangent fo face fi at pnt(e,pare) oriented INSIDE 2d(fi) |
705 | // normal to tge = tg(e,pare). |
706 | // purpose : looking for ffound / |
707 | // MatterAng(xxref, xxfound) = Min{ MatterAng(xxref, xxi), xxi for fi in <lof> |
708 | // providing fi reduces 3d(fref) } |
709 | |
710 | // <parone> : |
711 | Standard_Real f,l; FUN_tool_bounds(e,f,l); Standard_Real eps = 0.45678; Standard_Real pare = (1-eps)*f+eps*l; |
712 | |
713 | // RONd (x,y,z) = (xxref,ntref,x^y) |
714 | Standard_Real tola = Precision::Angular()*1.e3; //gp_Dir xapp,yapp; Standard_Boolean refapp = Standard_False; |
715 | gp_Dir x,y; Standard_Boolean ok = ::FUN_vectors(fref,e,pare,y,x,tola,Standard_False); |
716 | if (!ok) {FUN_Raise(); return Standard_False;} |
7fd59977 |
717 | |
718 | // initializing |
719 | // ------------ |
720 | Standard_Real angfound = 0; |
721 | TopTools_ListIteratorOfListOfShape itf(lof); |
722 | for (; itf.More(); itf.Next()){ |
723 | ffound = TopoDS::Face(itf.Value()); |
724 | gp_Dir ntfound,xxfound; |
725 | ok = ::FUN_vectors(ffound,e,pare,ntfound,xxfound,tola,Standard_False); |
726 | if (!ok) {FUN_Raise(); return Standard_False;} |
727 | |
728 | Standard_Boolean oppo = TopOpeBRepTool_TOOL::Matter(x,y,xxfound,ntfound,tola, angfound); |
0797d9d3 |
729 | #ifdef OCCT_DEBUG |
7fd59977 |
730 | if (trc&&!oppo) cout<<" f"<<FUN_adds(fref)<<",f"<<FUN_adds(ffound)<<" not oppo"<<endl; |
731 | #endif |
732 | if (!oppo) {ffound.Nullify(); continue;} |
733 | |
734 | if (angfound < tola) { |
735 | // refapp = Standard_True; ::FUN_vectors(fref,e,pare,yapp,xapp,tola,Standard_True); |
736 | // ::FUN_vectors(ffound,e,pare,ntfound,xxfound,tola,Standard_True); |
737 | // TopOpeBRepTool_TOOL::Matter(xapp,yapp,xxfound,ntfound,tola, angfound); |
738 | ok = TopOpeBRepTool_TOOL::MatterKPtg(fref,ffound,e,angfound); |
739 | if (!ok) {FUN_Raise(); return Standard_False;} |
740 | } |
0797d9d3 |
741 | #ifdef OCCT_DEBUG |
586db386 |
742 | if (trc) cout<<" ang(f"<<FUN_adds(fref)<<",f"<<FUN_adds(ffound)<<")="<<angfound<<endl; |
7fd59977 |
743 | #endif |
744 | break; |
745 | } |
746 | if (ffound.IsNull()) {FUN_Raise(); return Standard_False;} |
747 | if (itf.More()) itf.Next(); |
748 | else return Standard_True; |
749 | |
750 | // selecting nearest face |
751 | // ---------------------- |
752 | for (; itf.More(); itf.Next()){ |
753 | gp_Dir nti,xxi; |
754 | const TopoDS_Face& fi = TopoDS::Face(itf.Value()); |
755 | ok = ::FUN_vectors(fi,e,pare,nti,xxi,tola,Standard_False); |
756 | if (!ok) {FUN_Raise(); return Standard_False;} |
757 | |
758 | Standard_Real angi = 0; |
759 | Standard_Boolean oppo = TopOpeBRepTool_TOOL::Matter(x,y,xxi,nti,tola, angi); |
0797d9d3 |
760 | #ifdef OCCT_DEBUG |
7fd59977 |
761 | if (trc&&!oppo) cout<<" f"<<FUN_adds(fref)<<",f"<<FUN_adds(fi)<<" not oppo"<<endl; |
762 | #endif |
763 | if (!oppo) continue; |
764 | |
765 | if (angi < tola) { |
766 | // if (!refapp) ::FUN_vectors(fref,e,pare,yapp,xapp,tola,Standard_True); |
767 | // ::FUN_vectors(fi,e,pare,nti,xxi,tola,Standard_True); |
768 | // TopOpeBRepTool_TOOL::Matter(xapp,yapp,xxi,nti,tola, angi); |
769 | ok = TopOpeBRepTool_TOOL::MatterKPtg(fref,fi,e,angi); |
770 | if (!ok) {FUN_Raise(); return Standard_False;} |
771 | } |
0797d9d3 |
772 | #ifdef OCCT_DEBUG |
586db386 |
773 | if (trc) cout<<" ang(f"<<FUN_adds(fref)<<",f"<<FUN_adds(fi)<<")="<<angi<<endl; |
7fd59977 |
774 | #endif |
775 | if (angi > angfound) continue; |
776 | angfound = angi; |
777 | ffound = fi; |
778 | } |
779 | return Standard_True; |
780 | } |
781 | |
782 | |
783 | |