1 #ifdef OCCGEOMETRY
2
3 // GEOM PARTITION : partition algorithm
4 //
5 // Copyright (C) 2003 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
6 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
7 //
8 // This library is free software; you can redistribute it and/or
9 // modify it under the terms of the GNU Lesser General Public
10 // License as published by the Free Software Foundation; either
11 // version 2.1 of the License.
12 //
13 // This library is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 // Lesser General Public License for more details.
17 //
18 // You should have received a copy of the GNU Lesser General Public
19 // License along with this library; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21 //
22 // See http://www.opencascade.org/SALOME/ or email : webmaster.salome@opencascade.org
23 //
24 //
25 //
26 // File : Partition_Spliter.cxx
27 // Author : Benedicte MARTIN
28 // Module : GEOM
29 // $Header: /cvs/netgen/netgen/libsrc/occ/Partition_Spliter.cxx,v 1.7 2008/03/31 14:20:28 wabro Exp $
30
31 //using namespace std;
32 #include <climits>
33 #include "Partition_Inter2d.hxx"
34 #include "Partition_Inter3d.hxx"
35 #include "Partition_Loop2d.hxx"
36 #include "Partition_Loop3d.hxx"
37 #include "Partition_Spliter.ixx"
38
39 #include "utilities.h"
40
41 #include <Precision.hxx>
42 #include <TopAbs_Orientation.hxx>
43 #include <TopExp.hxx>
44 #include <TopExp_Explorer.hxx>
45
46 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
47 #include <TopTools_DataMapOfShapeListOfShape.hxx>
48 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
49 #include <TopTools_IndexedMapOfShape.hxx>
50 #include <TopTools_ListIteratorOfListOfShape.hxx>
51 #include <TopTools_ListOfShape.hxx>
52 #include <TopTools_MapIteratorOfMapOfShape.hxx>
53 #include <TopTools_SequenceOfShape.hxx>
54
55 #include <Geom2d_Curve.hxx>
56 #include <Geom_Curve.hxx>
57 #include <Geom_Surface.hxx>
58 #include <Geom_TrimmedCurve.hxx>
59 #include <gp_Pnt.hxx>
60 #include <gp_Pnt2d.hxx>
61 #include <gp_Vec.hxx>
62
63 #include <TopoDS.hxx>
64 #include <TopoDS_Compound.hxx>
65 #include <TopoDS_Edge.hxx>
66 #include <TopoDS_Face.hxx>
67 #include <TopoDS_Iterator.hxx>
68 #include <TopoDS_Shell.hxx>
69 #include <TopoDS_Solid.hxx>
70 #include <TopoDS_Vertex.hxx>
71 #include <TopoDS_Wire.hxx>
72
73 #include <BRepBndLib.hxx>
74 #include <BRepClass3d_SolidClassifier.hxx>
75 #include <BRepLib.hxx>
76 #include <BRep_Tool.hxx>
77
78 #include <Extrema_ExtPC.hxx>
79 #include <GeomAdaptor_Curve.hxx>
80 #include <TopOpeBRepTool_CurveTool.hxx>
81
82 #ifdef DEB
83 //# define PART_PERF
84 #endif
85
86 #ifdef PART_PERF
87 # include <OSD_Chronometer.hxx>
88 #endif
89
90 //=======================================================================
91 //function : isClosed
92 //purpose : check id a shape is closed, ie is a solid or a closed shell
93 //=======================================================================
94
isClosed(const TopoDS_Shape & theShape)95 static Standard_Boolean isClosed(const TopoDS_Shape& theShape)
96 {
97 Standard_Boolean isClosed = (theShape.ShapeType() == TopAbs_SOLID);
98
99 if (!isClosed && theShape.ShapeType() == TopAbs_SHELL) {
100 TopTools_IndexedDataMapOfShapeListOfShape MEF;
101 TopExp::MapShapesAndAncestors(theShape, TopAbs_EDGE, TopAbs_FACE, MEF);
102 for (Standard_Integer i=1; isClosed && i<=MEF.Extent(); ++i)
103 isClosed = ( MEF(i).Extent() != 1 );
104 }
105
106 return isClosed;
107 }
108
109 //=======================================================================
110 //function : Partition_Spliter
111 //purpose : constructor
112 //=======================================================================
113
Partition_Spliter()114 Partition_Spliter::Partition_Spliter()
115 {
116 myAsDes = new BRepAlgo_AsDes;
117 Clear();
118 }
119
120 //=======================================================================
121 //function : AddTool
122 //purpose : add cutting tool that will _NOT_ be in result
123 //=======================================================================
124
AddTool(const TopoDS_Shape & S)125 void Partition_Spliter::AddTool(const TopoDS_Shape& S)
126 {
127 if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid
128 TopoDS_Iterator it (S);
129 for (; it.More(); it.Next())
130 {
131 AddTool( it.Value());
132 myFaceShapeMap.Bind( it.Value(), S ); // to know compound by shape
133 }
134 return;
135 }
136
137 for (TopExp_Explorer exp(S,TopAbs_FACE); exp.More(); exp.Next())
138 {
139 myMapTools.Add(exp.Current());
140 myFaceShapeMap.Bind( exp.Current(), S );
141 }
142 if (isClosed( S ))
143 myClosedShapes.Add( S );
144 }
145
146 //=======================================================================
147 //function : AddShape
148 //purpose : add object Shape to be splited
149 //=======================================================================
150
AddShape(const TopoDS_Shape & S)151 void Partition_Spliter::AddShape(const TopoDS_Shape& S)
152 {
153 if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid
154 TopoDS_Iterator it (S);
155 for (; it.More(); it.Next())
156 {
157 AddShape( it.Value());
158 myFaceShapeMap.Bind( it.Value(), S ); // to know compound by shape
159 }
160 return;
161 }
162
163 TopExp_Explorer exp(S,TopAbs_FACE);
164 if (!exp.More()) { // do not split edges and vertices
165 //myBuilder.Add( myShape, S );
166 return;
167 }
168
169 Standard_Integer nbFacesBefore = myMapFaces.Extent(); // not to add twice the same S
170 for (; exp.More(); exp.Next()) {
171 const TopoDS_Shape & aFace = exp.Current();
172 if ( ! myFaceShapeMap.IsBound( aFace )) // keep shape of tool face added as object
173 myFaceShapeMap.Bind( aFace, S );
174 if (myMapFaces.Add( aFace ))
175 myImagesFaces.SetRoot( aFace );
176 }
177
178 if (nbFacesBefore == myMapFaces.Extent())
179 return;
180
181 // solids must be processed before all
182 if (S.ShapeType() == TopAbs_SOLID)
183 myListShapes.Prepend(S);
184 else
185 myListShapes.Append(S);
186
187 if (isClosed( S ))
188 myClosedShapes.Add( S );
189
190 }
191
192 //=======================================================================
193 //function : Shape
194 //purpose : return resulting compound
195 //=======================================================================
196
Shape() const197 TopoDS_Shape Partition_Spliter::Shape() const
198 {
199 return myShape;
200 }
201
202 //=======================================================================
203 //function : Clear
204 //purpose : clear fields
205 //=======================================================================
206
Clear()207 void Partition_Spliter::Clear()
208 {
209 myDoneStep = TopAbs_SHAPE;
210
211 myListShapes.Clear();
212 myMapFaces.Clear();
213 myMapTools.Clear();
214 myEqualEdges.Clear();
215 myNewSection.Clear();
216 myClosedShapes.Clear();
217 mySharedFaces.Clear();
218 myWrappingSolid.Clear();
219 myFaceShapeMap.Clear();
220
221 myInternalFaces.Clear();
222 myIntNotClFaces.Clear();
223
224 myAsDes->Clear();
225 myImagesFaces.Clear();
226 myImagesEdges.Clear();
227 myImageShape.Clear();
228
229 // myInter3d = Partition_Inter3d(myAsDes);
230 Partition_Inter3d hinter3d (myAsDes);
231 myInter3d = hinter3d;
232
233 myAddedFacesMap.Clear();
234
235 }
236
237 //=======================================================================
238 //function : Compute
239 //purpose : produce a result
240 //=======================================================================
241
Compute(const TopAbs_ShapeEnum Limit)242 void Partition_Spliter::Compute(const TopAbs_ShapeEnum Limit)
243 {
244 if ((Limit != TopAbs_SHAPE && myDoneStep == Limit) ||
245 (Limit == TopAbs_SHAPE && myDoneStep == TopAbs_SOLID))
246 return;
247
248 myBuilder.MakeCompound( myShape );
249
250 TopTools_MapIteratorOfMapOfShape it;
251 TopTools_ListIteratorOfListOfShape itl;
252 TopExp_Explorer exp;
253
254 #ifdef PART_PERF
255 OSD_Chronometer aCron;
256 #endif
257
258 if (myDoneStep > TopAbs_VERTEX) {
259
260 TopTools_ListOfShape aListFaces;
261 aListFaces = myImagesFaces.Roots();
262 for (it.Initialize(myMapTools); it.More(); it.Next())
263 aListFaces.Append(it.Key());
264
265 #ifdef PART_PERF
266 aCron.Start();
267 #endif
268
269 //-----------------------------------------------
270 // Intersection between faces
271 //-----------------------------------------------
272 // result is in myAsDes as a map Face - list of new edges;
273 // special care is done for section edges, same domain faces and vertices:
274 // data about them is inside myInter3d
275 myInter3d.CompletPart3d(aListFaces, myFaceShapeMap);
276
277 #ifdef PART_PERF
278 MESSAGE("+++ CompletPart3d()");
279 aCron.Show( cout );
280 aCron.Reset();
281 aCron.Start();
282 #endif
283 //-----------------------------------------------
284 // Intersection of edges
285 //-----------------------------------------------
286
287 // add tool faces which must be reconstructed to myMapFaces too
288 FindToolsToReconstruct();
289
290 #ifdef PART_PERF
291 MESSAGE("+++ FindToolsToReconstruct()");
292 aCron.Show( cout );
293 aCron.Reset();
294 aCron.Start();
295 #endif
296
297 // add existing vertices to edges of object faces in myAsDes
298 TopTools_MapOfShape DoneEM;
299 for ( it.Initialize(myMapFaces); it.More(); it.Next()) {
300 const TopoDS_Shape& F = it.Key();
301 TopoDS_Face FForward = TopoDS::Face(F.Oriented(TopAbs_FORWARD));
302 for (exp.Init(FForward,TopAbs_EDGE); exp.More(); exp.Next()) {
303 const TopoDS_Edge& E = TopoDS::Edge( exp.Current() );
304 myAsDes->Add(FForward,E);
305 if (DoneEM.Add(E)) {
306 TopoDS_Iterator itV(E);
307 for (; itV.More(); itV.Next()) {
308 const TopoDS_Vertex& V = TopoDS::Vertex( itV.Value());
309 myAsDes->Add(E, myInter3d.ReplaceSameDomainV( V, E ));
310 }
311 }
312 }
313 }
314
315 // intersect edges that are descendants of a face in myAsDes
316 TopTools_MapOfShape& Modif = myInter3d.TouchedFaces();
317 for ( it.Initialize(Modif); it.More(); it.Next()) {
318 const TopoDS_Face& F = TopoDS::Face(it.Key());
319 Partition_Inter2d::CompletPart2d (myAsDes, F, myInter3d.NewEdges());
320 }
321 // now myAsDes contains also new vertices made at edge intersection as
322 // descendant of edges both new and old
323
324 myDoneStep = TopAbs_VERTEX;
325
326 #ifdef PART_PERF
327 MESSAGE("+++ CompletPart2d()");
328 aCron.Show( cout );
329 aCron.Reset();
330 aCron.Start();
331 #endif
332 } // if (myDoneStep > TopAbs_VERTEX)
333
334 if (Limit == TopAbs_VERTEX) {
335 // add new vertices to myShape
336 for ( it.Initialize( myInter3d.NewEdges() ); it.More(); it.Next()) {
337 if (! myAsDes->HasDescendant( it.Key() ))
338 continue;
339 itl.Initialize( myAsDes->Descendant( it.Key() ));
340 for (; itl.More(); itl.Next())
341 myBuilder.Add ( myShape, itl.Value() );
342 }
343 return;
344 }
345
346
347 if (myDoneStep > TopAbs_EDGE) {
348
349 //-----------------------------------------------
350 //-----------------------------------------------
351 // ------- Reconstruction of all the edges.------
352 //-----------------------------------------------
353 //-----------------------------------------------
354
355 // ==============
356 // cut new edges
357 // ==============
358 TopTools_ListOfShape LSE; // all edge splits
359 for ( it.Initialize(myInter3d.NewEdges()); it.More(); it.Next()) {
360
361 TopoDS_Vertex V1,V2;
362 TopoDS_Edge EE = TopoDS::Edge(it.Key());
363
364 TopTools_ListOfShape aListV, aListF;
365 aListV = myAsDes->Descendant(EE); // intersection vertices
366 aListF = myAsDes->Ascendant(EE); // intersected faces
367
368 if (aListV.IsEmpty())
369 continue; // new edge does not intersect any other edge
370
371 // Add end vertices to new edges only if
372 // one face is Tool and the other is Shape
373 Standard_Boolean isTool1 = ! myMapFaces.Contains( aListF.First() );
374 Standard_Boolean isTool2 = ! myMapFaces.Contains( aListF.Last() );
375 if (isTool1 || isTool2)
376 {
377 TopExp::Vertices(EE,V1,V2);
378 Standard_Real Tol = Max (BRep_Tool::Tolerance( V1 ),
379 BRep_Tool::Tolerance( V2 ));
380
381 gp_Pnt P1 = BRep_Tool::Pnt(V1);
382 gp_Pnt P2 = BRep_Tool::Pnt(V2);
383 Standard_Boolean AddV1 = Standard_True;
384 Standard_Boolean AddV2 = Standard_True;
385
386 // add only if there is no intersection at end vertex
387 for (itl.Initialize(aListV); itl.More(); itl.Next()) {
388 const TopoDS_Vertex& Ve = TopoDS::Vertex(itl.Value()) ;
389 Standard_Real Tol2 = Max ( Tol, BRep_Tool::Tolerance( Ve ));
390 Tol2 *= Tol2;
391 gp_Pnt P = BRep_Tool::Pnt(Ve);
392 if (AddV1 && P.SquareDistance(P1) <= Tol2)
393 AddV1 = Standard_False;
394
395 if (AddV2 && P.SquareDistance(P2) <= Tol2)
396 AddV2 = Standard_False;
397 }
398
399 if (AddV1) {
400 aListV.Append(V1);
401 myAsDes->Add(EE,V1);
402 }
403
404 if (AddV2) {
405 aListV.Append(V2);
406 myAsDes->Add(EE,V2);
407 }
408 }
409
410 // cut new edges
411 Standard_Integer NbV=aListV.Extent() ;
412 if (NbV>1 || (NbV==1 && V1.IsSame(V2)) ) {
413 TopTools_ListOfShape LNE;
414 MakeEdges (EE,aListV, LNE);
415 myImagesEdges.Bind(EE,LNE);
416 LSE.Append( LNE );
417 }
418 }
419
420 // ==============
421 // cut old edges
422 // ==============
423 for ( it.Initialize(myMapFaces); it.More(); it.Next()) {
424 for (exp.Init( it.Key(), TopAbs_EDGE); exp.More(); exp.Next()) {
425 const TopoDS_Edge& EE = TopoDS::Edge( exp.Current() );
426 if ( myImagesEdges.HasImage( EE ))
427 continue;
428 TopTools_ListOfShape LNE;
429 const TopTools_ListOfShape& aListVV = myAsDes->Descendant(EE);
430 MakeEdges (EE, aListVV, LNE);
431 myImagesEdges.Bind(EE,LNE);
432 LSE.Append( LNE );
433 }
434 }
435 #ifdef PART_PERF
436 MESSAGE("+++ Cut Edges");
437 aCron.Show( cout );
438 aCron.Reset();
439 aCron.Start();
440 #endif
441
442 // process same domain section edges
443 MergeEqualEdges( LSE );
444
445 myDoneStep = TopAbs_EDGE;
446
447 #ifdef PART_PERF
448 MESSAGE("+++ MergeEqualEdges()");
449 aCron.Show( cout );
450 aCron.Reset();
451 aCron.Start();
452 #endif
453 } // if (myDoneStep > TopAbs_EDGE)
454
455 if (Limit == TopAbs_EDGE) {
456 // add splits of old edges
457 TopTools_ListIteratorOfListOfShape itNE;
458 for (itl.Initialize( myListShapes );itl.More();itl.Next()) {
459 if (myMapTools.Contains( itl.Value() ))
460 continue; // skip tool faces
461 for ( exp.Init( itl.Value(), TopAbs_EDGE ); exp.More(); exp.Next()) {
462 itNE.Initialize( myImagesEdges.Image( exp.Current() ));
463 for ( ; itNE.More(); itNE.Next())
464 myBuilder.Add ( myShape, itNE.Value() );
465 }
466 }
467 // add splits of new edges
468 for ( it.Initialize( myInter3d.NewEdges() ); it.More(); it.Next()) {
469 itNE.Initialize( myImagesEdges.Image( it.Key() ));
470 for (; itNE.More(); itNE.Next())
471 myBuilder.Add ( myShape, itNE.Value() );
472 }
473 return;
474 }
475
476
477 //-----------------------------------------------
478 // split faces
479 //-----------------------------------------------
480
481 if (myDoneStep > TopAbs_FACE) {
482
483 for (itl.Initialize(myListShapes);itl.More();itl.Next()) {
484 TopoDS_Shape FacesComp = MakeFaces ( itl.Value());
485 // there is a cunning here: myImagesFaces keeps faces made by Loop2d
486 // but some of them may be replaced with splits of same domain face
487 // and myImageShape keeps ultimate result
488 myImageShape.Bind( itl.Value(), FacesComp );
489 }
490
491 myDoneStep = TopAbs_FACE;
492 #ifdef PART_PERF
493 MESSAGE("+++ MakeFaces()");
494 aCron.Show( cout );
495 aCron.Reset();
496 aCron.Start();
497 #endif
498 }
499
500 if (Limit == TopAbs_WIRE ||
501 Limit == TopAbs_FACE) {
502 for (itl.Initialize(myListShapes);itl.More();itl.Next()) {
503 if ( myMapTools.Contains( itl.Value() ))
504 continue; // no result needed for a tool face
505 const TopoDS_Shape& FacesComp = myImageShape.Image( itl.Value() ).First();
506 for ( exp.Init( FacesComp, Limit); exp.More(); exp.Next())
507 myBuilder.Add ( myShape, exp.Current());
508 }
509 return;
510 }
511
512
513 //-----------------------------------------------
514 // split and add solids and shells
515 //-----------------------------------------------
516
517 Standard_Boolean makeSolids = (Limit == TopAbs_SHAPE ||
518 Limit < TopAbs_SHELL);
519 for (itl.Initialize(myListShapes);itl.More();itl.Next())
520 {
521 const TopoDS_Shape & S = itl.Value();
522 if (S.ShapeType() > TopAbs_SHELL)
523 continue;
524
525 TopTools_ListOfShape NSL; // new shape list
526 MakeShells (S , NSL);
527 if (makeSolids && S.ShapeType() == TopAbs_SOLID )
528 MakeSolids( S, NSL );
529
530 // store new shells or solids
531 TopTools_ListIteratorOfListOfShape itNSL (NSL);
532 for ( ; itNSL.More(); itNSL.Next())
533 myBuilder.Add (myShape, itNSL.Value());
534 }
535 #ifdef PART_PERF
536 MESSAGE("+++ MakeShells()");
537 aCron.Show( cout );
538 #endif
539
540 //-----------------------------------------------
541 // add split faces
542 //-----------------------------------------------
543
544 for (itl.Initialize(myListShapes);itl.More();itl.Next())
545 {
546 const TopoDS_Shape & S = itl.Value();
547 if (S.ShapeType() != TopAbs_FACE ||
548 myMapTools.Contains( S ))
549 continue;
550 TopoDS_Iterator itS( myImageShape.Image(S).First() );
551 for (; itS.More(); itS.Next())
552 if (! myAddedFacesMap.Contains( itS.Value() ))
553 myBuilder.Add (myShape, itS.Value());
554 }
555
556 myDoneStep = makeSolids ? TopAbs_SOLID : TopAbs_SHELL;
557
558 }
559
560 //=======================================================================
561 //function : MakeSolids
562 //purpose : make solids out of Shells
563 //=======================================================================
564
MakeSolids(const TopoDS_Shape & theSolid,TopTools_ListOfShape & theShellList)565 void Partition_Spliter::MakeSolids(const TopoDS_Shape & theSolid,
566 TopTools_ListOfShape & theShellList)
567 {
568 // for a solid wrapping other shells or solids without intersection,
569 // it is necessary to find shells making holes in it
570
571 TopTools_ListOfShape aNewSolids; // result
572 TopTools_ListOfShape aHoleShells;
573 TopoDS_Shape anInfinitePointShape;
574
575 Standard_Boolean isWrapping = myWrappingSolid.Contains( theSolid );
576 if (!isWrapping && !theShellList.IsEmpty())
577 {
578 // check if theSolid initially has internal shells
579 TopoDS_Iterator aShellExp (theSolid);
580 aShellExp.Next();
581 isWrapping = aShellExp.More();
582 }
583
584 TopTools_ListIteratorOfListOfShape aShellIt(theShellList);
585 for ( ; aShellIt.More(); aShellIt.Next())
586 {
587 const TopoDS_Shape & aShell = aShellIt.Value();
588
589 // check if a shell is a hole
590 if (isWrapping && IsInside (anInfinitePointShape, aShell))
591 aHoleShells.Append( aShell );
592 else
593 {
594 // make a solid from a shell
595 TopoDS_Solid Solid;
596 myBuilder.MakeSolid( Solid );
597 myBuilder.Add (Solid, aShell);
598
599 aNewSolids.Append (Solid);
600 }
601 }
602
603 // find an outer shell most close to each hole shell
604 TopTools_DataMapOfShapeShape aInOutMap;
605 for (aShellIt.Initialize( aHoleShells ); aShellIt.More(); aShellIt.Next())
606 {
607 const TopoDS_Shape & aHole = aShellIt.Value();
608 TopTools_ListIteratorOfListOfShape aSolisIt (aNewSolids);
609 for ( ; aSolisIt.More(); aSolisIt.Next())
610 {
611 const TopoDS_Shape & aSolid = aSolisIt.Value();
612 if (! IsInside( aHole, aSolid ))
613 continue;
614
615 if ( aInOutMap.IsBound (aHole))
616 {
617 const TopoDS_Shape & aSolid2 = aInOutMap( aHole );
618 if ( IsInside( aSolid, aSolid2 ))
619 {
620 aInOutMap.UnBind( aHole );
621 aInOutMap.Bind ( aHole, aSolid );
622 }
623 }
624 else
625 aInOutMap.Bind ( aHole, aSolid );
626 }
627
628 // add aHole to a solid
629 if (aInOutMap.IsBound( aHole ))
630 myBuilder.Add ( aInOutMap( aHole ), aHole );
631 }
632
633 theShellList.Clear();
634 theShellList.Append( aNewSolids );
635 }
636
637 //=======================================================================
638 //function : FindFacesInside
639 //purpose : return compound of faces of other shapes that are
640 // inside <theShape>.
641 // <theShape> is an object shape.
642 // <CheckClosed> makes avoid faces that do not form a
643 // closed shell
644 // <All> makes return already added faces
645 //=======================================================================
646
FindFacesInside(const TopoDS_Shape & theShape,const Standard_Boolean CheckClosed,const Standard_Boolean All)647 TopoDS_Shape Partition_Spliter::FindFacesInside(const TopoDS_Shape& theShape,
648 const Standard_Boolean CheckClosed,
649 const Standard_Boolean All)
650 {
651 // ================================================
652 // check if internal faces have been already found
653 // ================================================
654 TopExp_Explorer expl;
655 if (myInternalFaces.IsBound( theShape ))
656 {
657 TopoDS_Shape aIntFComp = myInternalFaces.Find ( theShape );
658 TopoDS_Shape aIntRemFComp = myIntNotClFaces.Find ( theShape );
659
660 expl.Init( aIntRemFComp, TopAbs_FACE);
661 if (CheckClosed || !expl.More())
662 return aIntFComp;
663
664 TopoDS_Compound C;
665 myBuilder.MakeCompound( C );
666 // add removed faces
667 for (; expl.More(); expl.Next())
668 myBuilder.Add( C, expl.Current() );
669 // add good internal faces
670 for (expl.Init( aIntFComp, TopAbs_FACE); expl.More(); expl.Next())
671 myBuilder.Add( C, expl.Current() );
672 return C;
673 }
674
675 // ===================================
676 // get data for internal faces search
677 // ===================================
678
679 // compound of split faces of theShape
680 const TopoDS_Shape& CSF = myImageShape.Image(theShape).First();
681
682 TopTools_MapOfShape MSE, MFP;
683 TopTools_DataMapOfShapeListOfShape DMSEFP;
684 TopTools_MapIteratorOfMapOfShape itm;
685 TopTools_ListOfShape EmptyL;
686
687 // MSE filling: map of new section edges of CSF
688 for (expl.Init(CSF,TopAbs_EDGE); expl.More(); expl.Next()) {
689 const TopoDS_Shape & resE = expl.Current() ;
690 if (myNewSection.Contains( resE )) // only new edges
691 MSE.Add(resE);
692 }
693
694 // DMEF: map edge of CSF - faces of CSF
695 TopTools_IndexedDataMapOfShapeListOfShape DMEF;
696 TopExp::MapShapesAndAncestors(CSF, TopAbs_EDGE, TopAbs_FACE, DMEF);
697
698 // Fill
699 // 1. MFP - a map of faces to process: map of resulting faces except
700 // those of theShape; we`ll add to C those of them which are inside CSF
701 // 2. DMSEFP - edge of MSE => faces of MFP
702 TopTools_ListIteratorOfListOfShape itl;
703 for (itl.Initialize(myListShapes);itl.More();itl.Next()) {
704 const TopoDS_Shape& aShape = itl.Value();
705 if ( theShape.IsSame( aShape )) continue;
706 // fill maps
707 // iterate on split faces of aShape
708 TopoDS_Iterator itF ( myImageShape.Image(aShape).First() );
709 for ( ; itF.More(); itF.Next()) {
710 const TopoDS_Shape& sf = itF.Value();
711 MFP.Add(sf);
712 // iterate on edges of split faces of aShape,
713 // add to DMSEFP edges that are new
714 for (expl.Init( sf, TopAbs_EDGE ); expl.More(); expl.Next()) {
715 TopoDS_Shape se = expl.Current();
716 if ( MSE.Contains(se)) {// section edge
717 if (!DMSEFP.IsBound(se))
718 DMSEFP.Bind(se,EmptyL);
719 DMSEFP(se).Append(sf);
720 }
721 }
722 }
723 }
724
725 // add tool faces having section edges on faces of theShape to MFP and DMSEFP;
726 // such tool faces need not to be reconstructed and so they are not in myListShapes
727 for (itm.Initialize(myMapTools); itm.More(); itm.Next())
728 {
729 const TopoDS_Shape & aToolFace = itm.Key();
730 if (myMapFaces.Contains( aToolFace ))
731 continue;
732 MFP.Add(aToolFace);
733 for (expl.Init( aToolFace, TopAbs_EDGE ); expl.More(); expl.Next()) {
734 TopoDS_Shape se = expl.Current();
735 if ( MSE.Contains( se )) {// section edge
736 if (!DMSEFP.IsBound( se ))
737 DMSEFP.Bind( se, EmptyL );
738 DMSEFP( se ).Append( aToolFace );
739 }
740 }
741 }
742
743
744 // ===========================
745 // find faces inside theShape
746 // ===========================
747
748 Standard_Boolean skipAlreadyAdded = Standard_False;
749 Standard_Boolean GoodOri, inside;
750 Standard_Real dot;
751 TopTools_ListOfShape KeepFaces;
752 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape Mapit;
753
754 // iterate on section edges, check faces of other shapes
755 // sharing section edges and put internal faces to KeepFaces
756 for (Mapit.Initialize(DMSEFP); Mapit.More() ; Mapit.Next() ) {
757 // a new edge of theShape
758 const TopoDS_Edge& E = TopoDS::Edge (Mapit.Key());
759 // an original edge of which E is a split
760 const TopoDS_Edge& OrigE = TopoDS::Edge ( myImagesEdges.Root( E ));
761 // does OrigE itself splits a face
762 Standard_Boolean isSectionE = myInter3d.IsSectionEdge ( OrigE );
763
764 // split faces of other shapes sharing E
765 TopTools_ListOfShape& LSF = DMSEFP.ChangeFind(E);
766 itl.Initialize( LSF );
767 while (itl.More()) {
768 // a split faces of other shape
769 TopoDS_Face aFace1 = TopoDS::Face(itl.Value());
770 // remove aFace1 form DMSEFP and MFP
771 LSF.Remove( itl ); // == itl.Next();
772 if (!MFP.Remove( aFace1 ))
773 continue; // was not is MFP ( i.e already checked)
774 // check if aFace1 was already added to 2 shells
775 if (!All &&
776 myAddedFacesMap.Contains( aFace1 ) &&
777 myAddedFacesMap.Contains( aFace1.Reversed() )) {
778 skipAlreadyAdded = Standard_True;
779 continue;
780 }
781
782 // find another face which originates from the same face as aFace1:
783 // usually aFace2 is internal if aFace1 is not and vice versa
784
785 TopoDS_Shape anOrigFace = aFace1;
786 if (myImagesFaces.IsImage(aFace1))
787 anOrigFace = myImagesFaces.Root(aFace1);
788 TopoDS_Shape aFace2;
789 if ( !isSectionE ) {
790 while (itl.More()) {
791 aFace2 = itl.Value();
792 if (!MFP.Contains( aFace2 )) {
793 LSF.Remove( itl );
794 continue;
795 }
796 if (anOrigFace.IsSame( myImagesFaces.Root( aFace2 )))
797 break;
798 itl.Next();
799 }
800 if (itl.More()) { // aFace2 found, remove it from maps
801 LSF.Remove( itl );
802 MFP.Remove(aFace2);
803 }
804 else
805 aFace2.Nullify();
806 itl.Initialize( LSF );
807 }
808
809 // check that anOrigFace is not same domain with CSF faces it intersects
810
811 const TopTools_ListOfShape& FL = DMEF.FindFromKey(E); //faces of CSF sharing E
812 const TopoDS_Shape& origF1 = myImagesFaces.Root(FL.First());
813 const TopoDS_Shape& origF2 = myImagesFaces.Root(FL.Last());
814 Standard_Boolean sameDom1 = anOrigFace.IsSame( origF1 );
815 Standard_Boolean sameDom2 = anOrigFace.IsSame( origF2 );
816 if (!(sameDom1 || sameDom2) && myInter3d.HasSameDomainF( anOrigFace )) {
817 sameDom1 = myInter3d.IsSameDomainF( anOrigFace, origF1);
818 if (origF1 == origF2)
819 sameDom2 = sameDom1;
820 else
821 myInter3d.IsSameDomainF( anOrigFace, origF2);
822 }
823 if (sameDom1 && sameDom2)
824 continue;
825 if ((sameDom1 || sameDom2)) {
826 inside = Partition_Loop3d::IsInside (E,
827 TopoDS::Face(FL.First()),
828 TopoDS::Face(FL.Last()),
829 1, dot, GoodOri);
830 if (inside || (dot + Precision::Angular() >= 1.0))
831 continue; // E is convex between origF1 and origF2 or they are tangent
832 }
833
834
835 // keep one of found faces
836
837 //face of CSF sharing E
838 const TopoDS_Shape& aShapeFace = sameDom1 ? FL.Last() : FL.First();
839 // analyse aFace1 state
840 inside = Partition_Loop3d::IsInside (E, TopoDS::Face(aShapeFace), aFace1,
841 1, dot, GoodOri);
842 if (inside && isSectionE)
843 {
844 // aFace1 must be tested with both adjacent faces of CSF
845 const TopoDS_Shape& aShapeFace2 = sameDom1 ? FL.First() : FL.Last();
846 if (aShapeFace2 != aShapeFace)
847 inside = Partition_Loop3d::IsInside (E, TopoDS::Face(aShapeFace2), aFace1,
848 1, dot, GoodOri);
849 }
850
851 // store internal face
852 if (inside)
853 KeepFaces.Append(aFace1);
854
855 else if (!aFace2.IsNull())
856 {
857 if (dot + Precision::Angular() >= 1.0)
858 {
859 // aFace2 state is not clear, it will be analysed alone,
860 // put it back to the maps
861 MFP.Add( aFace2 );
862 LSF.Append( aFace2 );
863 }
864 else
865 KeepFaces.Append(aFace2);
866 }
867 }
868 }
869
870 // ===================================================
871 // add not distributed faces connected with KeepFaces
872 // ===================================================
873
874 // ultimate list of internal faces
875 TopTools_ListOfShape KeptFaces;
876
877 // add to MFP not split tool faces as well, they may be connected with
878 // tool faces interfering with theShape
879 for ( itm.Initialize(myMapTools); itm.More(); itm.Next() ) {
880 const TopoDS_Shape& aToolFace = itm.Key();
881 if (!myImageShape.HasImage(aToolFace))
882 MFP.Add (aToolFace);
883 }
884
885 if (MFP.IsEmpty())
886 KeptFaces.Append (KeepFaces);
887
888 while (!KeepFaces.IsEmpty())
889 {
890 // KeepEdges : map of edges of faces kept last time
891 TopTools_IndexedMapOfShape KeepEdges;
892 for ( itl.Initialize(KeepFaces); itl.More(); itl.Next() ) {
893 TopExp::MapShapes( itl.Value(), TopAbs_EDGE, KeepEdges);
894 KeptFaces.Append( itl.Value() );
895 }
896
897 KeepFaces.Clear();
898
899 // keep faces connected with already kept faces by KeepEdges
900 for ( itm.Initialize(MFP); itm.More(); itm.Next() ) {
901 const TopoDS_Shape& FP = itm.Key();
902 for (expl.Init(FP,TopAbs_EDGE); expl.More(); expl.Next()) {
903 const TopoDS_Shape& se = expl.Current();
904 if (!MSE.Contains(se) && KeepEdges.Contains(se) ) {
905 KeepFaces.Append(FP);
906 MFP.Remove(FP);
907 break;
908 }
909 }
910 }
911 }
912
913 // ===============================================================
914 // here MFP contains faces outer of theShape and those of shapes
915 // which do not interfere with theShape at all and between which
916 // there may be those wrapped by theShape and whose faces may be
917 // needed to be returned as well
918 // ===============================================================
919
920 Standard_Boolean isSolid = (theShape.ShapeType() == TopAbs_SOLID);
921 if (All || isSolid) // All is for sub-result removal
922 {
923 // loop on not used faces; checked faces will be removed from MFP
924 // during the loop
925 for ( itm.Initialize( MFP ); itm.More(); itm.Next() ) {
926 const TopoDS_Shape & aFace = itm.Key();
927
928 // a shape which aFace originates from
929 TopoDS_Shape anOrigShape = GetOriginalShape( aFace );
930
931 // find out if all split faces of anOrigShape are not in MFP
932 // and by the way remove them from MFP
933 Standard_Boolean isAllOut = Standard_True;
934 TopoDS_Shape aSplitFaces = anOrigShape;
935 if (myImageShape.HasImage(anOrigShape))
936 aSplitFaces = myImageShape.Image(anOrigShape).First();
937
938 TopTools_ListOfShape aSplitFaceL; // faces candidate to be kept
939 for (expl.Init( aSplitFaces, TopAbs_FACE ); expl.More(); expl.Next())
940 {
941 const TopoDS_Shape & aSpFace = expl.Current();
942 // a tool face which became object has image but the whole tool shape has not
943 if (myImageShape.HasImage( aSpFace ))
944 {
945 TopExp_Explorer exF (myImageShape.Image( aSpFace ).First(), TopAbs_FACE );
946 for ( ; exF.More(); exF.Next() )
947 {
948 aSplitFaceL.Append( exF.Current() );
949 if ( ! MFP.Remove( exF.Current() ) && isAllOut )
950 // a shared face might be removed from MFP during a prev loop
951 isAllOut = mySharedFaces.Contains( exF.Current() );
952 }
953 }
954 else
955 {
956 aSplitFaceL.Append( aSpFace );
957 if ( ! MFP.Remove( aSpFace ) && isAllOut)
958 // a shared face might be removed from MFP during a prev loop
959 isAllOut = mySharedFaces.Contains( aSpFace );
960 }
961 }
962 itm.Initialize( MFP ); // iterate remaining faces
963 if ( !isAllOut )
964 continue;
965
966 // classify anOrigShape against theShape
967 if (IsInside (anOrigShape, theShape))
968 {
969 if (isSolid && myClosedShapes.Contains( anOrigShape ))
970 // to make a special care at solid reconstruction
971 myWrappingSolid.Add ( theShape );
972
973 // keep faces of an internal shape anOrigShape
974 KeptFaces.Append( aSplitFaceL );
975 }
976 }
977 }
978
979 // ====================================================
980 // check if kept faces form a shell without free edges
981 // ====================================================
982
983 DMEF.Clear(); // edge - kept faces
984 MFP.Clear(); // reuse it for wrong faces
985 if (CheckClosed) {
986 for (itl.Initialize(KeptFaces); itl.More(); itl.Next() )
987 TopExp::MapShapesAndAncestors(itl.Value(), TopAbs_EDGE, TopAbs_FACE, DMEF);
988
989 Standard_Integer i, nb = DMEF.Extent();
990 Standard_Boolean isClosed = Standard_False;
991 while (!isClosed) {
992 isClosed = Standard_True;
993 for (i=1; isClosed && i<=nb; ++i) {
994 const TopoDS_Shape& E = DMEF.FindKey( i );
995 if (! BRep_Tool::Degenerated( TopoDS::Edge( E )) &&
996 ! MSE.Contains( E ))
997 isClosed = ( DMEF(i).Extent() != 1 );
998 }
999 if (!isClosed) {
1000 const TopoDS_Shape& F = DMEF.FindFromIndex( i-1 ).First(); // bad face
1001 MFP.Add( F );
1002 // remove bad face from DMEF
1003 for (expl.Init( F, TopAbs_EDGE); expl.More(); expl.Next()) {
1004 const TopoDS_Shape& E = expl.Current();
1005 TopTools_ListOfShape& FL = DMEF.ChangeFromKey( E );
1006 for (itl.Initialize( FL ); itl.More(); itl.Next() ) {
1007 if ( F.IsSame( itl.Value() )) {
1008 FL.Remove( itl );
1009 break;
1010 }
1011 }
1012 }
1013 }
1014 }
1015 }
1016
1017 // ==============
1018 // make a result
1019 // ==============
1020
1021 TopoDS_Compound C;
1022 // compound of removed internal faces
1023 TopoDS_Compound CNotCl;
1024
1025 myBuilder.MakeCompound(C);
1026 myBuilder.MakeCompound(CNotCl);
1027
1028 // add to compounds
1029 for (itl.Initialize(KeptFaces); itl.More(); itl.Next() )
1030 {
1031 TopoDS_Shape & aIntFace = itl.Value();
1032 if (! MFP.Contains( aIntFace ))
1033 myBuilder.Add( C, aIntFace);
1034 else
1035 myBuilder.Add( CNotCl, aIntFace);
1036 }
1037
1038 if (!skipAlreadyAdded && CheckClosed)
1039 {
1040 myInternalFaces.Bind( theShape, C );
1041 myIntNotClFaces.Bind( theShape, CNotCl );
1042 }
1043
1044 return C;
1045 }
1046
1047 //=======================================================================
1048 //function : MakeShell
1049 //purpose : split S into compound of shells
1050 //=======================================================================
1051
MakeShells(const TopoDS_Shape & S,TopTools_ListOfShape & NS)1052 void Partition_Spliter::MakeShells(const TopoDS_Shape& S,
1053 TopTools_ListOfShape& NS)
1054 {
1055 Partition_Loop3d ShellMaker;
1056 // get compound of split faces of S
1057 const TopoDS_Shape& FacesComp = myImageShape.Image(S).First();
1058 ShellMaker.AddConstFaces( FacesComp );
1059 // add split faces inside S
1060 if (myClosedShapes.Contains( S )) {
1061 TopoDS_Shape InternalFacesComp = FindFacesInside(S, Standard_True);
1062 ShellMaker.AddSectionFaces( InternalFacesComp );
1063 }
1064
1065 NS = ShellMaker.MakeShells( myAddedFacesMap );
1066
1067 // Add faces added to new shell to myAddedFacesMap:
1068 // avoid rebuilding twice commont part of 2 solids.
1069 TopTools_ListIteratorOfListOfShape itS(NS);
1070 while ( itS.More()) {
1071 TopExp_Explorer expF (itS.Value(), TopAbs_FACE);
1072 for (; expF.More(); expF.Next())
1073 myAddedFacesMap.Add (expF.Current());
1074
1075 itS.Next();
1076 }
1077 }
1078
1079 //=======================================================================
1080 //function : findEqual
1081 //purpose : compare edges of EL1 against edges of EL2,
1082 // Result is in EMM binding EL1 edges to list of equal edges.
1083 // Edges are considered equall only if they have same vertices.
1084 // <addSame>==True makes consider same edges as equal
1085 // Put in <AllEqMap> all equal edges
1086 //=======================================================================
1087
findEqual(const TopTools_ListOfShape & EL1,const TopTools_ListOfShape & EL2,const Standard_Boolean addSame,TopTools_DataMapOfShapeListOfShape & EEM,TopTools_MapOfShape & AllEqMap)1088 static void findEqual (const TopTools_ListOfShape& EL1,
1089 const TopTools_ListOfShape& EL2,
1090 const Standard_Boolean addSame,
1091 TopTools_DataMapOfShapeListOfShape& EEM,
1092 TopTools_MapOfShape& AllEqMap)
1093 {
1094 // map vertices to edges for EL2
1095 TopTools_DataMapOfShapeListOfShape VEM;
1096 TopTools_ListIteratorOfListOfShape itE1, itE2(EL2);
1097 TopoDS_Iterator itV;
1098 TopTools_ListOfShape emptyL;
1099 for (; itE2.More(); itE2.Next()) {
1100 for (itV.Initialize( itE2.Value() ); itV.More(); itV.Next()) {
1101 const TopoDS_Shape& V = itV.Value();
1102 if (! VEM.IsBound( V ) )
1103 VEM.Bind( V, emptyL);
1104 VEM( V ).Append( itE2.Value());
1105 }
1106 }
1107
1108 gp_Vec D1, D2;
1109 gp_Pnt P;
1110 Standard_Real f,l,u,tol;
1111 Handle(Geom_Curve) C1, C2;
1112 Extrema_ExtPC Extrema;
1113 TopoDS_Vertex V1, V2, V3, V4;
1114
1115 AllEqMap.Clear();
1116
1117 for (itE1.Initialize(EL1); itE1.More(); itE1.Next()) {
1118 const TopoDS_Edge& E1 = TopoDS::Edge( itE1.Value());
1119 if (BRep_Tool::Degenerated( E1 ) || AllEqMap.Contains (E1))
1120 continue;
1121 TopExp::Vertices( E1, V1, V2 );
1122
1123 if (VEM.IsBound(V1))
1124 itE2.Initialize( VEM(V1) );
1125 for (; itE2.More(); itE2.Next()) {
1126 const TopoDS_Edge& E2 = TopoDS::Edge( itE2.Value());
1127 if (BRep_Tool::Degenerated( E2 ) || AllEqMap.Contains (E2))
1128 continue;
1129
1130 if (E1.IsSame(E2)) {
1131 if (!addSame)
1132 continue;
1133 }
1134 else {
1135 TopExp::Vertices( E2, V3, V4);
1136 if (!V2.IsSame(V4) && !V2.IsSame(V3))
1137 continue;
1138 // E1 and E2 have same vertices
1139 // check D1 at end points.
1140 C2 = BRep_Tool::Curve( E2, f,l);
1141 C1 = BRep_Tool::Curve( E1, f,l);
1142 u = BRep_Tool::Parameter(V1,E1);
1143 C1->D1(u, P, D1);
1144 u = BRep_Tool::Parameter(V1.IsSame(V3) ? V3 : V4, E2);
1145 C2->D1(u, P, D2);
1146 D1.Normalize(); D2.Normalize();
1147 if (Abs(D1*D2) + Precision::Angular() < 1.0)
1148 continue;
1149 if (! V1.IsSame(V2)) {
1150 u = BRep_Tool::Parameter(V2,E1);
1151 C1->D1(u, P, D1);
1152 u = BRep_Tool::Parameter(V2.IsSame(V3) ? V3 : V4, E2);
1153 C2->D1(u, P, D2);
1154 D1.Normalize(); D2.Normalize();
1155 if (Abs(D1*D2) + Precision::Angular() < 1.0)
1156 continue;
1157 }
1158 // check distance at a couple of internal points
1159 tol = Max(BRep_Tool::Tolerance(E1),
1160 BRep_Tool::Tolerance(E2));
1161 GeomAdaptor_Curve AC1(C1);
1162 Extrema.Initialize(AC1,f,l);
1163 Standard_Boolean ok = Standard_True, hasMin = Standard_False;
1164 BRep_Tool::Range( E2, f, l);
1165 Standard_Integer i=1, nbi=3;
1166 for (; i<nbi && ok; ++i) {
1167 Extrema.Perform( C2->Value( f+(l-f)*i/nbi ));
1168 Standard_Integer j=1, nbj=Extrema.NbExt();
1169 for (; j<=nbj && ok; ++j) {
1170 if (Extrema.IsMin(j)) {
1171 hasMin = Standard_True;
1172 ok = Extrema.Value(j) <= tol; // V6.3
1173 // ok = Extrema.SquareDistance(j) <= tol; // V6.5
1174 }
1175 }
1176 }
1177 if ( !hasMin || !ok)
1178 continue;
1179 }
1180 // bind E2 to E1 in EEM
1181 if (!EEM.IsBound(E1)) {
1182 EEM.Bind (E1, emptyL);
1183 AllEqMap.Add (E1);
1184 }
1185 EEM(E1).Append(E2);
1186 AllEqMap.Add (E2);
1187 }
1188 }
1189 }
1190
1191 //=======================================================================
1192 //function : MakeFaces
1193 //purpose : split faces of S, return compound of new faces
1194 //=======================================================================
1195
MakeFaces(const TopoDS_Shape & S)1196 TopoDS_Shape Partition_Spliter::MakeFaces (const TopoDS_Shape& S)
1197 {
1198 TopoDS_Compound C;
1199 myBuilder.MakeCompound(C);
1200
1201 TopTools_ListIteratorOfListOfShape itl, itNE;
1202
1203 TopExp_Explorer exp(S,TopAbs_FACE);
1204 for (; exp.More(); exp.Next()) {
1205
1206 const TopoDS_Face& F = TopoDS::Face(exp.Current());
1207
1208 TopTools_ListOfShape LNF;
1209
1210 if (myImagesFaces.HasImage( F )) {
1211 myImagesFaces.LastImage( F, LNF );
1212 TopAbs_Orientation oriF = F.Orientation();
1213 for ( itl.Initialize( LNF ); itl.More(); itl.Next())
1214 itl.Value().Orientation( oriF );
1215 }
1216 else {
1217
1218 Partition_Loop2d loops;
1219 loops.Init(F);
1220
1221 TopTools_IndexedMapOfShape EM;
1222 TopExp::MapShapes( F, TopAbs_EDGE, EM);
1223
1224 TopTools_MapOfShape AddedEqualM, EqualSeamM;
1225 Standard_Boolean needRebuild = Standard_False;
1226
1227 // add splits to loops
1228
1229 // LE: old edges + new not splitted edges
1230 const TopTools_ListOfShape& LE = myAsDes->Descendant(F);
1231 for (itl.Initialize(LE); itl.More(); itl.Next()) {
1232 const TopoDS_Edge& E = TopoDS::Edge( itl.Value() );
1233
1234 Standard_Boolean isSectionE = myInter3d.IsSectionEdge(E);
1235 Standard_Boolean isNewE = !EM.Contains( E );
1236
1237 // LSE: list of split edges
1238 TopTools_ListOfShape LSE;
1239 myImagesEdges.LastImage(E,LSE); // splits of E or E itself
1240
1241 for (itNE.Initialize(LSE); itNE.More(); itNE.Next()) {
1242
1243 TopoDS_Edge NE = TopoDS::Edge( itNE.Value() );
1244 Standard_Boolean isSameE = NE.IsSame ( E );
1245
1246 if ( isNewE || isSectionE || !isSameE) {
1247 if (AddedEqualM.Contains( NE )) {
1248 // a seam must be twice in a loop
1249 if (!BRep_Tool::IsClosed( E, F ) || !EqualSeamM.Add( NE ))
1250 continue;
1251 }
1252
1253 if (isNewE) {
1254 if (isSectionE) {
1255 if ( ! myInter3d.IsSplitOn( NE, E, F) )
1256 continue;
1257 }
1258 else {
1259 TopoDS_Vertex V1,V2;
1260 TopExp::Vertices(NE,V1,V2);
1261 const TopTools_ListOfShape& EL1 = myAsDes->Ascendant(V1);
1262 const TopTools_ListOfShape& EL2 = myAsDes->Ascendant(V2);
1263 if ( EL1.Extent() < 2 && EL2.Extent() < 2 )
1264 continue;
1265 }
1266 }
1267 else {
1268 NE.Orientation( E.Orientation());
1269 if (!isSameE) {
1270 // orient NE because it may be a split of other edge
1271 Standard_Real f,l,u;
1272 Handle(Geom_Curve) C3d = BRep_Tool::Curve( E,f,l );
1273 Handle(Geom_Curve) NC3d = BRep_Tool::Curve( NE,f,l);
1274 if ( C3d != NC3d) {
1275 gp_Vec D1, ND1; gp_Pnt P;
1276 TopoDS_Vertex V = TopExp::FirstVertex(NE);
1277 u = BRep_Tool::Parameter(V,NE);
1278 NC3d->D1 (u, P, ND1);
1279 u = BRep_Tool::Parameter(V,E);
1280 C3d ->D1 (u, P, D1);
1281 if (ND1.Dot(D1) < 0)
1282 NE.Reverse();
1283 }
1284 }
1285 }
1286 if (myEqualEdges.Contains( NE ))
1287 AddedEqualM.Add( NE );
1288
1289 needRebuild = Standard_True;
1290 }
1291
1292 if (isNewE || isSectionE)
1293 myNewSection.Add( NE );
1294
1295 if (isNewE)
1296 loops.AddSectionEdge(NE);
1297 else
1298 loops.AddConstEdge(NE);
1299 }
1300 }
1301
1302 //-------------------
1303 // Build the faces.
1304 //-------------------
1305
1306 if (needRebuild) {
1307
1308 loops.Perform();
1309 loops.WiresToFaces(myImagesEdges);
1310
1311 LNF = loops.NewFaces();
1312
1313 myImagesFaces.Bind(F,LNF);
1314
1315 // replace the result faces that have already been built
1316 // during same domain faces reconstruction done earlier
1317 if (myInter3d.HasSameDomainF( F ))
1318 {
1319 // build map edge to same domain faces: EFM
1320 TopTools_IndexedDataMapOfShapeListOfShape EFM;
1321 TopTools_MapOfShape SDFM; // avoid doubling
1322 itl.Initialize( myInter3d.SameDomain( F ));
1323 for (; itl.More(); itl.Next()) {
1324 if ( !myImagesFaces.HasImage( itl.Value() ))
1325 continue;
1326 // loop on splits of a SD face
1327 TopTools_ListIteratorOfListOfShape itNF;
1328 itNF.Initialize (myImagesFaces.Image( itl.Value() ));
1329 for ( ; itNF.More(); itNF.Next()) {
1330 TopoDS_Shape SDF = itNF.Value();
1331 if (myImagesFaces.HasImage( SDF )) // already replaced
1332 SDF = myImagesFaces.Image( SDF ).First();
1333 if (SDFM.Add (SDF))
1334 TopExp::MapShapesAndAncestors(SDF, TopAbs_EDGE, TopAbs_FACE, EFM);
1335 }
1336 }
1337 // do replace faces in the LNF
1338 TopTools_ListOfShape LOF;
1339 if ( !EFM.IsEmpty() )
1340 itl.Initialize( LNF );
1341 while (itl.More()) {
1342 const TopoDS_Shape& NF = itl.Value();
1343 TopExp_Explorer expE ( NF, TopAbs_EDGE );
1344 const TopoDS_Edge& E = TopoDS::Edge (expE.Current());
1345 if (EFM.Contains( E )) {
1346 const TopTools_ListOfShape& SDFL = EFM.FindFromKey( E );
1347 TopoDS_Shape SDF = SDFL.First();
1348 Standard_Boolean GoodOri;
1349 Standard_Real dot;
1350 Partition_Loop3d::IsInside (E, TopoDS::Face(NF), TopoDS::Face(SDF),
1351 1, dot, GoodOri);
1352 if (dot < 0)
1353 {
1354 // NF and SDF are on different side of E
1355 if (SDFL.Extent() == 1) {
1356 itl.Next();
1357 continue;
1358 }
1359 else
1360 SDF = SDFL.Last(); // next face must be on the same side
1361 }
1362 gp_Vec V1 = Partition_Loop3d::Normal( E, TopoDS::Face( NF ));
1363 gp_Vec V2 = Partition_Loop3d::Normal( E, TopoDS::Face( SDF ));
1364 if (V1*V2 < 0)
1365 SDF.Reverse();
1366
1367 if (!myImagesFaces.HasImage( NF ))
1368 myImagesFaces.Bind( NF, SDF );
1369
1370 // mySharedFaces is used in FindFacesInside()
1371 mySharedFaces.Add( SDF );
1372
1373 LOF.Prepend ( SDF );
1374 LNF.Remove (itl);
1375 }
1376 else
1377 itl.Next();
1378 }
1379
1380 LNF.Append (LOF);
1381 }
1382 } // if (needRebuild)
1383
1384 else {
1385 LNF.Append( F );
1386 myImagesFaces.Bind(F,LNF);
1387 }
1388 } // if (myImagesFaces.HasImage( F ))
1389
1390 // fill the resulting compound
1391 for (itl.Initialize(LNF); itl.More(); itl.Next())
1392 myBuilder.Add ( C, itl.Value());
1393
1394 } // loop on faces of S
1395
1396 return C;
1397 }
1398
1399
1400 //=======================================================================
1401 //function : Tri
1402 //purpose :
1403 //=======================================================================
1404
Tri(const TopoDS_Edge & E,TopTools_SequenceOfShape & Seq,const Partition_Inter3d & theInter3d)1405 static void Tri(const TopoDS_Edge& E,
1406 TopTools_SequenceOfShape& Seq,
1407 const Partition_Inter3d & theInter3d)
1408 {
1409 Standard_Boolean Invert = Standard_True;
1410 Standard_Real U1,U2;
1411 TopoDS_Vertex V1,V2;
1412
1413 while (Invert) {
1414 Invert = Standard_False;
1415 for ( Standard_Integer i = 1; i < Seq.Length(); i++) {
1416
1417 V1 = TopoDS::Vertex(Seq.Value(i));
1418 V2 = TopoDS::Vertex(Seq.Value(i+1));
1419
1420 V1.Orientation(TopAbs_INTERNAL);
1421 V2.Orientation(TopAbs_INTERNAL);
1422
1423 U1 = BRep_Tool::Parameter(V1,E);
1424 U2 = BRep_Tool::Parameter(V2,E);
1425
1426 if (IsEqual(U1,U2)) {
1427 if (theInter3d.ReplaceSameDomainV( V1, E ).IsSame( V1 ))
1428 Seq.Remove(i+1); // remove V2
1429 else
1430 Seq.Remove(i);
1431 i--;
1432 continue;
1433 }
1434 if (U2 < U1) {
1435 Seq.Exchange(i,i+1);
1436 Invert = Standard_True;
1437 }
1438 }
1439 }
1440 }
1441
1442 //=======================================================================
1443 //function : MakeEdges
1444 //purpose : cut E by vertices VOnE, return list of new edges NE
1445 //=======================================================================
1446
MakeEdges(const TopoDS_Edge & E,const TopTools_ListOfShape & VOnE,TopTools_ListOfShape & NE) const1447 void Partition_Spliter::MakeEdges (const TopoDS_Edge& E,
1448 const TopTools_ListOfShape& VOnE,
1449 TopTools_ListOfShape& NE ) const
1450 {
1451 TopoDS_Edge WE = E;
1452 WE.Orientation(TopAbs_FORWARD);
1453
1454 Standard_Real U1,U2, f, l;
1455 TopoDS_Vertex V1,V2,VF,VL;
1456
1457 BRep_Tool::Range(WE,f,l);
1458 TopExp::Vertices(WE,VF,VL);
1459
1460 if (VOnE.Extent() < 3) { // do not rebuild not cut edge
1461 if (( VF.IsSame( VOnE.First() ) && VL.IsSame( VOnE.Last() )) ||
1462 VL.IsSame( VOnE.First() ) && VF.IsSame( VOnE.Last() ) ) {
1463 NE.Append( E );
1464 return;
1465 }
1466 }
1467
1468 TopTools_SequenceOfShape SV;
1469 TopTools_ListIteratorOfListOfShape itv(VOnE);
1470 TopTools_MapOfOrientedShape VM( VOnE.Extent() );
1471 for (; itv.More(); itv.Next())
1472 if ( VM.Add( itv.Value() ))
1473 SV.Append(itv.Value());
1474
1475 Tri( WE, SV, myInter3d );
1476
1477 if (SV.Length() < 3) { // do not rebuild not cut edge
1478 if (( VF.IsSame( SV.First() ) && VL.IsSame( SV.Last() )) ||
1479 VL.IsSame( SV.First() ) && VF.IsSame( SV.Last() ) ) {
1480 NE.Append( E );
1481 return;
1482 }
1483 }
1484
1485 Standard_Integer iVer, NbVer = SV.Length();
1486
1487
1488 //----------------------------------------------------------------
1489 // Construction of the new edges .
1490 //----------------------------------------------------------------
1491
1492 if (VF.IsSame(VL)) { // closed edge
1493 if (NbVer==1)
1494 SV.Append( SV.First() );
1495 else if (!SV.First().IsSame(SV.Last())) {
1496 Standard_Boolean isFirst=0;
1497 Standard_Real minDU = 1.e10;
1498 TopoDS_Vertex endV = Partition_Inter2d::FindEndVertex(VOnE, f,l, E, isFirst,minDU);
1499 if (endV.IsSame(SV.First()))
1500 SV.Append(endV);
1501 else if (endV.IsSame(SV.Last()))
1502 SV.Prepend(endV);
1503 else
1504 MESSAGE ("END VERTEX IS IN SEQUNCE MIDDLE");
1505 }
1506 NbVer = SV.Length();
1507 }
1508
1509 for (iVer=1; iVer < NbVer; iVer++) {
1510 V1 = TopoDS::Vertex(SV(iVer));
1511 V2 = TopoDS::Vertex(SV(iVer+1));
1512
1513 TopoDS_Shape NewEdge = WE.EmptyCopied();
1514 V1.Orientation(TopAbs_FORWARD);
1515 myBuilder.Add (NewEdge,V1);
1516 V2.Orientation(TopAbs_REVERSED);
1517 myBuilder.Add (NewEdge,V2);
1518
1519 if (iVer==1)
1520 U1 = f;
1521 else {
1522 V1.Orientation(TopAbs_INTERNAL);
1523 U1=BRep_Tool::Parameter(V1,WE);
1524 }
1525 if (iVer+1 == NbVer)
1526 U2 = l;
1527 else {
1528 V2.Orientation(TopAbs_INTERNAL);
1529 U2=BRep_Tool::Parameter(V2,WE);
1530 }
1531 if (Abs(U1-U2) <= Precision::PConfusion()) {
1532 MESSAGE( "MakeEdges(), EQUAL PARAMETERS OF DIFFERENT VERTICES");
1533 continue;
1534 }
1535 TopoDS_Edge EE=TopoDS::Edge(NewEdge);
1536 myBuilder.Range (EE,U1,U2);
1537
1538 TopoDS_Edge NEdge = TopoDS::Edge(NewEdge);
1539 myBuilder.SameParameter(NEdge,Standard_False);
1540
1541 Standard_Real tol = 1.0e-2;
1542 Standard_Boolean flag = BRep_Tool::SameParameter(NEdge);
1543 if (!flag) {
1544 BRepLib::SameParameter(NEdge,tol);
1545 }
1546 NE.Append(NEdge.Oriented(E.Orientation()));
1547 }
1548 }
1549
1550 //=======================================================================
1551 //function : MergeEqualEdges
1552 //purpose : find equal edges, choose ones to keep and make
1553 // them have pcurves on all faces they are shared by
1554 //=======================================================================
1555
MergeEqualEdges(const TopTools_ListOfShape & LSE)1556 void Partition_Spliter::MergeEqualEdges (const TopTools_ListOfShape& LSE)
1557 {
1558 // find equal edges
1559 // map: edge - equal edges
1560 TopTools_DataMapOfShapeListOfShape EEM( LSE.Extent() );
1561 findEqual (LSE, LSE, 0, EEM, myEqualEdges);
1562
1563 TopTools_ListOfShape EEL; // list of equal edges
1564 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape itM (EEM);
1565 for ( ; itM.More(); itM.Next()) {
1566 EEL = itM.Value();
1567 EEL.Append( itM.Key() );
1568
1569 // choose an edge to keep, section edges have priority
1570 TopoDS_Edge EKeep;
1571 TopTools_ListIteratorOfListOfShape itEE (EEL);
1572 for (; itEE.More(); itEE.Next()) {
1573 EKeep = TopoDS::Edge( itEE.Value() );
1574 const TopoDS_Edge& EKeepOrig = TopoDS::Edge( myImagesEdges.Root( EKeep ));
1575 if (myInter3d.IsSectionEdge( EKeepOrig ))
1576 break;
1577 }
1578
1579 // update edge images and build pcurves
1580 Standard_Real f,l, tol;
1581 for (itEE.Initialize (EEL); itEE.More(); itEE.Next()) {
1582 const TopoDS_Edge& E = TopoDS::Edge( itEE.Value() );
1583 if ( E.IsSame( EKeep ))
1584 continue;
1585
1586 // 1. build pcurves of the kept edge on faces where replaced edges exist
1587 const TopoDS_Edge& EReplOrig = TopoDS::Edge( myImagesEdges.Root( E ));
1588 TopTools_ListOfShape FL;
1589 FL = myAsDes->Ascendant( EReplOrig );
1590 Standard_Integer iFace, iFirstSectionFace = FL.Extent() + 1;
1591 // add faces where the replaced edge is a section edge
1592 if (myInter3d.IsSectionEdge( EReplOrig )) {
1593 TopTools_ListIteratorOfListOfShape seIt;
1594 seIt.Initialize( myInter3d.SectionEdgeFaces ( EReplOrig ));
1595 for ( ; seIt.More(); seIt.Next())
1596 FL.Append( seIt.Value() );
1597 }
1598 // loop on faces
1599 TopTools_ListIteratorOfListOfShape itF (FL);
1600 for ( iFace = 1 ; itF.More(); itF.Next(), ++iFace ) {
1601 const TopoDS_Face& F = TopoDS::Face( itF.Value());
1602
1603 Handle(Geom2d_Curve) pc = BRep_Tool::CurveOnSurface( EKeep, F, f,l);
1604 if (pc.IsNull()) {
1605 Handle(Geom_Curve) C3d = BRep_Tool::Curve( EKeep, f, l);
1606 C3d = new Geom_TrimmedCurve( C3d, f,l);
1607 pc = TopOpeBRepTool_CurveTool::MakePCurveOnFace (F,C3d,tol);
1608 if (pc.IsNull()) {
1609 MESSAGE (" CANT BUILD PCURVE ");
1610 }
1611 myBuilder.UpdateEdge( EKeep, pc, F, tol);
1612 }
1613
1614 if (iFace >= iFirstSectionFace ||
1615 !BRep_Tool::IsClosed( EReplOrig, F ))
1616 continue;
1617
1618 // build the second pcurve for a seam
1619 TopoDS_Vertex V = TopExp::FirstVertex( EKeep );
1620 Standard_Real Ukeep = BRep_Tool::Parameter( V, EKeep );
1621 Standard_Real Urepl = BRep_Tool::Parameter( V, E );
1622
1623 TopoDS_Edge EReplRev = E;
1624 EReplRev.Reverse();
1625 Handle(Geom2d_Curve) pcRepl1 = BRep_Tool::CurveOnSurface( E, F, f,l);
1626 Handle(Geom2d_Curve) pcRepl2 = BRep_Tool::CurveOnSurface( EReplRev, F, f,l);
1627
1628 gp_Pnt2d p1r, p2r, pk;
1629 p1r = pcRepl1->Value( Urepl );
1630 p2r = pcRepl2->Value( Urepl );
1631 pk = pc->Value( Ukeep );
1632
1633 // suppose that pk is equal to either p1r or p2r
1634 Standard_Boolean isUPeriod =
1635 ( Abs( p1r.X() - p2r.X() ) > Abs( p1r.Y() - p2r.Y() ));
1636 Standard_Boolean is1Equal;
1637 if (isUPeriod)
1638 is1Equal = ( Abs( p1r.X() - pk.X() ) < Abs( p2r.X() - pk.X() ));
1639 else
1640 is1Equal = ( Abs( p1r.Y() - pk.Y() ) < Abs( p2r.Y() - pk.Y() ));
1641
1642 Handle(Geom2d_Curve) pc2 = Handle(Geom2d_Curve)::DownCast
1643 ( pc->Translated( pk, is1Equal ? p2r : p1r ) );
1644
1645 if (E.Orientation() == TopAbs_REVERSED)
1646 is1Equal = !is1Equal;
1647
1648 if (is1Equal)
1649 myBuilder.UpdateEdge( EKeep, pc, pc2, F, tol);
1650 else
1651 myBuilder.UpdateEdge( EKeep, pc2, pc, F, tol);
1652
1653 } // loop on a Faces where a replaced edge exists
1654
1655
1656 // 2. update edge images according to replacement
1657 if (myImagesEdges.HasImage( E ))
1658 myImagesEdges.Remove( E );
1659 myImagesEdges.Bind( E, EKeep );
1660
1661 } // loop on a list of equal edges EEL
1662 } // loop on a map of equal edges EEM
1663 }
1664
1665 //=======================================================================
1666 //function : KeepShapesInside
1667 //purpose : remove shapes that are outside of S from resul
1668 //=======================================================================
1669
KeepShapesInside(const TopoDS_Shape & S)1670 void Partition_Spliter::KeepShapesInside (const TopoDS_Shape& S)
1671 {
1672 TopoDS_Iterator it;
1673 if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid
1674 for (it.Initialize( S ); it.More(); it.Next())
1675 KeepShapesInside( it.Value());
1676 return;
1677 }
1678
1679 Standard_Boolean isTool = Standard_False;
1680 if (!myImageShape.HasImage( S )) {
1681 isTool = CheckTool( S );
1682 if (!isTool) return;
1683 }
1684
1685 // build map of internal faces
1686 TopTools_IndexedMapOfShape MIF;
1687 TopoDS_Shape IntFacesComp = FindFacesInside( S, Standard_False, Standard_True);
1688 TopExp::MapShapes( IntFacesComp, TopAbs_FACE, MIF );
1689
1690 TopoDS_Compound C;
1691 myBuilder.MakeCompound(C);
1692
1693 TopAbs_ShapeEnum anInternalShapeType = TopAbs_SHAPE;
1694 if (!MIF.IsEmpty())
1695 {
1696 // leave in the result only those shapes having a face in MIF
1697 for (it.Initialize( myShape ); it.More(); it.Next()) {
1698 const TopoDS_Shape & aResShape = it.Value();
1699 TopExp_Explorer expResF( aResShape, TopAbs_FACE );
1700 for (; expResF.More(); expResF.Next()) {
1701 if ( MIF.Contains( expResF.Current())) {
1702 myBuilder.Add( C, aResShape );
1703 if (aResShape.ShapeType() < anInternalShapeType)
1704 anInternalShapeType = aResShape.ShapeType();
1705 break;
1706 }
1707 }
1708 }
1709 }
1710
1711 // may be S was not split by internal faces then it is missing
1712 // in myShape, add it
1713 if (!isTool &&
1714 (anInternalShapeType > TopAbs_SOLID || S.ShapeType() > TopAbs_SOLID))
1715 {
1716 TopTools_IndexedMapOfShape MSF; // map of split faces of S
1717 TopExp::MapShapes( myImageShape.Image(S).First(), TopAbs_FACE, MSF);
1718
1719 // find a shape having all faces in MSF
1720 for (it.Initialize( myShape ); it.More(); it.Next()) {
1721 TopExp_Explorer expResF( it.Value(), TopAbs_FACE );
1722 for (; expResF.More(); expResF.Next()) {
1723 if (! MSF.Contains( expResF.Current()))
1724 break;
1725 }
1726 if (! expResF.More()) {
1727 myBuilder.Add( C, it.Value() );
1728 break;
1729 }
1730 }
1731 }
1732
1733 myShape = C;
1734 }
1735
1736 //=======================================================================
1737 //function : RemoveShapesInside
1738 //purpose : remove shapes that are inside S from resul
1739 //=======================================================================
1740
RemoveShapesInside(const TopoDS_Shape & S)1741 void Partition_Spliter::RemoveShapesInside (const TopoDS_Shape& S)
1742 {
1743 TopoDS_Iterator it;
1744 if (S.ShapeType() < TopAbs_SOLID) { // compound or compsolid
1745 for (it.Initialize( S ); it.More(); it.Next())
1746 RemoveShapesInside( it.Value());
1747 return;
1748 }
1749 Standard_Boolean isTool = Standard_False;
1750 if (!myImageShape.HasImage( S )) {
1751 isTool = CheckTool( S );
1752 if (!isTool) return;
1753 }
1754
1755 TopoDS_Shape IntFacesComp = FindFacesInside( S, Standard_False, Standard_True);
1756 TopTools_IndexedMapOfShape MIF; // map of internal faces
1757 TopExp::MapShapes( IntFacesComp, TopAbs_FACE, MIF);
1758
1759 if (MIF.IsEmpty()) return;
1760
1761 // add to MIF split faces of S
1762 if (myImageShape.HasImage(S))
1763 TopExp::MapShapes( myImageShape.Image(S).First(), TopAbs_FACE, MIF);
1764
1765 // leave in the result only those shapes not having all face in MIF
1766
1767 TopoDS_Compound C;
1768 myBuilder.MakeCompound(C);
1769
1770 // RMF : faces of removed shapes that encounter once
1771 TopTools_MapOfShape RFM;
1772
1773 for (it.Initialize( myShape ); it.More(); it.Next()) {
1774
1775 TopExp_Explorer expResF( it.Value(), TopAbs_FACE );
1776 for (; expResF.More(); expResF.Next())
1777 if (!MIF.Contains( expResF.Current()))
1778 break;
1779
1780 if (expResF.More())
1781 // add shape to result
1782 myBuilder.Add( C, it.Value() );
1783 else
1784 // add faces of a removed shape to RFM
1785 for (expResF.ReInit(); expResF.More(); expResF.Next()) {
1786 const TopoDS_Shape& F = expResF.Current();
1787 if ( ! RFM.Remove ( F ))
1788 RFM.Add( F );
1789 }
1790 }
1791
1792 if (!isTool) {
1793
1794 // rebuild S, it must remain in the result
1795
1796 Standard_Boolean isClosed = Standard_False;
1797 switch (S.ShapeType()) {
1798 case TopAbs_SOLID :
1799 isClosed = Standard_True; break;
1800 case TopAbs_SHELL: {
1801 TopTools_IndexedDataMapOfShapeListOfShape MEF;
1802 TopExp::MapShapesAndAncestors(S, TopAbs_EDGE, TopAbs_FACE, MEF);
1803 Standard_Integer i;
1804 for (i=1; isClosed && i<=MEF.Extent(); ++i)
1805 isClosed = ( MEF(i).Extent() != 1 );
1806 break;
1807 }
1808 default:
1809 isClosed = Standard_False;
1810 }
1811 if (isClosed) {
1812
1813 // add to a new shape external faces of removed shapes, ie those in RFM
1814
1815 TopoDS_Shell Shell;
1816 myBuilder.MakeShell( Shell );
1817
1818 // exclude redundant internal face with edges encounterd only once
1819 TopTools_IndexedDataMapOfShapeListOfShape MEF;
1820 TopTools_MapIteratorOfMapOfShape itF (RFM);
1821 for ( ; itF.More(); itF.Next())
1822 TopExp::MapShapesAndAncestors(itF.Key(), TopAbs_EDGE, TopAbs_FACE, MEF);
1823
1824 // add only faces forming a closed shell
1825 for (itF.Reset() ; itF.More(); itF.Next())
1826 {
1827 TopExp_Explorer expE (itF.Key(), TopAbs_EDGE);
1828 for (; expE.More(); expE.Next())
1829 if (MEF.FindFromKey(expE.Current()).Extent() == 1)
1830 break;
1831 if (!expE.More())
1832 myBuilder.Add( Shell, itF.Key());
1833 }
1834
1835 if (S.ShapeType() == TopAbs_SOLID) {
1836 TopoDS_Solid Solid;
1837 myBuilder.MakeSolid( Solid );
1838 myBuilder.Add (Solid, Shell);
1839 myBuilder.Add (C, Solid);
1840 }
1841 else
1842 myBuilder.Add (C, Shell);
1843 }
1844 else {
1845 if (myImageShape.HasImage( S )) {
1846 for (it.Initialize( myImageShape.Image(S).First()); it.More(); it.Next())
1847 myBuilder.Add (C, it.Value());
1848 }
1849 }
1850 }
1851
1852 myShape = C;
1853 }
1854
1855 //=======================================================================
1856 //function : CheckTool
1857 //purpose : Return True if <S> is a tool shape. Prepare tool
1858 // faces of <S> for the search of internal faces.
1859 //=======================================================================
1860
CheckTool(const TopoDS_Shape & S)1861 Standard_Boolean Partition_Spliter::CheckTool(const TopoDS_Shape& S)
1862 {
1863 // suppose S has not an image
1864
1865 Standard_Boolean isTool = Standard_False;
1866 TopoDS_Compound C;
1867 myBuilder.MakeCompound( C );
1868
1869 TopExp_Explorer expF( S, TopAbs_FACE);
1870 for (; expF.More(); expF.Next()) {
1871
1872 const TopoDS_Face& F = TopoDS::Face( expF.Current() );
1873 if (myMapTools.Contains( F ))
1874 isTool = Standard_True;
1875 else
1876 continue;
1877
1878 if (myImagesFaces.HasImage( F )) {
1879 // F has been reconstructed
1880 TopAbs_Orientation Fori = F.Orientation();
1881 TopTools_ListOfShape LNF;
1882 myImagesFaces.LastImage( F, LNF);
1883 TopTools_ListIteratorOfListOfShape itF (LNF);
1884 for ( ; itF.More(); itF.Next())
1885 myBuilder.Add( C, itF.Value().Oriented(Fori) );
1886 continue;
1887 }
1888
1889 Standard_Boolean hasSectionE = myInter3d.HasSectionEdge( F );
1890 Standard_Boolean hasNewE = myAsDes->HasDescendant( F );
1891 if (!hasSectionE && !hasNewE)
1892 {
1893 // F intersects nothing
1894 myBuilder.Add( C, F );
1895 continue;
1896 }
1897
1898 // make an image for F
1899
1900 TopoDS_Face NF = F;
1901 NF.Orientation(TopAbs_FORWARD);
1902 NF = TopoDS::Face( NF.EmptyCopied() ); // make a copy
1903 TopoDS_Wire NW;
1904 myBuilder.MakeWire( NW );
1905
1906 // add edges, as less as possible
1907 TopTools_ListOfShape NEL;
1908 TopTools_ListIteratorOfListOfShape itNE;
1909 if (hasSectionE) {
1910 // add section edges
1911 TopExp_Explorer expE;
1912 for ( ; expE.More(); expE.Next()) {
1913 if (! myImagesEdges.HasImage( expE.Current() ))
1914 continue;
1915 myImagesEdges.LastImage( expE.Current(), NEL );
1916 for ( itNE.Initialize( NEL ); itNE.More(); itNE.Next())
1917 myBuilder.Add ( NW, itNE.Value());
1918 }
1919 }
1920 if (hasNewE) {
1921 // add new adges
1922 NEL = myAsDes->Descendant( F );
1923 for ( itNE.Initialize( NEL ); itNE.More(); itNE.Next()) {
1924 TopTools_ListOfShape SEL; // splits
1925 myImagesEdges.LastImage( itNE.Value(), SEL );
1926 TopTools_ListIteratorOfListOfShape itSE (SEL);
1927 for ( ; itSE.More(); itSE.Next())
1928 myBuilder.Add ( NW, itSE.Value());
1929 }
1930 }
1931 myBuilder.Add( NF, NW );
1932 myBuilder.Add (C, NF);
1933
1934 NF.Orientation( F.Orientation() ); // NF is most probably invalid
1935 myImagesFaces.Bind (F, NF);
1936 }
1937 if (isTool)
1938 myImageShape.Bind (S, C);
1939
1940 return isTool;
1941 }
1942
1943 //=======================================================================
1944 //function : IsInside
1945 //purpose : Return True if the first vertex of S1 inside S2.
1946 // If S1.IsNull(), check infinite point against S2.
1947 //=======================================================================
1948
IsInside(const TopoDS_Shape & theS1,const TopoDS_Shape & theS2)1949 Standard_Boolean Partition_Spliter::IsInside (const TopoDS_Shape& theS1,
1950 const TopoDS_Shape& theS2)
1951 {
1952 BRepClass3d_SolidClassifier aClassifier( theS2 );
1953
1954 TopExp_Explorer expl( theS1, TopAbs_VERTEX );
1955 if (!expl.More())
1956 aClassifier.PerformInfinitePoint( ::RealSmall());
1957 else
1958 {
1959 const TopoDS_Vertex & aVertex = TopoDS::Vertex( expl.Current() );
1960 aClassifier.Perform (BRep_Tool::Pnt( aVertex ),
1961 BRep_Tool::Tolerance( aVertex ));
1962 }
1963
1964 return ( aClassifier.State() == TopAbs_IN );
1965 }
1966
1967 //=======================================================================
1968 //function : GetOriginalShape
1969 //purpose : Return the shape aShape originates from. aShape
1970 // should be a face or more complex result shape
1971 //=======================================================================
1972
GetOriginalShape(const TopoDS_Shape & theShape) const1973 TopoDS_Shape Partition_Spliter::GetOriginalShape(const TopoDS_Shape& theShape) const
1974 {
1975 TopoDS_Shape anOrigShape;
1976
1977 TopExp_Explorer expl( theShape, TopAbs_FACE);
1978 if (expl.More())
1979 {
1980
1981 TopoDS_Shape aFace = expl.Current();
1982 if (myImagesFaces.IsImage( aFace ))
1983 aFace = myImagesFaces.Root( aFace );
1984 anOrigShape = myFaceShapeMap.Find( aFace );
1985 }
1986 return anOrigShape;
1987 }
1988
1989 //=======================================================================
1990 //function : FindToolsToReconstruct
1991 //purpose : find and store as objects tools which interfere
1992 // with solids or are inside solids without
1993 // an interference
1994 //=======================================================================
1995
FindToolsToReconstruct()1996 void Partition_Spliter::FindToolsToReconstruct()
1997 {
1998 if (myMapTools.IsEmpty())
1999 return;
2000
2001 Standard_Integer nbFoundTools = 0;
2002
2003 // build edge - face map in order to detect interference with section edges
2004 TopTools_IndexedDataMapOfShapeListOfShape EFM;
2005 TopTools_MapIteratorOfMapOfShape aMapIt;
2006 for (aMapIt.Initialize(myMapTools); aMapIt.More(); aMapIt.Next())
2007 TopExp::MapShapesAndAncestors( aMapIt.Key(), TopAbs_EDGE, TopAbs_FACE, EFM);
2008 for (aMapIt.Initialize(myMapFaces); aMapIt.More(); aMapIt.Next())
2009 TopExp::MapShapesAndAncestors( aMapIt.Key(), TopAbs_EDGE, TopAbs_FACE, EFM);
2010
2011 TopTools_MapOfShape aCurrentSolids, aCheckedShapes;
2012
2013 // faces cut by new edges
2014 TopTools_MapOfShape & aSectionFaces = myInter3d.TouchedFaces();
2015
2016 // keep solids interfering with each other in aCurrentSolids map
2017 // and add tool faces intersecting solids as object shapes
2018
2019 TopTools_ListIteratorOfListOfShape itS, itF, itCF, itE;
2020 for (itS.Initialize( myListShapes ); itS.More(); itS.Next()) {
2021 TopExp_Explorer expSo (itS.Value(), TopAbs_SOLID);
2022 for (; expSo.More(); expSo.Next()) {
2023
2024 // check if a solid has been already processed
2025 const TopoDS_Shape & aSo = expSo.Current();
2026 if (!aCheckedShapes.Add( aSo ))
2027 continue;
2028 aCurrentSolids.Add( aSo );
2029
2030 // faces to check
2031 TopTools_ListOfShape aFacesToCheck;
2032 TopExp_Explorer exp( aSo, TopAbs_FACE );
2033 for ( ; exp.More(); exp.Next())
2034 aFacesToCheck.Append ( exp.Current());
2035
2036 // add other shapes interefering with a solid.
2037 // iterate faces to check while appending new ones
2038 for (itCF.Initialize (aFacesToCheck) ; itCF.More(); itCF.Next())
2039 {
2040 const TopoDS_Shape& aCheckFace = itCF.Value();
2041 // if (!aCheckedShapes.Add( aCheckFace ))
2042 // continue;
2043
2044 // find faces interfering with aCheckFace
2045 TopTools_ListOfShape anIntFaces;
2046
2047 // ** 1. faces intersecting aCheckFace with creation of new edges on it
2048 if ( myAsDes->HasDescendant( aCheckFace ))
2049 {
2050 // new edges on aCheckFace
2051 const TopTools_ListOfShape& NEL = myAsDes->Descendant( aCheckFace );
2052 for (itE.Initialize( NEL); itE.More(); itE.Next())
2053 {
2054 const TopoDS_Shape & aNewEdge = itE.Value();
2055 if (!aCheckedShapes.Add( aNewEdge ))
2056 continue;
2057
2058 // faces interfering by aNewEdge
2059 itF.Initialize (myAsDes->Ascendant( aNewEdge ));
2060 for (; itF.More(); itF.Next())
2061 if (aCheckFace != itF.Value())
2062 anIntFaces.Append( itF.Value() );
2063
2064 // ** 2. faces having section edge aNewEdge on aFacesToCheck
2065 if (EFM.Contains( aNewEdge))
2066 {
2067 itF.Initialize ( EFM.FindFromKey (itE.Value()));
2068 for (; itF.More(); itF.Next())
2069 if (aCheckFace != itF.Value())
2070 anIntFaces.Append( itF.Value() );
2071 }
2072 }
2073 }
2074
2075 // ** 3. faces cut by edges of aCheckFace
2076 TopExp_Explorer expE (aCheckFace, TopAbs_EDGE);
2077 for ( ; expE.More(); expE.Next())
2078 {
2079 const TopoDS_Shape & aCheckEdge = expE.Current();
2080 if (aCheckedShapes.Add( aCheckEdge ) &&
2081 myInter3d.IsSectionEdge( TopoDS::Edge( aCheckEdge )))
2082 {
2083 itF.Initialize( myInter3d.SectionEdgeFaces( TopoDS::Edge( aCheckEdge )));
2084 for (; itF.More(); itF.Next())
2085 if (aCheckFace != itF.Value())
2086 anIntFaces.Append( itF.Value() );
2087 }
2088 }
2089
2090 // process faces interfering with aCheckFace and shapes they
2091 // belong to
2092 for (itF.Initialize (anIntFaces); itF.More(); itF.Next())
2093 {
2094 const TopoDS_Shape & F = itF.Value();
2095 if (! aCheckedShapes.Add( F ))
2096 continue;
2097
2098 Standard_Boolean isTool = myMapTools.Contains( F );
2099 if (isTool &&
2100 myFaceShapeMap( aCheckFace ).ShapeType() == TopAbs_SOLID )
2101 {
2102 // a tool interfering with a solid
2103 if (aSectionFaces.Contains( F ))
2104 AddShape( F );
2105 ++ nbFoundTools;
2106 if (nbFoundTools == myMapTools.Extent())
2107 return;
2108 }
2109
2110 const TopoDS_Shape & S = myFaceShapeMap( F );
2111 if (aCheckedShapes.Add( S ))
2112 {
2113 // a new shape interefering with aCurrentSolids is found
2114 if (!isTool && S.ShapeType() == TopAbs_SOLID)
2115 aCurrentSolids.Add ( S );
2116 // add faces to aFacesToCheck list
2117 for ( exp.Init( S, TopAbs_FACE ); exp.More(); exp.Next())
2118 aFacesToCheck.Append ( exp.Current() );
2119 }
2120 }
2121 } // loop on aFacesToCheck
2122
2123 // Here aCurrentSolids contains all solids interfering with each other.
2124 // aCheckedShapes contains all faces belonging to shapes included
2125 // in or interfering with aCurrentSolids or previously checked solids.
2126 // Test if tool faces that do not interefere with other shapes are
2127 // wrapped by any of aCurrentSolids
2128
2129 TopTools_MapIteratorOfMapOfShape aSolidIt (aCurrentSolids);
2130 for ( ; aSolidIt.More(); aSolidIt.Next())
2131 {
2132 const TopoDS_Shape & aSolid = aSolidIt.Key();
2133 TopTools_MapOfShape aCheckedTools( myMapTools.Extent() );
2134
2135 TopTools_MapIteratorOfMapOfShape aToolIt (myMapTools);
2136 for ( ; aToolIt.More(); aToolIt.Next())
2137 {
2138 const TopoDS_Shape & aToolFace = aToolIt.Key();
2139 if (aCheckedShapes.Contains( aToolFace ) || // already found
2140 aCheckedTools.Contains( aToolFace )) // checked against aSolid
2141 continue;
2142
2143 const TopoDS_Shape & aToolShape = myFaceShapeMap( aToolFace );
2144 TopExp_Explorer aToolFaceIt( aToolShape, TopAbs_FACE );
2145
2146 Standard_Boolean isInside = IsInside( aToolShape, aSolid );
2147 for ( ; aToolFaceIt.More(); aToolFaceIt.Next() )
2148 {
2149 const TopoDS_Shape & aTool = aToolFaceIt.Current();
2150 aCheckedTools.Add( aTool );
2151 if (isInside)
2152 {
2153 if (aSectionFaces.Contains( aTool ))
2154 AddShape( aTool );
2155 ++ nbFoundTools;
2156 if (nbFoundTools == myMapTools.Extent())
2157 return;
2158 aCheckedShapes.Add( aTool );
2159 }
2160 }
2161 }
2162 }
2163
2164 } // loop on solid shapes
2165 }
2166 }
2167
2168 #endif
2169