1 // Created on: 1996-02-13
2 // Created by: Olga KOULECHOVA
3 // Copyright (c) 1996-1999 Matra Datavision
4 // Copyright (c) 1999-2014 OPEN CASCADE SAS
5 //
6 // This file is part of Open CASCADE Technology software library.
7 //
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
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.
13 //
14 // Alternatively, this file may be used under the terms of Open CASCADE
15 // commercial license or contractual agreement.
16
17
18 #include <Bnd_Box.hxx>
19 #include <BRep_Tool.hxx>
20 #include <BRep_Builder.hxx>
21 #include <BRepAlgo.hxx>
22 #include <BRepAlgoAPI_BooleanOperation.hxx>
23 #include <BRepAlgoAPI_Cut.hxx>
24 #include <BRepAlgoAPI_Fuse.hxx>
25 #include <BRepBndLib.hxx>
26 #include <BRepCheck_Analyzer.hxx>
27 #include <BRepFeat.hxx>
28 #include <BRepFeat_Builder.hxx>
29 #include <BRepFeat_Form.hxx>
30 #include <BRepLib.hxx>
31 #include <BRepTools_Modifier.hxx>
32 #include <BRepTools_TrsfModification.hxx>
33 #include <ElCLib.hxx>
34 #include <Geom_ConicalSurface.hxx>
35 #include <Geom_Curve.hxx>
36 #include <Geom_CylindricalSurface.hxx>
37 #include <Geom_Plane.hxx>
38 #include <Geom_RectangularTrimmedSurface.hxx>
39 #include <LocOpe.hxx>
40 #include <LocOpe_BuildShape.hxx>
41 #include <LocOpe_CSIntersector.hxx>
42 #include <LocOpe_FindEdges.hxx>
43 #include <LocOpe_Gluer.hxx>
44 #include <LocOpe_PntFace.hxx>
45 #include <LocOpe_SequenceOfCirc.hxx>
46 #include <Precision.hxx>
47 #include <Standard_NoSuchObject.hxx>
48 #include <TColgp_SequenceOfPnt.hxx>
49 #include <TopExp_Explorer.hxx>
50 #include <TopoDS.hxx>
51 #include <TopoDS_Compound.hxx>
52 #include <TopoDS_Shape.hxx>
53 #include <TopoDS_Solid.hxx>
54 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
55 #include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
56 #include <TopTools_ListIteratorOfListOfShape.hxx>
57 #include <TopTools_MapIteratorOfMapOfShape.hxx>
58 #include <TopTools_MapOfShape.hxx>
59
60 #ifdef OCCT_DEBUG
61 extern Standard_Boolean BRepFeat_GettraceFEAT();
62 #endif
63
64 static void Descendants(const TopoDS_Shape&,
65 BRepFeat_Builder&,
66 TopTools_MapOfShape&);
67
68 //=======================================================================
69 //function : Perform
70 //purpose : topological reconstruction of the result
71 //=======================================================================
GlobalPerform()72 void BRepFeat_Form::GlobalPerform ()
73 {
74
75 #ifdef OCCT_DEBUG
76 Standard_Boolean trc = BRepFeat_GettraceFEAT();
77 if (trc) std::cout << "BRepFeat_Form::GlobalPerform ()" << std::endl;
78 #endif
79
80 if (!mySbOK || !myGSOK || !mySFOK || !mySUOK || !myGFOK ||
81 !mySkOK || !myPSOK) {
82 #ifdef OCCT_DEBUG
83 if (trc) std::cout << " Fields not initialized in BRepFeat_Form" << std::endl;
84 #endif
85 myStatusError = BRepFeat_NotInitialized;
86 NotDone();
87 return;
88 }
89
90 //--- Initialisation
91 TopExp_Explorer exp,exp2;
92 Standard_Integer theOpe = 2;
93 TopTools_DataMapIteratorOfDataMapOfShapeShape itm;
94
95 if(myJustFeat && !myFuse) {
96 #ifdef OCCT_DEBUG
97 if (trc) std::cout << " Invalid option : myJustFeat + Cut" << std::endl;
98 #endif
99 myStatusError = BRepFeat_InvOption;
100 NotDone();
101 return;
102 }
103 else if(myJustFeat) {
104 theOpe = 2;
105 }
106 else if (!myGluedF.IsEmpty()) {
107 theOpe = 1;
108 }
109 else {}
110 Standard_Boolean ChangeOpe = Standard_False;
111
112 Standard_Boolean FromInShape = Standard_False;
113 Standard_Boolean UntilInShape = Standard_False;
114
115 if (!mySFrom.IsNull()) {
116 FromInShape = Standard_True;
117 for (exp2.Init(mySFrom,TopAbs_FACE); exp2.More(); exp2.Next()) {
118 const TopoDS_Shape& ffrom = exp2.Current();
119 for (exp.Init(mySbase,TopAbs_FACE); exp.More(); exp.Next()) {
120 if (exp.Current().IsSame(ffrom)) {
121 break;
122 }
123 }
124 if (!exp.More()) {
125 FromInShape = Standard_False;
126 #ifdef OCCT_DEBUG
127 if (trc) std::cout << " From not in Shape" << std::endl;
128 #endif
129 break;
130 }
131 }
132 }
133
134 if (!mySUntil.IsNull()) {
135 UntilInShape = Standard_True;
136 for (exp2.Init(mySUntil,TopAbs_FACE); exp2.More(); exp2.Next()) {
137 const TopoDS_Shape& funtil = exp2.Current();
138 for (exp.Init(mySbase,TopAbs_FACE); exp.More(); exp.Next()) {
139 if (exp.Current().IsSame(funtil)) {
140 break;
141 }
142 }
143 if (!exp.More()) {
144 UntilInShape = Standard_False;
145 #ifdef OCCT_DEBUG
146 if (trc) std::cout << " Until not in Shape" << std::endl;
147 #endif
148 break;
149 }
150 }
151 }
152
153 TopTools_ListIteratorOfListOfShape it,it2;
154 Standard_Integer sens = 0;
155
156 TColGeom_SequenceOfCurve scur;
157 Curves(scur);
158
159 Standard_Real mf, Mf, mu, Mu;
160
161 TopAbs_Orientation Orifuntil = TopAbs_INTERNAL;
162 TopAbs_Orientation Oriffrom = TopAbs_INTERNAL;
163 TopoDS_Face FFrom,FUntil;
164
165 LocOpe_CSIntersector ASI1;
166 LocOpe_CSIntersector ASI2;
167
168 TopTools_ListOfShape IntList;
169 IntList.Clear();
170
171 //--- 1) by intersection
172
173 // Intersection Tool Shape From
174 if (!mySFrom.IsNull()) {
175 ASI1.Init(mySFrom);
176 ASI1.Perform(scur);
177 }
178
179 // Intersection Tool Shape Until
180 if (!mySUntil.IsNull()) {
181 ASI2.Init(mySUntil);
182 ASI2.Perform(scur);
183 }
184
185 {
186 // Find sens, FFrom, FUntil
187 for (Standard_Integer jj=1; jj<=scur.Length(); jj++) {
188 if (ASI1.IsDone() && ASI2.IsDone()) {
189 if (ASI1.NbPoints(jj) <= 0) {
190 continue;
191 }
192 mf = ASI1.Point(jj,1).Parameter();
193 Mf = ASI1.Point(jj,ASI1.NbPoints(jj)).Parameter();
194 if (ASI2.NbPoints(jj) <= 0) {
195 continue;
196 }
197 mu = ASI2.Point(jj,1).Parameter();
198 Mu = ASI2.Point(jj,ASI2.NbPoints(jj)).Parameter();
199 if (!scur(jj)->IsPeriodic()) {
200 Standard_Integer ku, kf;
201 if (! (mu > Mf || mf > Mu)) { //overlapping intervals
202 sens = 1;
203 kf = 1;
204 ku = ASI2.NbPoints(jj);
205 }
206 else if (mu > Mf) {
207 if (sens == -1) {
208 myStatusError = BRepFeat_IntervalOverlap;
209 NotDone();
210 return;
211 }
212 sens = 1;
213 kf = 1;
214 ku = ASI2.NbPoints(jj);
215 }
216 else {
217 if (sens == 1) {
218 myStatusError = BRepFeat_IntervalOverlap;
219 NotDone();
220 return;
221 }
222 sens = -1;
223 kf = ASI1.NbPoints(jj);
224 ku = 1;
225 }
226 if (Oriffrom == TopAbs_INTERNAL) {
227 TopAbs_Orientation Oript = ASI1.Point(jj,kf).Orientation();
228 if (Oript == TopAbs_FORWARD || Oript == TopAbs_REVERSED) {
229 if (sens == -1) {
230 Oript = TopAbs::Reverse(Oript);
231 }
232 Oriffrom = TopAbs::Reverse(Oript);
233 FFrom = ASI1.Point(jj,kf).Face();
234 }
235 }
236 if (Orifuntil == TopAbs_INTERNAL) {
237 TopAbs_Orientation Oript = ASI2.Point(jj,ku).Orientation();
238 if (Oript == TopAbs_FORWARD || Oript == TopAbs_REVERSED) {
239 if (sens == -1) {
240 Oript = TopAbs::Reverse(Oript);
241 }
242 Orifuntil = Oript;
243 FUntil = ASI2.Point(jj,ku).Face();
244 }
245 }
246 }
247 }
248 else if (ASI2.IsDone()) {
249 if (ASI2.NbPoints(jj) <= 0)
250 continue;
251
252 // for base case prism on mySUntil -> ambivalent direction
253 // -> preferable direction = 1
254 if(sens != 1) {
255 if (ASI2.Point(jj,1).Parameter()*
256 ASI2.Point(jj,ASI2.NbPoints(jj)).Parameter()<=0)
257 sens=1;
258 else if (ASI2.Point(jj,1).Parameter()<0.)
259 sens =-1;
260 else
261 sens =1;
262 }
263
264 Standard_Integer ku;
265 if (sens == -1) {
266 ku = 1;
267 }
268 else {
269 ku = ASI2.NbPoints(jj);
270 }
271 if (Orifuntil == TopAbs_INTERNAL && sens != 0) {
272 TopAbs_Orientation Oript = ASI2.Point(jj,ku).Orientation();
273 if (Oript == TopAbs_FORWARD || Oript == TopAbs_REVERSED) {
274 if (sens == -1) {
275 Oript = TopAbs::Reverse(Oript);
276 }
277 Orifuntil = Oript;
278 FUntil = ASI2.Point(jj,ku).Face();
279 }
280 }
281 }
282 else {
283 sens = 1;
284 break;
285 }
286 }
287 }
288
289 LocOpe_Gluer theGlue;
290
291 //--- case of gluing
292
293 if (theOpe == 1) {
294 #ifdef OCCT_DEBUG
295 if (trc) std::cout << " Gluer" << std::endl;
296 #endif
297 Standard_Boolean Collage = Standard_True;
298 // cut by FFrom && FUntil
299 TopoDS_Shape Comp;
300 BRep_Builder B;
301 B.MakeCompound(TopoDS::Compound(Comp));
302 if (!mySFrom.IsNull()) {
303 TopoDS_Solid S = BRepFeat::Tool(mySFrom,FFrom,Oriffrom);
304 if (!S.IsNull()) {
305 B.Add(Comp,S);
306 }
307 }
308 if (!mySUntil.IsNull()) {
309 TopoDS_Solid S = BRepFeat::Tool(mySUntil,FUntil,Orifuntil);
310 if (!S.IsNull()) {
311 B.Add(Comp,S);
312 }
313 }
314
315 LocOpe_FindEdges theFE;
316 TopTools_DataMapOfShapeListOfShape locmap;
317 TopExp_Explorer expp(Comp, TopAbs_SOLID);
318 if(expp.More() && !Comp.IsNull() && !myGShape.IsNull()) {
319 BRepAlgoAPI_Cut trP(myGShape, Comp);
320 exp.Init(trP.Shape(), TopAbs_SOLID);
321 if (exp.Current().IsNull()) {
322 theOpe = 2;
323 ChangeOpe = Standard_True;
324 Collage = Standard_False;
325 }
326 else {// else X0
327 // Only solids are preserved
328 TopoDS_Shape theGShape;
329 B.MakeCompound(TopoDS::Compound(theGShape));
330 for (; exp.More(); exp.Next()) {
331 B.Add(theGShape,exp.Current());
332 }
333 if (!BRepAlgo::IsValid(theGShape)) {
334 theOpe = 2;
335 ChangeOpe = Standard_True;
336 Collage = Standard_False;
337 }
338 else {// else X1
339 if(!mySFrom.IsNull()) {
340 TopExp_Explorer ex;
341 ex.Init(mySFrom, TopAbs_FACE);
342 for(; ex.More(); ex.Next()) {
343 const TopoDS_Face& fac = TopoDS::Face(ex.Current());
344 if (!FromInShape) {
345 TopTools_ListOfShape thelist;
346 myMap.Bind(fac, thelist);
347 }
348 else {
349 TopTools_ListOfShape thelist1;
350 locmap.Bind(fac, thelist1);
351 }
352 if (trP.IsDeleted(fac)) {
353 }
354 else if (!FromInShape) {
355 myMap(fac) = trP.Modified(fac);
356 if (myMap(fac).IsEmpty()) myMap(fac).Append(fac);
357 }
358 else {
359 locmap(fac) =trP.Modified(fac) ;
360 if (locmap(fac).IsEmpty()) locmap(fac).Append(fac);
361 }
362 }
363 }// if(!mySFrom.IsNull())
364 //
365 if(!mySUntil.IsNull()) {
366 TopExp_Explorer ex;
367 ex.Init(mySUntil, TopAbs_FACE);
368 for(; ex.More(); ex.Next()) {
369 const TopoDS_Face& fac = TopoDS::Face(ex.Current());
370 if (!UntilInShape) {
371 TopTools_ListOfShape thelist2;
372 myMap.Bind(fac,thelist2);
373 }
374 else {
375 TopTools_ListOfShape thelist3;
376 locmap.Bind(fac,thelist3);
377 }
378 if (trP.IsDeleted(fac)) {
379 }
380 else if (!UntilInShape) {
381 myMap(fac) = trP.Modified(fac);
382 if (myMap(fac).IsEmpty()) myMap(fac).Append(fac);
383 }
384 else {
385 locmap(fac) = trP.Modified(fac);
386 if (locmap(fac).IsEmpty()) locmap(fac).Append(fac);
387 }
388 }
389 }// if(!mySUntil.IsNull())
390 //
391 UpdateDescendants(trP,theGShape,Standard_True); // skip faces
392
393 theGlue.Init(mySbase,theGShape);
394 for (itm.Initialize(myGluedF);itm.More();itm.Next()) {
395 const TopoDS_Face& gl = TopoDS::Face(itm.Key());
396 TopTools_ListOfShape ldsc;
397 if (trP.IsDeleted(gl)) {
398 }
399 else {
400 ldsc = trP.Modified(gl);
401 if (ldsc.IsEmpty()) ldsc.Append(gl);
402 }
403 const TopoDS_Face& glface = TopoDS::Face(itm.Value());
404 for (it.Initialize(ldsc);it.More();it.Next()) {
405 const TopoDS_Face& fac = TopoDS::Face(it.Value());
406 Collage = BRepFeat::IsInside(fac, glface);
407 if(!Collage) {
408 theOpe = 2;
409 ChangeOpe = Standard_True;
410 break;
411 }
412 else {
413 theGlue.Bind(fac,glface);
414 theFE.Set(fac,glface);
415 for (theFE.InitIterator(); theFE.More();theFE.Next()) {
416 theGlue.Bind(theFE.EdgeFrom(),theFE.EdgeTo());
417 }
418 }
419 }
420 }
421 }// else X1
422 }// else X0
423 }// if(expp.More() && !Comp.IsNull() && !myGShape.IsNull())
424 else {
425 theGlue.Init(mySbase,myGShape);
426 for (itm.Initialize(myGluedF); itm.More();itm.Next()) {
427 const TopoDS_Face& glface = TopoDS::Face(itm.Key());
428 const TopoDS_Face& fac = TopoDS::Face(myGluedF(glface));
429 for (exp.Init(myGShape,TopAbs_FACE); exp.More(); exp.Next()) {
430 if (exp.Current().IsSame(glface)) {
431 break;
432 }
433 }
434 if (exp.More()) {
435 Collage = BRepFeat::IsInside(glface, fac);
436 if(!Collage) {
437 theOpe = 2;
438 ChangeOpe = Standard_True;
439 break;
440 }
441 else {
442 theGlue.Bind(glface, fac);
443 theFE.Set(glface, fac);
444 for (theFE.InitIterator(); theFE.More();theFE.Next()) {
445 theGlue.Bind(theFE.EdgeFrom(),theFE.EdgeTo());
446 }
447 }
448 }
449 }
450 }
451
452 // Add gluing on start and end face if necessary !!!
453 if (FromInShape && Collage) {
454 TopExp_Explorer ex(mySFrom,TopAbs_FACE);
455 for(; ex.More(); ex.Next()) {
456 const TopoDS_Face& fac2 = TopoDS::Face(ex.Current());
457 // for (it.Initialize(myMap(fac2)); it.More(); it.Next()) {
458 for (it.Initialize(locmap(fac2)); it.More(); it.Next()) {
459 const TopoDS_Face& fac1 = TopoDS::Face(it.Value());
460 theFE.Set(fac1, fac2);
461 theGlue.Bind(fac1, fac2);
462 for (theFE.InitIterator(); theFE.More();theFE.Next()) {
463 theGlue.Bind(theFE.EdgeFrom(),theFE.EdgeTo());
464 }
465 }
466 // myMap.UnBind(fac2);
467 }
468 }
469
470 if (UntilInShape && Collage) {
471 TopExp_Explorer ex(mySUntil, TopAbs_FACE);
472 for(; ex.More(); ex.Next()) {
473 const TopoDS_Face& fac2 = TopoDS::Face(ex.Current());
474 // for (it.Initialize(myMap(fac2)); it.More(); it.Next()) {
475 for (it.Initialize(locmap(fac2)); it.More(); it.Next()) {
476 const TopoDS_Face& fac1 = TopoDS::Face(it.Value());
477 theGlue.Bind(fac1, fac2);
478 theFE.Set(fac1, fac2);
479 for (theFE.InitIterator(); theFE.More();theFE.Next()) {
480 theGlue.Bind(theFE.EdgeFrom(),theFE.EdgeTo());
481 }
482 }
483 //myMap.UnBind(fac2); // to avoid fac2 in Map when
484 // UpdateDescendants(theGlue) is called
485 }
486 }
487
488 LocOpe_Operation ope = theGlue.OpeType();
489 if (ope == LocOpe_INVALID ||
490 (myFuse && ope != LocOpe_FUSE) ||
491 (!myFuse && ope != LocOpe_CUT) ||
492 (!Collage)) {
493 theOpe = 2;
494 ChangeOpe = Standard_True;
495 }
496 }
497
498 //--- if the gluing is always applicable
499
500 if (theOpe == 1) {
501 #ifdef OCCT_DEBUG
502 if (trc) std::cout << " still Gluer" << std::endl;
503 #endif
504 theGlue.Perform();
505 if (theGlue.IsDone()) {
506 TopoDS_Shape shshs = theGlue.ResultingShape();
507 // if (BRepOffsetAPI::IsTopologicallyValid(shshs)) {
508 if (BRepAlgo::IsValid(shshs)) {
509 UpdateDescendants(theGlue);
510 myNewEdges = theGlue.Edges();
511 myTgtEdges = theGlue.TgtEdges();
512 #ifdef OCCT_DEBUG
513 if (trc) std::cout << " Gluer result" << std::endl;
514 #endif
515 Done();
516 myShape = theGlue.ResultingShape();
517 }
518 else {
519 theOpe = 2;
520 ChangeOpe = Standard_True;
521 }
522 }
523 else {
524 theOpe = 2;
525 ChangeOpe = Standard_True;
526 }
527 }
528
529
530 //--- case without gluing + Tool with proper dimensions
531
532 if (theOpe == 2 && ChangeOpe && myJustGluer) {
533 #ifdef OCCT_DEBUG
534 if (trc) std::cout << " Gluer failure" << std::endl;
535 #endif
536 myJustGluer = Standard_False;
537 theOpe = 0;
538 // Done();
539 // return;
540 }
541
542 //--- case without gluing
543
544 if (theOpe == 2) {
545 #ifdef OCCT_DEBUG
546 if (trc) std::cout << " No Gluer" << std::endl;
547 #endif
548 TopoDS_Shape theGShape = myGShape;
549 if (ChangeOpe) {
550 #ifdef OCCT_DEBUG
551 if (trc) std::cout << " Passage to topological operations" << std::endl;
552 #endif
553 }
554
555 TopoDS_Shape Comp;
556 BRep_Builder B;
557 B.MakeCompound(TopoDS::Compound(Comp));
558 if (!mySFrom.IsNull() || !mySUntil.IsNull()) {
559 if (!mySFrom.IsNull() && !FromInShape) {
560 TopoDS_Solid S = BRepFeat::Tool(mySFrom,FFrom,Oriffrom);
561 if (!S.IsNull()) {
562 B.Add(Comp,S);
563 }
564 }
565 if (!mySUntil.IsNull() && !UntilInShape) {
566 if (!mySFrom.IsNull()) {
567 if (!mySFrom.IsSame(mySUntil)) {
568 TopoDS_Solid S = BRepFeat::Tool(mySUntil,FUntil,Orifuntil);
569 if (!S.IsNull()) {
570 B.Add(Comp,S);
571 }
572 }
573 }
574 else {
575 TopoDS_Solid S = BRepFeat::Tool(mySUntil,FUntil,Orifuntil);
576 if (!S.IsNull()) {
577 B.Add(Comp,S);
578 }
579 }
580 }
581 }
582
583 // update type of selection
584 if(myPerfSelection == BRepFeat_SelectionU && !UntilInShape) {
585 myPerfSelection = BRepFeat_NoSelection;
586 }
587 else if(myPerfSelection == BRepFeat_SelectionFU &&
588 !FromInShape && !UntilInShape) {
589 myPerfSelection = BRepFeat_NoSelection;
590 }
591 else if(myPerfSelection == BRepFeat_SelectionShU && !UntilInShape) {
592 myPerfSelection = BRepFeat_NoSelection;
593 }
594 else {}
595
596 TopExp_Explorer expp(Comp, TopAbs_SOLID);
597 if(expp.More() && !Comp.IsNull() && !myGShape.IsNull()) {
598 BRepAlgoAPI_Cut trP(myGShape, Comp);
599 // the result is necessarily a compound.
600 exp.Init(trP.Shape(),TopAbs_SOLID);
601 if (!exp.More()) {
602 myStatusError = BRepFeat_EmptyCutResult;
603 NotDone();
604 return;
605 }
606 // Only solids are preserved
607 theGShape.Nullify();
608 B.MakeCompound(TopoDS::Compound(theGShape));
609 for (; exp.More(); exp.Next()) {
610 B.Add(theGShape,exp.Current());
611 }
612 if (!BRepAlgo::IsValid(theGShape)) {
613 myStatusError = BRepFeat_InvShape;
614 NotDone();
615 return;
616 }
617 if(!mySFrom.IsNull()) {
618 if(!FromInShape) {
619 TopExp_Explorer ex(mySFrom, TopAbs_FACE);
620 for(; ex.More(); ex.Next()) {
621 const TopoDS_Face& fac = TopoDS::Face(ex.Current());
622 TopTools_ListOfShape thelist4;
623 myMap.Bind(fac,thelist4);
624 if (trP.IsDeleted(fac)) {
625 }
626 else {
627 myMap(fac) = trP.Modified(fac);
628 if (myMap(fac).IsEmpty()) myMap(fac).Append(fac);
629 }
630 }
631 }
632 }
633 if(!mySUntil.IsNull()) {
634 if(!UntilInShape) {
635 TopExp_Explorer ex(mySUntil, TopAbs_FACE);
636 for(; ex.More(); ex.Next()) {
637 const TopoDS_Face& fac = TopoDS::Face(ex.Current());
638 TopTools_ListOfShape thelist5;
639 myMap.Bind(fac,thelist5);
640 if (trP.IsDeleted(fac)) {
641 }
642 else {
643 myMap(fac) = trP.Modified(fac);
644 if (myMap.IsEmpty()) myMap(fac).Append(fac);
645 }
646 }
647 }
648 }
649 UpdateDescendants(trP,theGShape,Standard_True);
650 }//if(expp.More() && !Comp.IsNull() && !myGShape.IsNull()) {
651 //
652
653 //--- generation of "just feature" for assembly = Parts of tool
654 Standard_Boolean bFlag = (myPerfSelection == BRepFeat_NoSelection) ? 0 : 1;
655 BRepFeat_Builder theBuilder;
656 theBuilder.Init(mySbase, theGShape);
657 theBuilder.SetOperation(myFuse, bFlag);
658 theBuilder.Perform();
659 //
660 TopTools_ListOfShape lshape;
661 theBuilder.PartsOfTool(lshape);
662 //
663 Standard_Real pbmin = RealLast(), pbmax = RealFirst();
664 Standard_Real prmin = RealLast() - 2*Precision::Confusion();
665 Standard_Real prmax = RealFirst() + 2*Precision::Confusion();
666 Standard_Boolean flag1 = Standard_False;
667 Handle(Geom_Curve) C;
668
669 //--- Selection of pieces of tool to be preserved
670 if(!lshape.IsEmpty() && myPerfSelection != BRepFeat_NoSelection) {
671 // Find ParametricMinMax depending on the constraints of Shape From and Until
672 // -> prmin, prmax, pbmin and pbmax
673 C = BarycCurve();
674 if (C.IsNull()) {
675 myStatusError = BRepFeat_EmptyBaryCurve;
676 NotDone();
677 return;
678 }
679
680 if(myPerfSelection == BRepFeat_SelectionSh) {
681 BRepFeat::ParametricMinMax(mySbase,C,
682 prmin, prmax, pbmin, pbmax, flag1);
683 }
684 else if(myPerfSelection == BRepFeat_SelectionFU) {
685 Standard_Real prmin1, prmax1, prmin2, prmax2;
686 Standard_Real prbmin1, prbmax1, prbmin2, prbmax2;
687
688 BRepFeat::ParametricMinMax(mySFrom,C,
689 prmin1, prmax1, prbmin1, prbmax1, flag1);
690 BRepFeat::ParametricMinMax(mySUntil,C,
691 prmin2, prmax2, prbmin2, prbmax2, flag1);
692
693 // case of revolutions
694 if (C->IsPeriodic()) {
695 Standard_Real period = C->Period();
696 prmax = prmax2;
697 if (flag1) {
698 prmin = ElCLib::InPeriod(prmin1,prmax-period,prmax);
699 }
700 else {
701 prmin = Min(prmin1, prmin2);
702 }
703 pbmax = prbmax2;
704 pbmin = ElCLib::InPeriod(prbmin1,pbmax-period,pbmax);
705 }
706 else {
707 prmin = Min(prmin1, prmin2);
708 prmax = Max(prmax1, prmax2);
709 pbmin = Min(prbmin1, prbmin2);
710 pbmax = Max(prbmax1, prbmax2);
711 }
712 }
713 else if(myPerfSelection == BRepFeat_SelectionShU) {
714 Standard_Real prmin1, prmax1, prmin2, prmax2;
715 Standard_Real prbmin1, prbmax1, prbmin2, prbmax2;
716
717 if(!myJustFeat && sens == 0) sens =1;
718 if (sens == 0) {
719 myStatusError = BRepFeat_IncDirection;
720 NotDone();
721 return;
722 }
723
724 BRepFeat::ParametricMinMax(mySUntil,C,
725 prmin1, prmax1, prbmin1, prbmax1, flag1);
726
727 BRepFeat::ParametricMinMax(mySbase,C,
728 prmin2, prmax2, prbmin2, prbmax2, flag1);
729 if (sens == 1) {
730 prmin = prmin2;
731 prmax = prmax1;
732 pbmin = prbmin2;
733 pbmax = prbmax1;
734 }
735 else if (sens == -1) {
736 prmin = prmin1;
737 prmax = prmax2;
738 pbmin = prbmin1;
739 pbmax = prbmax2;
740 }
741 }
742 else if (myPerfSelection == BRepFeat_SelectionU) {
743 Standard_Real prmin1, prmax1, prbmin1, prbmax1;
744 if (sens == 0) {
745 myStatusError = BRepFeat_IncDirection;
746 NotDone();
747 return;
748 }
749
750 // Find parts of the tool containing descendants of Shape Until
751 BRepFeat::ParametricMinMax(mySUntil,C,
752 prmin1, prmax1, prbmin1, prbmax1, flag1);
753 if (sens == 1) {
754 prmin = RealFirst();
755 prmax = prmax1;
756 pbmin = RealFirst();
757 pbmax = prbmax1;
758 }
759 else if(sens == -1) {
760 prmin = prmin1;
761 prmax = RealLast();
762 pbmin = prbmin1;
763 pbmax = RealLast();
764 }
765 }
766
767
768 // Finer choice of ParametricMinMax in case when the tool
769 // intersects Shapes From and Until
770 // case of several intersections (keep PartsOfTool according to the selection)
771 // position of the face of intersection in PartsOfTool (before or after)
772 Standard_Real delta = Precision::Confusion();
773
774 if (myPerfSelection != BRepFeat_NoSelection) {
775 // modif of the test for cts21181 : (prbmax2 and prnmin2) -> (prbmin1 and prbmax1)
776 // correction take into account flag2 for pro15323 and flag3 for pro16060
777 if (!mySUntil.IsNull()) {
778 TopTools_MapOfShape mapFuntil;
779 Descendants(mySUntil,theBuilder,mapFuntil);
780 if (!mapFuntil.IsEmpty()) {
781 for (it.Initialize(lshape); it.More(); it.Next()) {
782 TopExp_Explorer expf;
783 for (expf.Init(it.Value(),TopAbs_FACE);
784 expf.More(); expf.Next()) {
785 if (mapFuntil.Contains(expf.Current())) {
786 Standard_Boolean flag2,flag3;
787 Standard_Real prmin1, prmax1, prbmin1, prbmax1;
788 Standard_Real prmin2, prmax2, prbmin2, prbmax2;
789 BRepFeat::ParametricMinMax(expf.Current(),C, prmin1, prmax1,
790 prbmin1, prbmax1,flag3);
791 BRepFeat::ParametricMinMax(it.Value(),C, prmin2, prmax2,
792 prbmin2, prbmax2,flag2);
793 if (sens == 1) {
794 Standard_Boolean testOK = !flag2;
795 if (flag2) {
796 testOK = !flag1;
797 if (flag1 && prmax2 > prmin + delta) {
798 testOK = !flag3;
799 if (flag3 && prmax1 == prmax2) {
800 testOK = Standard_True;
801 }
802 }
803 }
804 if (prbmin1 < pbmax && testOK) {
805 if (flag2) {
806 flag1 = flag2;
807 prmax = prmax2;
808 }
809 pbmax = prbmin1;
810 }
811 }
812 else if (sens == -1){
813 Standard_Boolean testOK = !flag2;
814 if (flag2) {
815 testOK = !flag1;
816 if (flag1 && prmin2 < prmax - delta) {
817 testOK = !flag3;
818 if (flag3 && prmin1 == prmin2) {
819 testOK = Standard_True;
820 }
821 }
822 }
823 if (prbmax1 > pbmin && testOK) {
824 if (flag2) {
825 flag1 = flag2;
826 prmin = prmin2;
827 }
828 pbmin = prbmax1;
829 }
830 }
831 break;
832 }
833 }
834 }
835 it.Initialize(lshape);
836 }
837 }
838 if (!mySFrom.IsNull()) {
839 TopTools_MapOfShape mapFfrom;
840 Descendants(mySFrom, theBuilder, mapFfrom);
841 if (!mapFfrom.IsEmpty()) {
842 for (it.Initialize(lshape); it.More(); it.Next()) {
843 TopExp_Explorer expf;
844 for (expf.Init(it.Value(),TopAbs_FACE);
845 expf.More(); expf.Next()) {
846 if (mapFfrom.Contains(expf.Current())) {
847 Standard_Boolean flag2,flag3;
848 Standard_Real prmin1, prmax1, prbmin1, prbmax1;
849 Standard_Real prmin2, prmax2, prbmin2, prbmax2;
850 BRepFeat::ParametricMinMax(expf.Current(),C, prmin1, prmax1,
851 prbmin1, prbmax1,flag3);
852 BRepFeat::ParametricMinMax(it.Value(),C, prmin2, prmax2,
853 prbmin2, prbmax2,flag2);
854 if (sens == 1) {
855 Standard_Boolean testOK = !flag2;
856 if (flag2) {
857 testOK = !flag1;
858 if (flag1 && prmin2 < prmax - delta) {
859 testOK = !flag3;
860 if (flag3 && prmin1 == prmin2) {
861 testOK = Standard_True;
862 }
863 }
864 }
865 if (prbmax1 > pbmin && testOK) {
866 if (flag2) {
867 flag1 = flag2;
868 prmin = prmin2;
869 }
870 pbmin = prbmax1;
871 }
872 }
873 else if (sens == -1){
874 Standard_Boolean testOK = !flag2;
875 if (flag2) {
876 testOK = !flag1;
877 if (flag1 && prmax2 > prmin + delta) {
878 testOK = !flag3;
879 if (flag3 && prmax1 == prmax2) {
880 testOK = Standard_True;
881 }
882 }
883 }
884 if (prbmin1 < pbmax && testOK) {
885 if (flag2) {
886 flag1 = flag2;
887 prmax = prmax2;
888 }
889 pbmax = prbmin1;
890 }
891 }
892 break;
893 }
894 }
895 }
896 it.Initialize(lshape);
897 }
898 }
899 }
900
901
902 // Parse PartsOfTool to preserve or not depending on ParametricMinMax
903 if (!myJustFeat) {
904 Standard_Boolean KeepParts = Standard_False;
905 Standard_Real prmin1, prmax1, prbmin1, prbmax1;
906 Standard_Real min, max, pmin, pmax;
907 Standard_Boolean flag2;
908 for (it.Initialize(lshape); it.More(); it.Next()) {
909 if (C->IsPeriodic()) {
910 Standard_Real period = C->Period();
911 Standard_Real pr, prb;
912 BRepFeat::ParametricMinMax(it.Value(),C, pr, prmax1,
913 prb, prbmax1,flag2,Standard_True);
914 if (flag2) {
915 prmin1 = ElCLib::InPeriod(pr,prmax1-period,prmax1);
916 }
917 else {
918 prmin1 = pr;
919 }
920 prbmin1 = ElCLib::InPeriod(prb,prbmax1-period,prbmax1);
921 }
922 else {
923 BRepFeat::ParametricMinMax(it.Value(),C,
924 prmin1, prmax1, prbmin1, prbmax1,flag2);
925 }
926 if(flag2 == Standard_False || flag1 == Standard_False) {
927 pmin = pbmin;
928 pmax = pbmax;
929 min = prbmin1;
930 max = prbmax1;
931 }
932 else {
933 pmin = prmin;
934 pmax = prmax;
935 min = prmin1;
936 max = prmax1;
937 }
938 if (!((min > pmax - delta) ||
939 (max < pmin + delta))) {
940 KeepParts = Standard_True;
941 const TopoDS_Shape& S = it.Value();
942 theBuilder.KeepPart(S);
943 }
944 }
945
946 // Case when no part of the tool is preserved
947 if (!KeepParts) {
948 #ifdef OCCT_DEBUG
949 if (trc) std::cout << " No parts of tool kept" << std::endl;
950 #endif
951 myStatusError = BRepFeat_NoParts;
952 NotDone();
953 return;
954 }
955 }
956 else {
957 // case JustFeature -> all PartsOfTool are preserved
958 Standard_Real prmin1, prmax1, prbmin1, prbmax1;
959 Standard_Real min, max, pmin, pmax;
960 Standard_Boolean flag2;
961 TopoDS_Shape Compo;
962 B.MakeCompound(TopoDS::Compound(Compo));
963 for (it.Initialize(lshape); it.More(); it.Next()) {
964 BRepFeat::ParametricMinMax(it.Value(),C,
965 prmin1, prmax1, prbmin1, prbmax1,flag2);
966 if(flag2 == Standard_False || flag1 == Standard_False) {
967 pmin = pbmin;
968 pmax = pbmax;
969 min = prbmin1;
970 max = prbmax1;
971 }
972 else {
973 pmin = prmin;
974 pmax = prmax;
975 min = prmin1;
976 max = prmax1;
977 }
978 if ((min < pmax - delta) &&
979 (max > pmin + delta)){
980 if (!it.Value().IsNull()) {
981 B.Add(Compo,it.Value());
982 }
983 }
984 }
985 myShape = Compo;
986 }
987 }
988
989 //--- Generation of result myShape
990
991 if (!myJustFeat) {
992 // removal of edges of section that have no common vertices
993 // with PartsOfTool preserved
994 if (bFlag) {
995 theBuilder.PerformResult();
996 myShape = theBuilder.Shape();
997 } else {
998 myShape = theBuilder.Shape();
999 }
1000 Done();
1001 }
1002 else {
1003 // all is already done
1004 Done();
1005 }
1006 }
1007
1008 myStatusError = BRepFeat_OK;
1009 }
1010
1011 //=======================================================================
1012 //function : IsDeleted
1013 //purpose :
1014 //=======================================================================
1015
IsDeleted(const TopoDS_Shape & F)1016 Standard_Boolean BRepFeat_Form::IsDeleted(const TopoDS_Shape& F)
1017 {
1018 if (myMap.IsBound(F))
1019 {
1020 return (myMap(F).IsEmpty());
1021 }
1022 return Standard_False;
1023 }
1024
1025 //=======================================================================
1026 //function : Modified
1027 //purpose :
1028 //=======================================================================
1029
Modified(const TopoDS_Shape & F)1030 const TopTools_ListOfShape& BRepFeat_Form::Modified
1031 (const TopoDS_Shape& F)
1032 {
1033 myGenerated.Clear();
1034 if (!IsDone())
1035 return myGenerated;
1036
1037 if (mySbase.IsEqual(F))
1038 {
1039 myGenerated.Append(myShape);
1040 return myGenerated;
1041 }
1042
1043 if (myMap.IsBound(F)) {
1044 TopTools_ListIteratorOfListOfShape ite(myMap(F));
1045 for(; ite.More(); ite.Next()) {
1046 const TopoDS_Shape& sh = ite.Value();
1047 if(!sh.IsSame(F) && sh.ShapeType() == F.ShapeType())
1048 myGenerated.Append(sh);
1049 }
1050 }
1051 return myGenerated; // empty list
1052 }
1053
1054 //=======================================================================
1055 //function : Generated
1056 //purpose :
1057 //=======================================================================
1058
Generated(const TopoDS_Shape & S)1059 const TopTools_ListOfShape& BRepFeat_Form::Generated
1060 (const TopoDS_Shape& S)
1061 {
1062 myGenerated.Clear();
1063 if (!IsDone())
1064 return myGenerated;
1065 if (myMap.IsBound(S) &&
1066 S.ShapeType() != TopAbs_FACE) { // check if filter on face or not
1067 TopTools_ListIteratorOfListOfShape ite(myMap(S));
1068 for(; ite.More(); ite.Next()) {
1069 const TopoDS_Shape& sh = ite.Value();
1070 if(!sh.IsSame(S))
1071 myGenerated.Append(sh);
1072 }
1073 return myGenerated;
1074 }
1075 return myGenerated;
1076 }
1077
1078
1079
1080 //=======================================================================
1081 //function : UpdateDescendants
1082 //purpose :
1083 //=======================================================================
1084
UpdateDescendants(const LocOpe_Gluer & G)1085 void BRepFeat_Form::UpdateDescendants(const LocOpe_Gluer& G)
1086 {
1087 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itdm;
1088 TopTools_ListIteratorOfListOfShape it,it2;
1089 TopTools_MapIteratorOfMapOfShape itm;
1090
1091 for (itdm.Initialize(myMap);itdm.More();itdm.Next()) {
1092 const TopoDS_Shape& orig = itdm.Key();
1093 TopTools_MapOfShape newdsc;
1094 for (it.Initialize(itdm.Value());it.More();it.Next()) {
1095 const TopoDS_Face& fdsc = TopoDS::Face(it.Value());
1096 for (it2.Initialize(G.DescendantFaces(fdsc));
1097 it2.More();it2.Next()) {
1098 newdsc.Add(it2.Value());
1099 }
1100 }
1101 myMap.ChangeFind(orig).Clear();
1102 for (itm.Initialize(newdsc);itm.More();itm.Next()) {
1103 myMap.ChangeFind(orig).Append(itm.Key());
1104 }
1105 }
1106 }
1107
1108
1109
1110
1111
1112 //=======================================================================
1113 //function : FirstShape
1114 //purpose :
1115 //=======================================================================
1116
FirstShape() const1117 const TopTools_ListOfShape& BRepFeat_Form::FirstShape() const
1118 {
1119 if (!myFShape.IsNull()) {
1120 return myMap(myFShape);
1121 }
1122 return myGenerated; // empty list
1123 }
1124
1125
1126 //=======================================================================
1127 //function : LastShape
1128 //purpose :
1129 //=======================================================================
1130
LastShape() const1131 const TopTools_ListOfShape& BRepFeat_Form::LastShape() const
1132 {
1133 if (!myLShape.IsNull()) {
1134 return myMap(myLShape);
1135 }
1136 return myGenerated; // empty list
1137 }
1138
1139
1140 //=======================================================================
1141 //function : NewEdges
1142 //purpose :
1143 //=======================================================================
1144
NewEdges() const1145 const TopTools_ListOfShape& BRepFeat_Form::NewEdges() const
1146 {
1147 return myNewEdges;
1148 }
1149
1150
1151 //=======================================================================
1152 //function : NewEdges
1153 //purpose :
1154 //=======================================================================
1155
TgtEdges() const1156 const TopTools_ListOfShape& BRepFeat_Form::TgtEdges() const
1157 {
1158 return myTgtEdges;
1159 }
1160
1161
1162 //=======================================================================
1163 //function : TransformSUntil
1164 //purpose : Limitation of the shape until the case of infinite faces
1165 //=======================================================================
1166
TransformShapeFU(const Standard_Integer flag)1167 Standard_Boolean BRepFeat_Form::TransformShapeFU(const Standard_Integer flag)
1168 {
1169 #ifdef OCCT_DEBUG
1170 Standard_Boolean trc = BRepFeat_GettraceFEAT();
1171 #endif
1172 Standard_Boolean Trf = Standard_False;
1173
1174 TopoDS_Shape shapefu;
1175 if(flag == 0)
1176 shapefu = mySFrom;
1177 else if(flag == 1)
1178 shapefu = mySUntil;
1179 else
1180 return Trf;
1181
1182 TopExp_Explorer exp(shapefu, TopAbs_FACE);
1183 if (!exp.More()) { // no faces... It is necessary to return an error
1184 #ifdef OCCT_DEBUG
1185 if (trc) std::cout << " BRepFeat_Form::TransformShapeFU : invalid Shape" << std::endl;
1186 #endif
1187 return Trf;
1188 }
1189
1190 exp.Next();
1191 if (!exp.More()) { // the only face. Is it infinite?
1192 exp.ReInit();
1193 TopoDS_Face fac = TopoDS::Face(exp.Current());
1194
1195 Handle(Geom_Surface) S = BRep_Tool::Surface(fac);
1196 Handle(Standard_Type) styp = S->DynamicType();
1197 if (styp == STANDARD_TYPE(Geom_RectangularTrimmedSurface)) {
1198 S = Handle(Geom_RectangularTrimmedSurface)::DownCast(S)->BasisSurface();
1199 styp = S->DynamicType();
1200 }
1201
1202 if (styp == STANDARD_TYPE(Geom_Plane) ||
1203 styp == STANDARD_TYPE(Geom_CylindricalSurface) ||
1204 styp == STANDARD_TYPE(Geom_ConicalSurface)) {
1205 TopExp_Explorer exp1(fac, TopAbs_WIRE);
1206 if (!exp1.More()) {
1207 Trf = Standard_True;
1208 }
1209 else {
1210 Trf = BRep_Tool::NaturalRestriction(fac);
1211 }
1212
1213 }
1214 if (Trf) {
1215 BRepFeat::FaceUntil(mySbase, fac);
1216 }
1217
1218 if(flag == 0) {
1219 TopTools_ListOfShape thelist6;
1220 myMap.Bind(mySFrom,thelist6);
1221 myMap(mySFrom).Append(fac);
1222 mySFrom = fac;
1223 }
1224 else if(flag == 1) {
1225 TopTools_ListOfShape thelist7;
1226 myMap.Bind(mySUntil,thelist7);
1227 myMap(mySUntil).Append(fac);
1228 mySUntil = fac;
1229 }
1230 else {
1231 }
1232 }
1233 else {
1234 for (exp.ReInit(); exp.More(); exp.Next()) {
1235 const TopoDS_Shape& fac = exp.Current();
1236 TopTools_ListOfShape thelist8;
1237 myMap.Bind(fac,thelist8);
1238 myMap(fac).Append(fac);
1239 }
1240 }
1241 #ifdef OCCT_DEBUG
1242 if (trc) {
1243 if (Trf && (flag == 0)) std::cout << " TransformShapeFU From" << std::endl;
1244 if (Trf && (flag == 1)) std::cout << " TransformShapeFU Until" << std::endl;
1245 }
1246 #endif
1247 return Trf;
1248 }
1249
1250
1251 //=======================================================================
1252 //function : CurrentStatusError
1253 //purpose :
1254 //=======================================================================
1255
CurrentStatusError() const1256 BRepFeat_StatusError BRepFeat_Form::CurrentStatusError() const
1257 {
1258 return myStatusError;
1259 }
1260
1261 //=======================================================================
1262 //function : Descendants
1263 //purpose :
1264 //=======================================================================
1265
Descendants(const TopoDS_Shape & S,BRepFeat_Builder & theFB,TopTools_MapOfShape & mapF)1266 static void Descendants(const TopoDS_Shape& S,
1267 BRepFeat_Builder& theFB,
1268 TopTools_MapOfShape& mapF)
1269 {
1270 mapF.Clear();
1271 TopTools_ListIteratorOfListOfShape it;
1272 TopExp_Explorer exp;
1273 for (exp.Init(S,TopAbs_FACE); exp.More(); exp.Next()) {
1274
1275 const TopoDS_Face& fdsc = TopoDS::Face(exp.Current());
1276 const TopTools_ListOfShape& aLM=theFB.Modified(fdsc);
1277 it.Initialize(aLM);
1278 for (; it.More(); it.Next()) {
1279 mapF.Add(it.Value());
1280 }
1281
1282 }
1283 }
1284
1285 //=======================================================================
1286 //function : UpdateDescendants
1287 //purpose :
1288 //=======================================================================
UpdateDescendants(const BRepAlgoAPI_BooleanOperation & aBOP,const TopoDS_Shape & S,const Standard_Boolean SkipFace)1289 void BRepFeat_Form::UpdateDescendants(const BRepAlgoAPI_BooleanOperation& aBOP,
1290 const TopoDS_Shape& S,
1291 const Standard_Boolean SkipFace)
1292 {
1293 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itdm;
1294 TopTools_ListIteratorOfListOfShape it,it2;
1295 TopTools_MapIteratorOfMapOfShape itm;
1296 TopExp_Explorer exp;
1297
1298 for (itdm.Initialize(myMap);itdm.More();itdm.Next()) {
1299 const TopoDS_Shape& orig = itdm.Key();
1300 if (SkipFace && orig.ShapeType() == TopAbs_FACE) {
1301 continue;
1302 }
1303 TopTools_MapOfShape newdsc;
1304
1305 if (itdm.Value().IsEmpty()) {myMap.ChangeFind(orig).Append(orig);}
1306
1307 for (it.Initialize(itdm.Value());it.More();it.Next()) {
1308 const TopoDS_Shape& sh = it.Value();
1309 if(sh.ShapeType() != TopAbs_FACE) continue;
1310 const TopoDS_Face& fdsc = TopoDS::Face(it.Value());
1311 for (exp.Init(S,TopAbs_FACE);exp.More();exp.Next()) {
1312 if (exp.Current().IsSame(fdsc)) { // preserved
1313 newdsc.Add(fdsc);
1314 break;
1315 }
1316 }
1317 if (!exp.More()) {
1318 BRepAlgoAPI_BooleanOperation* pBOP=(BRepAlgoAPI_BooleanOperation*)&aBOP;
1319 const TopTools_ListOfShape& aLM=pBOP->Modified(fdsc);
1320 it2.Initialize(aLM);
1321 for (; it2.More(); it2.Next()) {
1322 const TopoDS_Shape& aS=it2.Value();
1323 newdsc.Add(aS);
1324 }
1325
1326 }
1327 }
1328 myMap.ChangeFind(orig).Clear();
1329 for (itm.Initialize(newdsc); itm.More(); itm.Next()) {
1330 // check the appartenance to the shape...
1331 for (exp.Init(S,TopAbs_FACE);exp.More();exp.Next()) {
1332 if (exp.Current().IsSame(itm.Key())) {
1333 // const TopoDS_Shape& sh = itm.Key();
1334 myMap.ChangeFind(orig).Append(itm.Key());
1335 break;
1336 }
1337 }
1338 }
1339 }
1340 }
1341