0024025: The method Modified2() in BRepAlgoAPI_BooleanOperation should be removed.
[occt.git] / src / QANewModTopOpe / QANewModTopOpe_Glue_shell.cxx
CommitLineData
b311480e 1// Created on: 2001-01-16
2// Created by: Michael SAZONOV
3// Copyright (c) 2001-2012 OPEN CASCADE SAS
4//
5// The content of this file is subject to the Open CASCADE Technology Public
6// License Version 6.5 (the "License"). You may not use the content of this file
7// except in compliance with the License. Please obtain a copy of the License
8// at http://www.opencascade.org and read it completely before using this file.
9//
10// The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11// main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12//
13// The Original Code and all software distributed under the License is
14// distributed on an "AS IS" basis, without warranty of any kind, and the
15// Initial Developer hereby disclaims all such warranties, including without
16// limitation, any warranties of merchantability, fitness for a particular
17// purpose or non-infringement. Please see the License for the specific terms
18// and conditions governing the rights and limitations under the License.
7fd59977 19
20#include <QANewModTopOpe_Glue.ixx>
21#include <Precision.hxx>
22#include <Geom2d_Curve.hxx>
23#include <Geom_Surface.hxx>
24#include <GeomAPI_ProjectPointOnSurf.hxx>
25#include <TopoDS.hxx>
26#include <TopoDS_Iterator.hxx>
27#include <BRep_Tool.hxx>
28#include <BRepTools.hxx>
29#include <BRepClass_FaceClassifier.hxx>
30#include <BRepFeat_SplitShape.hxx>
31#include <BRepLib.hxx>
32#include <TopExp.hxx>
33#include <TopExp_Explorer.hxx>
34#include <TopTools_DataMapOfShapeInteger.hxx>
35#include <TopTools_ListIteratorOfListOfShape.hxx>
36#include <TopTools_MapIteratorOfMapOfShape.hxx>
37#include <TopTools_DataMapIteratorOfDataMapOfShapeShape.hxx>
38#include <BRepAlgo_EdgeConnector.hxx>
39#include <TopTools_MapOfShape.hxx>
40#include <BRep_Builder.hxx>
41#include <QANewModTopOpe_Tools.hxx>
42#include <TopTools_IndexedMapOfShape.hxx>
43
44//=======================================================================
45//function : SplitEdgeComplete
46//purpose : static
47//=======================================================================
48
49static void
50SplitEdgeComplete (const TopoDS_Edge& theEdge,
51 TopTools_ListOfShape& theListSplits)
52{
53 struct ParVer {
54 Standard_Real myParF, myParL;
55 TopoDS_Vertex myVerF, myVerL;
56 };
57 ParVer *aParVer = new ParVer[theListSplits.Extent()+1];
58 TopTools_DataMapOfShapeInteger aMapEdgeIPV;
59 TopTools_ListOfShape aListTodo;
60 aListTodo = theListSplits;
61
62 // prepare structures aMapEdgeIPV and aParVer
63
64 aListTodo.Prepend(theEdge);
65 TopTools_ListIteratorOfListOfShape aIter(aListTodo);
66 Standard_Integer iPV;
67 for (iPV=0; aIter.More(); aIter.Next(), iPV++) {
68 const TopoDS_Edge& aEdge = TopoDS::Edge(aIter.Value());
69 TopoDS_Vertex aVer1, aVer2;
70 Standard_Real aPar1, aPar2;
71
72 // compute parameters of first and last vertices of aEdge on theEdge
73
74 TopExp::Vertices(aEdge, aVer1, aVer2);
75
76 if(aVer1.IsNull() || aVer2.IsNull()) {
77 aListTodo.Remove(aIter);
78 TopTools_ListIteratorOfListOfShape aIter1(theListSplits);
79 for (; aIter1.More(); aIter1.Next()) {
80 if(aEdge.IsSame(aIter1.Value())) {
81 theListSplits.Remove(aIter1);
82 break;
83 }
84 }
85 if(aIter.More()) continue;
86 break;
87 }
88
89 if (iPV == 0) {
90 // the vertices of theEdge
91 aPar1 = BRep_Tool::Parameter(aVer1, theEdge);
92 aPar2 = BRep_Tool::Parameter(aVer2, theEdge);
93 }
94 else {
95 Standard_Real aDist;
96 // the vertices of an edge from the source list
97 if (!QANewModTopOpe_Glue::ProjPointOnEdge (BRep_Tool::Pnt(aVer1),
98 theEdge, aPar1, aDist)) {
99 // the vertex is out of theEdge => take one from theEdge
100 Standard_Real aPar;
101 if (QANewModTopOpe_Glue::ProjPointOnEdge (BRep_Tool::Pnt(aParVer[0].myVerF),
102 aEdge, aPar, aDist)) {
103 aVer1 = aParVer[0].myVerF;
104 aPar1 = aParVer[0].myParF;
105 }
106 else {
107 aVer1 = aParVer[0].myVerL;
108 aPar1 = aParVer[0].myParL;
109 }
110 }
111 if (!QANewModTopOpe_Glue::ProjPointOnEdge (BRep_Tool::Pnt(aVer2),
112 theEdge, aPar2, aDist)) {
113 // the vertex is out of theEdge => take one from theEdge
114 Standard_Real aPar;
115 if (QANewModTopOpe_Glue::ProjPointOnEdge (BRep_Tool::Pnt(aParVer[0].myVerL),
116 aEdge, aPar, aDist)) {
117 aVer2 = aParVer[0].myVerL;
118 aPar2 = aParVer[0].myParL;
119 }
120 else {
121 aVer2 = aParVer[0].myVerF;
122 aPar2 = aParVer[0].myParF;
123 }
124 }
125 }
126 if (aPar1 < aPar2) {
127 aParVer[iPV].myParF = aPar1; aParVer[iPV].myVerF = aVer1;
128 aParVer[iPV].myParL = aPar2; aParVer[iPV].myVerL = aVer2;
129 }
130 else {
131 aParVer[iPV].myParF = aPar2; aParVer[iPV].myVerF = aVer2;
132 aParVer[iPV].myParL = aPar1; aParVer[iPV].myVerL = aVer1;
133 if(iPV != 0) {
134 TopTools_ListIteratorOfListOfShape aIterSplits(theListSplits);
135 for(; aIterSplits.More(); aIterSplits.Next()) {
136 if(aEdge.IsSame(aIterSplits.Value())) {
137 aIterSplits.Value().Reverse();
138 }
139 }
140 }
141 }
142 aMapEdgeIPV.Bind(aEdge,iPV);
143 }
144 aListTodo.RemoveFirst();
145
146 // find holes and make new edges
147
148 BRep_Builder aBld;
149 Standard_Integer iPVLast = 0;
150 iPV = -1;
151 while (iPV != 0) {
152
153 // find the most left edge
154 iPV = 0;
155 TopTools_ListIteratorOfListOfShape aIterFound;
156 Standard_Real aParF = aParVer[0].myParL;
157 TopoDS_Vertex aVerF = aParVer[0].myVerL;
158 for (aIter.Initialize(aListTodo); aIter.More(); aIter.Next()) {
159 const TopoDS_Edge& aEdge = TopoDS::Edge(aIter.Value());
160 Standard_Integer i = aMapEdgeIPV(aEdge);
161 if (aParVer[i].myParF < aParF) {
162 aParF = aParVer[i].myParF;
163 aVerF = aParVer[i].myVerF;
164 iPV = i;
165 aIterFound = aIter;
166 }
167 }
168
169 // get previous last parameter
170 Standard_Real aParPrevL;
171 TopoDS_Vertex aVerPrevL;
172 if (iPVLast == 0) {
173 aParPrevL = aParVer[0].myParF;
174 aVerPrevL = aParVer[0].myVerF;
175 }
176 else {
177 aParPrevL = aParVer[iPVLast].myParL;
178 aVerPrevL = aParVer[iPVLast].myVerL;
179 }
180
181 if (aParF > aParPrevL && !BRepTools::Compare(aVerF, aVerPrevL)) {
182 // make new edge to close the hole
183 TopoDS_Edge aNewEdge = theEdge;
184 aNewEdge.EmptyCopy();
185 aNewEdge.Orientation(TopAbs_FORWARD);
186 TopoDS_Vertex aV1 = aVerPrevL;
187 TopoDS_Vertex aV2 = aVerF;
188 aV1.Orientation(TopAbs_FORWARD);
189 aV2.Orientation(TopAbs_REVERSED);
190 aBld.Add(aNewEdge, aV1);
191 aBld.Add(aNewEdge, aV2);
192 aBld.UpdateVertex(aV1, aParPrevL, aNewEdge, BRep_Tool::Tolerance(aV1));
193 aBld.UpdateVertex(aV2, aParF, aNewEdge, BRep_Tool::Tolerance(aV2));
194 theListSplits.Append(aNewEdge);
195 }
196
197 iPVLast = iPV;
198 if (aIterFound.More()) aListTodo.Remove(aIterFound);
199 }
200
201 delete [] aParVer;
202}
203
204//=======================================================================
205//function : SplitEdge
206//purpose : static
207//=======================================================================
208
209static void
210SplitEdge (const TopoDS_Edge &theEdge,
4e57c75e 211 const BOPAlgo_PPaveFiller &thePDSFiller,
7fd59977 212 const TopTools_MapOfShape &theEdgesValid,
213 const Standard_Boolean useMap,
214 TopTools_ListOfShape &theListSplits)
215{
216 const TopAbs_State aStates[3] = {TopAbs_ON, TopAbs_IN, TopAbs_OUT};
217
218 for (Standard_Integer i=0; i < 3; i++) { // for each state {ON, IN, OUT}
219 if (QANewModTopOpe_Tools::IsSplit(thePDSFiller, theEdge, aStates[i])) {
220 // get splits according to this state
221 // and append them to the substitution list
222 TopTools_ListOfShape aListSplits;
223
224 QANewModTopOpe_Tools::Splits(thePDSFiller, theEdge, aStates[i], aListSplits);
225 TopTools_ListIteratorOfListOfShape aIterSplits(aListSplits);
226 for(; aIterSplits.More(); aIterSplits.Next()) {
227 const TopoDS_Shape& aEdge = aIterSplits.Value();
228 if (!useMap || theEdgesValid.Contains (aEdge))
229 theListSplits.Append(aEdge.Oriented(TopAbs_FORWARD));
230 }
231 }
232 }
233
234 if (!theListSplits.IsEmpty()) {
235 SplitEdgeComplete (theEdge, theListSplits);
236 }
237}
238
239//=======================================================================
240//function : IsEdgeOut
241//purpose : static
242//remark : the edge is expected to have a pcurve on this face
243//=======================================================================
244
245static Standard_Boolean
246IsEdgeOut (const TopoDS_Edge& theEdge, const TopoDS_Face& theFace)
247{
248 Standard_Real aParF, aParL, aParM;
249 Handle(Geom2d_Curve) aCrv = BRep_Tool::CurveOnSurface(theEdge, theFace, aParF, aParL);
250 if (aCrv.IsNull()) return Standard_True;
251
252 Standard_Real aPrec = Precision::PConfusion();
253 BRepClass_FaceClassifier aClf;
254 gp_Pnt2d aPnt;
255
256 if (!Precision::IsNegativeInfinite(aParF)) {
257 //check first point
258 aPnt = aCrv->Value(aParF);
259 aClf.Perform(theFace, aPnt, aPrec);
260 if(aClf.State() == TopAbs_OUT) return Standard_True;
261 }
262
263 if (!Precision::IsPositiveInfinite(aParL)) {
264 //check last point
265 aPnt = aCrv->Value(aParL);
266 aClf.Perform(theFace, aPnt, aPrec);
267 if(aClf.State() == TopAbs_OUT) return Standard_True;
268 }
269
270 //check middle point
271 if (!Precision::IsNegativeInfinite(aParF) &&
272 !Precision::IsPositiveInfinite(aParL)) {
273 aParM = aParF + 0.618 * (aParL - aParF);
274 }
275 else {
276 if (Precision::IsNegativeInfinite(aParF) &&
277 Precision::IsPositiveInfinite(aParL))
278 aParM = 0.;
279 else if (Precision::IsNegativeInfinite(aParF))
280 aParM = aParL - 1.;
281 else
282 aParM = aParF + 1.;
283 }
284 aPnt = aCrv->Value(aParM);
285 aClf.Perform(theFace, aPnt, aPrec);
286 if(aClf.State() == TopAbs_OUT) return Standard_True;
287
288 return Standard_False;
289}
290
291//=======================================================================
292//function : CorrectAncestorsList
293//purpose : static
294//=======================================================================
295
296static void
297CorrectAncestorsList (const TopoDS_Edge& theEdge, TopTools_ListOfShape& aListF)
298{
299 // remove duplicates from list,
300 // remove faces for which theEdge has the state "OUT"
301
302 // get a middle point on edge
303 TopTools_MapOfShape aMapF;
304 TopTools_ListIteratorOfListOfShape aIter(aListF);
305 while (aIter.More()) {
306 const TopoDS_Face& aFace = TopoDS::Face(aIter.Value());
307 if (!aMapF.Add(aFace)) {
308 // duplicate -> remove
309 aListF.Remove(aIter);
310 continue;
311 }
312 if (IsEdgeOut(theEdge, aFace)) {
313 // this face is not an ancestor -> remove
314 aListF.Remove(aIter);
315 continue;
316 }
317 aIter.Next();
318 }
319}
320
321//=======================================================================
322//function : PerformShell
323//purpose :
324//=======================================================================
325
326void
327QANewModTopOpe_Glue::PerformShell()
328{
329// Standard_Boolean isSolidShell = (myS1.ShapeType() == TopAbs_SOLID);
330 Standard_Boolean isSolidShell = Standard_False;
331 Standard_Integer i;
332
333 TopTools_MapOfShape anEdges, aCommonEdges, anOldVertices, aGenEdges;
334 TopExp_Explorer anExp;
335
336 anExp.Init(myS1, TopAbs_EDGE);
337 for(; anExp.More(); anExp.Next()) anEdges.Add(anExp.Current());
338
339 anExp.Init(myS2, TopAbs_EDGE);
340 for(; anExp.More(); anExp.Next()) {
341 if(anEdges.Contains(anExp.Current())) aCommonEdges.Add(anExp.Current());
342 }
343
344 anExp.ReInit();
345 for(; anExp.More(); anExp.Next()) anEdges.Add(anExp.Current());
346
347 anExp.Init(myS1, TopAbs_VERTEX);
348 for(; anExp.More(); anExp.Next()) anOldVertices.Add(anExp.Current());
349
350 anExp.Init(myS2, TopAbs_VERTEX);
351 for(; anExp.More(); anExp.Next()) anOldVertices.Add(anExp.Current());
352
353
354 // initialization
355 TopoDS_Shape aS1, aS2;
356 Standard_Boolean aWire1 = Standard_False, aWire2 = Standard_False;
357 anExp.Init(myS1, TopAbs_WIRE, TopAbs_FACE);
358 if(anExp.More()) {
359 aS1 = myS1;
360 aWire1 = Standard_True;
361 }
362 else {
363 anExp.Init(myS1, TopAbs_EDGE, TopAbs_WIRE);
364 if(anExp.More()) {
365 aS1 = myS1;
366 aWire1 = Standard_True;
367 }
368 }
369
370 anExp.Init(myS2, TopAbs_WIRE, TopAbs_FACE);
371 if(anExp.More()) {
372 aS2 = myS2;
373 aWire2 = Standard_True;
374 }
375 else {
376 anExp.Init(myS2, TopAbs_EDGE, TopAbs_WIRE);
377 if(anExp.More()) {
378 aS2 = myS2;
379 aWire2 = Standard_True;
380 }
381 }
382
383 if(aWire1) {
384 BRep_Builder aBld;
385 myS1.Nullify();
386 aBld.MakeCompound(TopoDS::Compound(myS1));
387 anExp.Init(aS1, TopAbs_COMPSOLID);
388 for(; anExp.More(); anExp.Next()) {
389 aBld.Add(myS1, anExp.Current());
390 }
391
392 anExp.Init(aS1, TopAbs_SOLID, TopAbs_COMPSOLID);
393 for(; anExp.More(); anExp.Next()) {
394 aBld.Add(myS1, anExp.Current());
395 }
396
397 anExp.Init(aS1, TopAbs_SHELL, TopAbs_SOLID);
398 for(; anExp.More(); anExp.Next()) {
399 aBld.Add(myS1, anExp.Current());
400 }
401
402 anExp.Init(aS1, TopAbs_FACE, TopAbs_SHELL);
403 for(; anExp.More(); anExp.Next()) {
404 aBld.Add(myS1, anExp.Current());
405 }
406
407 }
408
409 if(aWire2) {
410 BRep_Builder aBld;
411 myS2.Nullify();
412 aBld.MakeCompound(TopoDS::Compound(myS2));
413 anExp.Init(aS2, TopAbs_COMPSOLID);
414 for(; anExp.More(); anExp.Next()) {
415 aBld.Add(myS2, anExp.Current());
416 }
417
418 anExp.Init(aS2, TopAbs_SOLID, TopAbs_COMPSOLID);
419 for(; anExp.More(); anExp.Next()) {
420 aBld.Add(myS2, anExp.Current());
421 }
422
423 anExp.Init(aS2, TopAbs_SHELL, TopAbs_SOLID);
424 for(; anExp.More(); anExp.Next()) {
425 aBld.Add(myS2, anExp.Current());
426 }
427
428 anExp.Init(aS2, TopAbs_FACE, TopAbs_SHELL);
429 for(; anExp.More(); anExp.Next()) {
430 aBld.Add(myS2, anExp.Current());
431 }
432
433 }
434
435 Standard_Boolean hasSolid1 = Standard_False;
436 Standard_Boolean hasSolid2 = Standard_False;
437
438 anExp.Init(myS1, TopAbs_SOLID);
439
440 if (anExp.More())
441 hasSolid1 = Standard_True;
442
443 anExp.Init(myS2, TopAbs_SOLID);
444
445 if (anExp.More())
446 hasSolid2 = Standard_True;
447
448 if (hasSolid1 && hasSolid2)
4e57c75e 449 myOperation = BOPAlgo_FUSE;
7fd59977 450 else if (hasSolid1)
4e57c75e 451 myOperation = BOPAlgo_CUT21;
7fd59977 452 else if (hasSolid2)
4e57c75e 453 myOperation = BOPAlgo_CUT;
7fd59977 454 else
4e57c75e 455 myOperation = BOPAlgo_SECTION;
7fd59977 456
457 BRepAlgoAPI_BooleanOperation::Build();
458 if (!BuilderCanWork())
459 return;
460
461 if(aWire1) myS1 = aS1;
462 if(aWire2) myS2 = aS2;
463
464 TopTools_DataMapOfShapeListOfShape* aMapSEdgeFaces[2] =
465 {&myMapSEdgeFaces1, &myMapSEdgeFaces2};
466 TopTools_DataMapOfShapeShape* aMapSEdgeCrossFace[2] =
467 {&myMapSEdgeCrossFace1, &myMapSEdgeCrossFace2};
468 TopTools_MapOfShape aSetFaces[2];
469 TopTools_MapOfShape aSetEdges[2];
470
471 // fill myMapGener for new vertices
472 TopTools_MapIteratorOfMapOfShape aMapIter(anEdges);
473 const TopAbs_State aStates[3] = {TopAbs_ON, TopAbs_IN, TopAbs_OUT};
474 for(; aMapIter.More(); aMapIter.Next()) {
475 const TopoDS_Shape& aEdge = aMapIter.Key();
476
477 if(aCommonEdges.Contains(aEdge)) continue;
478
479 for (i=0; i < 3; i++) { // for each state {ON, IN, OUT}
480 if (QANewModTopOpe_Tools::IsSplit(myDSFiller, aEdge, aStates[i])) {
481 TopTools_ListOfShape aListSplits;
482
483 QANewModTopOpe_Tools::Splits(myDSFiller, aEdge, aStates[i], aListSplits);
484
485 TopTools_ListIteratorOfListOfShape aIterSplits(aListSplits);
486 for(; aIterSplits.More(); aIterSplits.Next()) {
487 const TopoDS_Shape& aE = aIterSplits.Value();
488 TopoDS_Iterator aTDSIter(aE);
489 for(; aTDSIter.More(); aTDSIter.Next()) {
490 const TopoDS_Shape& aV = aTDSIter.Value();
491
492 if(!anOldVertices.Add(aV)) continue;
493
494 if(!myMapGener.IsBound(aEdge)) {
495 // for Mandrake-10 - mkv,02.06.06 - myMapGener.Bind(aEdge, TopTools_ListOfShape());
496 TopTools_ListOfShape aListOfShape1;
497 myMapGener.Bind(aEdge, aListOfShape1);
498 }
499
500 myMapGener(aEdge).Append(aV);
501 }
502 }
503 }
504 }
505 }
506
507
508 // get list of section edges
509 const TopTools_ListOfShape& aListSE = SectionEdges();
510
511 // for each section edge remember the face crossed by the edge
512 // and the faces for which the edge coincides with a face's bound
513 TopTools_ListIteratorOfListOfShape aIterSE(aListSE);
514 Standard_Integer aNbUsedSecEdges = 0;
515 for(; aIterSE.More(); aIterSE.Next()) {
516 const TopoDS_Edge& aSecEdge = TopoDS::Edge(aIterSE.Value());
517
518 if(!aCommonEdges.Contains(aSecEdge)) {
519
520 aNbUsedSecEdges++;
521
522 TopoDS_Face aFaces[2];
523 QANewModTopOpe_Tools::EdgeCurveAncestors(myDSFiller, aSecEdge, aFaces[0],
524 aFaces[1]);
525
526 TopTools_ListOfShape aListF[2], aListE[2];
527 QANewModTopOpe_Tools::EdgeSectionAncestors(myDSFiller, aSecEdge, aListF[0],
528 aListF[1], aListE[0], aListE[1]);
529 CorrectAncestorsList (aSecEdge, aListF[0]);
530 CorrectAncestorsList (aSecEdge, aListF[1]);
531
532 Standard_Integer nbCurveAncestors = 0;
533 for (i = 0; i < 2; i++) {
534 if (!aListF[i].IsEmpty()) {
535 aMapSEdgeFaces[i]->Bind(aSecEdge, aListF[i]);
536 if (aListE[i].IsEmpty())
537 aMapSEdgeCrossFace[i]->Bind(aSecEdge, aListF[i].First());
538 TopTools_ListIteratorOfListOfShape aIter (aListF[i]);
539 for (; aIter.More(); aIter.Next())
540 aSetFaces[i].Add(aIter.Value());
541 }
542 else if (!aFaces[i].IsNull()) {
543 TopTools_ListOfShape aList;
544 aList.Append(aFaces[i]);
545 aMapSEdgeFaces[i]->Bind(aSecEdge, aList);
546 aMapSEdgeCrossFace[i]->Bind(aSecEdge, aFaces[i]);
547 aSetFaces[i].Add(aFaces[i]);
548 nbCurveAncestors++;
549 }
550 else if (!aListE[i].IsEmpty()) {
551 myEdgesToLeave.Add (aSecEdge);
552 TopTools_ListIteratorOfListOfShape aIter (aListE[i]);
553 for (; aIter.More(); aIter.Next())
554 aSetEdges[i].Add(aIter.Value());
555 }
556 }
557 if (nbCurveAncestors == 2) {
558 // the edge was computed by intersection of 2 surfaces
559 aGenEdges.Add(aSecEdge);
560 if (isSolidShell && !myAllowCutting) {
561 // Shell goes inside Solid while it is forbidden
562 return;
563 }
564 else {
565 // force same parameter
566 const Standard_Real aTol = 1.e-5;
567 BRep_Builder aBld;
568 aBld.SameRange (aSecEdge, Standard_False);
569 aBld.SameParameter (aSecEdge, Standard_False);
570 BRepLib::SameParameter (aSecEdge, aTol);
571 }
572 }
573 }
574 }
575
576 //--------------------------------------------------
577 if(aNbUsedSecEdges == 0 && aListSE.Extent() != 0) {
578 // all section edges are common edges - make compound
579 BRep_Builder aBld;
580 aBld.MakeCompound (TopoDS::Compound(myShape));
581 aBld.Add(myShape, myS1);
582 aBld.Add(myShape, myS2);
583 Done();
584 return;
585 }
586 //--------------------------------------------------
587
588 // cut faces of shell if another shape is solid
589 if (isSolidShell) {
590 // split edges of shape by section edges which are got
591 // due to coinciding of edges rather than intersecting of faces
592 TopTools_MapIteratorOfMapOfShape aIter(aSetEdges[1]);
593 for(; aIter.More(); aIter.Next()) {
594 const TopoDS_Edge aEdge = TopoDS::Edge (aIter.Key());
595 TopTools_ListOfShape aListSplitE;
596 SplitEdge (aEdge, myDSFiller, myEdgesToLeave, Standard_False, aListSplitE);
597 if (!aListSplitE.IsEmpty()) {
598 mySubst.Substitute (aEdge, aListSplitE);
599 if (mySubst.IsCopied (aEdge)) {
600 // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind(aEdge, TopTools_ListOfShape());
601 TopTools_ListOfShape aListOfShape2;
602 myMapModif.Bind(aEdge, aListOfShape2);
603 myMapModif(aEdge).Append (aListSplitE);
604 }
605 }
606 }
607
608 for(aIter.Initialize (aSetFaces[1]); aIter.More(); aIter.Next()) {
609 const TopoDS_Face aFace = TopoDS::Face (aIter.Key());
610 TopTools_ListOfShape aListSEOnFace;
611
612 // select section edges on this face
613 for (aIterSE.Initialize(aListSE); aIterSE.More(); aIterSE.Next()) {
614 const TopoDS_Edge& aSecEdge = TopoDS::Edge(aIterSE.Value());
615 // check if aFace is an ancestor of aSecEdge
616 if (aMapSEdgeFaces[1]->IsBound(aSecEdge)) {
617 TopTools_ListIteratorOfListOfShape
618 aIterF (aMapSEdgeFaces[1]->Find(aSecEdge));
619 for (; aIterF.More(); aIterF.Next())
620 if (aIterF.Value().IsSame(aFace)) {
621 aListSEOnFace.Append(aSecEdge);
622 break;
623 }
624 }
625 }
626 if (!aListSEOnFace.IsEmpty()) {
627 Standard_Boolean isCut = CutFace (aFace, aListSEOnFace);
628 if (isCut && !myAllowCutting) {
629 // Shell goes inside Solid while it is forbidden
630 return;
631 }
632 }
633 }
634
635 // remove from maps all the section edges which are not marked to leave
636 for (aIterSE.Initialize (aListSE); aIterSE.More(); aIterSE.Next()) {
637 const TopoDS_Shape& aSecEdge = aIterSE.Value();
638 if (!myEdgesToLeave.Contains (aSecEdge)) {
639 myMapSEdgeFaces1.UnBind (aSecEdge);
640 myMapSEdgeFaces2.UnBind (aSecEdge);
641 myMapSEdgeCrossFace1.UnBind (aSecEdge);
642 myMapSEdgeCrossFace2.UnBind (aSecEdge);
643 }
644 }
645 }
646 else { // not the case Solid-Shell
647 for (aIterSE.Initialize (aListSE); aIterSE.More(); aIterSE.Next())
648 myEdgesToLeave.Add (aIterSE.Value());
649 }
650
651 // process intersected faces
652 for (i = 0; i < 2; i++) {
653 if (i == 1 && isSolidShell) continue;
654
655 // split edges of shape by section edges which are got
656 // due to coinciding of edges rather than intersecting of faces
657 TopTools_MapIteratorOfMapOfShape aIter(aSetEdges[i]);
658 for(; aIter.More(); aIter.Next()) {
659 const TopoDS_Edge aEdge = TopoDS::Edge (aIter.Key());
660 TopTools_ListOfShape aListSplitE;
661 SplitEdge (aEdge, myDSFiller, myEdgesToLeave, Standard_True, aListSplitE);
662 if (!aListSplitE.IsEmpty()) {
663 mySubst.Substitute (aEdge, aListSplitE);
664 //Substitution of vertices at the ends of aEdge.
665 TopoDS_Vertex aV1, aV2;
666 TopExp::Vertices(aEdge, aV1, aV2);
667 TopTools_ListIteratorOfListOfShape anIter(aListSplitE);
668 for(; anIter.More(); anIter.Next()) {
669 const TopoDS_Edge& aSpE = TopoDS::Edge(anIter.Value());
670 TopoDS_Vertex aSpV1, aSpV2;
671 TopExp::Vertices(aSpE, aSpV1, aSpV2);
672 aSpV1.Orientation(TopAbs_FORWARD);
673 aSpV2.Orientation(TopAbs_FORWARD);
674 TopTools_ListOfShape aL;
675 if(BRepTools::Compare(aV1, aSpV1) && (!aV1.IsSame(aSpV1))) {
676 aL.Clear();
677 aL.Append(aSpV1);
678 if(!mySubst.IsCopied (aV1)) {
679 mySubst.Substitute(aV1, aL);
680// if (mySubst.IsCopied (aV1)) {
681 // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind(aV1, TopTools_ListOfShape());
682 TopTools_ListOfShape aListOfShape3;
683 myMapModif.Bind(aV1, aListOfShape3);
684 myMapModif(aV1).Append (aL);
685// }
686 }
687 }
688 if(BRepTools::Compare(aV1, aSpV2) && (!aV1.IsSame(aSpV2))) {
689 aL.Clear();
690 aL.Append(aSpV2);
691 if(!mySubst.IsCopied (aV1)) {
692 mySubst.Substitute(aV1, aL);
693// if (mySubst.IsCopied (aV1)) {
694 // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind(aV1, TopTools_ListOfShape());
695 TopTools_ListOfShape aListOfShape4;
696 myMapModif.Bind(aV1, aListOfShape4);
697 myMapModif(aV1).Append (aL);
698// }
699 }
700 }
701 if(BRepTools::Compare(aV2, aSpV1) && (!aV2.IsSame(aSpV1))) {
702 aL.Clear();
703 aL.Append(aSpV1);
704 if (!mySubst.IsCopied (aV2)) {
705 mySubst.Substitute(aV2, aL);
706// if (mySubst.IsCopied (aV2)) {
707 // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind(aV2, TopTools_ListOfShape());
708 TopTools_ListOfShape aListOfShape5;
709 myMapModif.Bind(aV2, aListOfShape5);
710 myMapModif(aV2).Append (aL);
711// }
712 }
713 }
714 if(BRepTools::Compare(aV2, aSpV2) && (!aV2.IsSame(aSpV2))) {
715 aL.Clear();
716 aL.Append(aSpV2);
717 if (!mySubst.IsCopied (aV2)) {
718 mySubst.Substitute(aV2, aL);
719// if (mySubst.IsCopied (aV2)) {
720 // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind(aV2, TopTools_ListOfShape());
721 TopTools_ListOfShape aListOfShape6;
722 myMapModif.Bind(aV2, aListOfShape6);
723 myMapModif(aV2).Append (aL);
724// }
725 }
726 }
727 }
728
729 if (mySubst.IsCopied (aEdge)) {
730 // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind(aEdge, TopTools_ListOfShape());
731 TopTools_ListOfShape aListOfShape7;
732 myMapModif.Bind(aEdge, aListOfShape7);
733 myMapModif(aEdge).Append (aListSplitE);
734 }
735 }
736 }
737
738 for(aIter.Initialize (aSetFaces[i]); aIter.More(); aIter.Next()) {
739 const TopoDS_Face aFace = TopoDS::Face (aIter.Key());
740 TopTools_ListOfShape aListSEOnFace;
741
742 // select section edges on this face
743 for (aIterSE.Initialize(aListSE); aIterSE.More(); aIterSE.Next()) {
744 const TopoDS_Edge& aSecEdge = TopoDS::Edge(aIterSE.Value());
745 // check if aFace is an ancestor of aSecEdge
746 if (aMapSEdgeFaces[i]->IsBound(aSecEdge)) {
747 TopTools_ListIteratorOfListOfShape
748 aIterF (aMapSEdgeFaces[i]->Find(aSecEdge));
749 for (; aIterF.More(); aIterF.Next())
750 if (aIterF.Value().IsSame(aFace)) {
751 aListSEOnFace.Append(aSecEdge);
752 break;
753 }
754 }
755 }
756 if (!aListSEOnFace.IsEmpty())
757 SectionInsideFace (aFace, aListSEOnFace, i, aGenEdges);
758 }
759 }
760
761 // construct new shapes from myS1 and myS2
762 // and result compound
763 TopoDS_Shape aNewS[2];
764 Standard_Integer nbModified = 0;
765 Standard_Integer nbDeleted = 0;
766 Standard_Integer iShape;
767
768 for (i = 0; i < 2; i++) {
769 const TopoDS_Shape& aOldS = (i==0 ? myS1 : myS2);
770 mySubst.Build(aOldS);
771 if (mySubst.IsCopied(aOldS)) {
772 if (!mySubst.Copy(aOldS).IsEmpty()) {
773 aNewS[i] = mySubst.Copy(aOldS).First();
774 aNewS[i].Orientation(aOldS.Orientation());
775 nbModified++;
776 iShape = i;
777 }
778 else if (!myAllowCutting) {
779 // all Shell is inside Solid while it is forbidden
780 return;
781 }
782 else
783 nbDeleted++;
784 }
785 else {
786 aNewS[i] = aOldS;
787 iShape = i;
788 }
789
790 TopExp_Explorer aExp (aOldS, TopAbs_FACE);
791 for (; aExp.More(); aExp.Next()) {
792 const TopoDS_Shape& aFace = aExp.Current();
793 if(myMapModif.IsBound(aFace)) continue;
794 if (mySubst.IsCopied(aFace)) {
795 if (!mySubst.Copy(aFace).IsEmpty()) {
796 myMapModif.Bind(aFace,mySubst.Copy(aFace));
797 }
798 }
799 }
800
801 }
802
803 if (nbModified > 0 && nbDeleted == 0) {
804 // the usual case
805 isSolidShell = Standard_True;
806 BRep_Builder aBld;
807 if(isSolidShell) {
808 aBld.MakeCompound (TopoDS::Compound(myShape));
809 aBld.Add(myShape, aNewS[0]);
810 aBld.Add(myShape, aNewS[1]);
811 }
812 else {
813 aBld.MakeShell (TopoDS::Shell(myShape));
814 for(anExp.Init(aNewS[0], TopAbs_FACE); anExp.More(); anExp.Next()) {
815 aBld.Add(myShape, anExp.Current());
816 }
817 for(anExp.Init(aNewS[1], TopAbs_FACE); anExp.More(); anExp.Next()) {
818 aBld.Add(myShape, anExp.Current());
819 }
820 }
821 Done();
822 }
823 else if (nbDeleted == 1) {
824 // all Shell is inside Solid while it is permitted
825 myShape = aNewS[iShape];
826 Done();
827 } else if (nbModified == 0) {
828 // The case if nothing is changed.
829 BRep_Builder aBld;
830
831 aBld.MakeCompound (TopoDS::Compound(myShape));
832 aBld.Add(myShape, aNewS[0]);
833 aBld.Add(myShape, aNewS[1]);
834 Done();
835 }
836
837 mySubst.Clear();
838 TopExp_Explorer aExp (myShape, TopAbs_EDGE);
839 Standard_Boolean IsSplit = Standard_False;
840 for (; aExp.More(); aExp.Next()) {
841 TopoDS_Edge aE = TopoDS::Edge(aExp.Current());
842 if(mySubst.IsCopied(aE)) continue;
843 aE.Orientation(TopAbs_FORWARD);
844 TopTools_ListOfShape aListSplits;
845 if(QANewModTopOpe_Tools::SplitE(aE, aListSplits)) {
846 if(!IsSplit) IsSplit = Standard_True;
847
848 BRep_Builder aBld;
849 Standard_Real aTol = Precision::Confusion();
850 TopTools_ListIteratorOfListOfShape anISpl(aListSplits);
851 for(; anISpl.More(); anISpl.Next()) {
852 const TopoDS_Shape& aSpE = anISpl.Value();
853 Standard_Real tol = BRep_Tool::Tolerance(TopoDS::Edge(aSpE));
854 if(tol > aTol) {
855 aBld.UpdateEdge(TopoDS::Edge(aSpE), 1.05*tol);
856 }
857 }
858
859 mySubst.Substitute(aE, aListSplits);
860 myMapModif.Bind(aE, aListSplits);
861 }
862 }
863
864 if(IsSplit) {
865 mySubst.Build(myShape);
866 if(mySubst.IsCopied(myShape)) {
867 aExp.Init(myShape, TopAbs_FACE);
868 for(; aExp.More(); aExp.Next()) {
869 const TopoDS_Shape& aF = aExp.Current();
870 if(mySubst.IsCopied(aF)) {
871 myMapModif.Bind(aF, mySubst.Copy(aF));
872 }
873 }
874 myShape = mySubst.Copy(myShape).First();
875 }
876 }
877
878}
879
880//=======================================================================
881//function : SplitFaceBoundary
882//purpose : static
883//=======================================================================
884
885static TopoDS_Face
886SplitFaceBoundary (const TopoDS_Face& theFace,
887 BRepTools_Substitution& theSubst,
4e57c75e 888 const BOPAlgo_PPaveFiller &thePDSFiller,
7fd59977 889 const TopTools_MapOfShape& theEdgesValid,
890 const Standard_Boolean useMap,
891 TopTools_DataMapOfShapeListOfShape& theMapModif)
892{
893 // split the face's edges by section edges lying on boundary
894 BRepTools_Substitution aLocalSubst;
895 TopExp_Explorer aExp (theFace, TopAbs_EDGE);
896 for (; aExp.More(); aExp.Next()) {
897 const TopoDS_Edge& aEdge = TopoDS::Edge (aExp.Current());
898 if (theSubst.IsCopied (aEdge)) continue;
899
900 TopTools_ListOfShape aListSplitE;
901 SplitEdge (aEdge, thePDSFiller, theEdgesValid, useMap, aListSplitE);
902 if (aListSplitE.IsEmpty()) continue;
903
904 theSubst.Substitute (aEdge, aListSplitE);
905 aLocalSubst.Substitute (aEdge, aListSplitE);
906//-------------------------------------------------------------
907 //Substitution of vertices at the ends of aEdge.
908 TopoDS_Vertex aV1, aV2;
909 TopExp::Vertices(aEdge, aV1, aV2);
910 TopTools_ListIteratorOfListOfShape anIter(aListSplitE);
911 for(; anIter.More(); anIter.Next()) {
912 const TopoDS_Edge& aSpE = TopoDS::Edge(anIter.Value());
913 TopoDS_Vertex aSpV1, aSpV2;
914 TopExp::Vertices(aSpE, aSpV1, aSpV2);
915 aSpV1.Orientation(TopAbs_FORWARD);
916 aSpV2.Orientation(TopAbs_FORWARD);
917 TopTools_ListOfShape aL;
918 if(BRepTools::Compare(aV1, aSpV1) && (!aV1.IsSame(aSpV1))) {
919 aL.Clear();
920 aL.Append(aSpV1);
921 aLocalSubst.Substitute(aV1, aL);
922 theSubst.Substitute(aV1, aL);
923 if (aLocalSubst.IsCopied (aV1)) {
924 // for Mandrake-10 - mkv,02.06.06 - theMapModif.Bind(aV1, TopTools_ListOfShape());
925 TopTools_ListOfShape aListOfShape1;
926 theMapModif.Bind(aV1, aListOfShape1);
927 theMapModif(aV1).Append (aL);
928 }
929 }
930 if(BRepTools::Compare(aV1, aSpV2) && (!aV1.IsSame(aSpV2))) {
931 aL.Clear();
932 aL.Append(aSpV2);
933 aLocalSubst.Substitute(aV1, aL);
934 theSubst.Substitute(aV1, aL);
935 if (aLocalSubst.IsCopied (aV1)) {
936 // for Mandrake-10 - mkv,02.06.06 - theMapModif.Bind(aV1, TopTools_ListOfShape());
937 TopTools_ListOfShape aListOfShape2;
938 theMapModif.Bind(aV1, aListOfShape2);
939 theMapModif(aV1).Append (aL);
940 }
941 }
942 if(BRepTools::Compare(aV2, aSpV1) && (!aV2.IsSame(aSpV1))) {
943 aL.Clear();
944 aL.Append(aSpV1);
945 aLocalSubst.Substitute(aV2, aL);
946 theSubst.Substitute(aV2, aL);
947 if (aLocalSubst.IsCopied (aV2)) {
948 // for Mandrake-10 - mkv,02.06.06 - theMapModif.Bind(aV2, TopTools_ListOfShape());
949 TopTools_ListOfShape aListOfShape3;
950 theMapModif.Bind(aV2, aListOfShape3);
951 theMapModif(aV2).Append (aL);
952 }
953 }
954 if(BRepTools::Compare(aV2, aSpV2) && (!aV2.IsSame(aSpV2))) {
955 aL.Clear();
956 aL.Append(aSpV2);
957 aLocalSubst.Substitute(aV2, aL);
958 theSubst.Substitute(aV2, aL);
959 if (aLocalSubst.IsCopied (aV2)) {
960 // for Mandrake-10 - mkv,02.06.06 - theMapModif.Bind(aV2, TopTools_ListOfShape());
961 TopTools_ListOfShape aListOfShape4;
962 theMapModif.Bind(aV2, aListOfShape4);
963 theMapModif(aV2).Append (aL);
964 }
965 }
966 }
967//-------------------------------------------------------------
968 if (aLocalSubst.IsCopied (aEdge)) {
969 // for Mandrake-10 - mkv,02.06.06 - theMapModif.Bind(aEdge, TopTools_ListOfShape());
970 TopTools_ListOfShape aListOfShape5;
971 theMapModif.Bind(aEdge, aListOfShape5);
972 theMapModif(aEdge).Append (aListSplitE);
973 }
974 }
975
976 aLocalSubst.Build (theFace);
977 if (aLocalSubst.IsCopied (theFace)) {
978// TopoDS_Iterator aIterF (theFace);
979// for (; aIterF.More(); aIterF.Next()) {
980// const TopoDS_Shape& aWire = aIterF.Value();
981// if (aLocalSubst.IsCopied (aWire))
982// theSubst.Substitute (aWire, aLocalSubst.Copy(aWire));
983// }
984 aExp.Init(theFace, TopAbs_EDGE);
985 for(; aExp.More(); aExp.Next()) {
986 const TopoDS_Shape& anE = aExp.Current();
987
988 if (aLocalSubst.IsCopied (anE)) {
989 if(!theSubst.IsCopied (anE)) {
990 theSubst.Substitute (anE, aLocalSubst.Copy(anE));
991 theMapModif.Bind(anE, aLocalSubst.Copy(anE));
992 }
993 }
994 }
995 return TopoDS::Face (aLocalSubst.Copy(theFace).First());
996 }
997 return theFace;
998}
999
1000//=======================================================================
1001//function : CutFace
1002//purpose :
1003//=======================================================================
1004
1005Standard_Boolean
1006QANewModTopOpe_Glue::CutFace(const TopoDS_Face& theFace,
1007 const TopTools_ListOfShape& theListSE)
1008{
1009 Standard_Boolean aRetValue = Standard_False;
1010 if (mySubst.IsCopied(theFace)) return aRetValue;
1011
1012 // theFace may contain edges which need to be substituted
1013 mySubst.Build(theFace);
1014 TopoDS_Face aFace;
1015 if (mySubst.IsCopied(theFace)) {
1016 if (mySubst.Copy(theFace).IsEmpty()) return Standard_True;
1017 aFace = TopoDS::Face(mySubst.Copy(theFace).First());
1018 }
1019 else
1020 aFace = theFace;
1021
1022 // split the face's edges by section edges lying on boundary
1023 TopoDS_Face aFace1 = SplitFaceBoundary (aFace, mySubst, myDSFiller,
1024 myEdgesToLeave, Standard_False, myMapModif);
1025
1026 // split face on subfaces by section edges lying inside the face
1027 BRepFeat_SplitShape aSpliter (aFace1);
1028 TopTools_ListIteratorOfListOfShape aIterSE (theListSE);
1029 for (; aIterSE.More(); aIterSE.Next()) {
1030 const TopoDS_Edge& aSEdge = TopoDS::Edge (aIterSE.Value());
1031 if (myMapSEdgeCrossFace2.IsBound(aSEdge))
1032 aSpliter.Add (aSEdge, aFace1);
1033 }
1034 aSpliter.Build();
1035 const TopTools_ListOfShape& aListSplit = aSpliter.Modified(aFace1);
1036
1037 // get OUT splits and append them to the substitution list
1038 TopTools_ListOfShape aListToSubst;
1039 TopTools_ListIteratorOfListOfShape aIter(aListSplit);
1040 for(; aIter.More(); aIter.Next()) {
1041 const TopoDS_Face& aFaceNew = TopoDS::Face (aIter.Value());
1042 TopAbs_State aState = ClassifyFace (aFaceNew, theListSE);
1043 if (aState == TopAbs_OUT) {
1044 aListToSubst.Append(aFaceNew.Oriented(TopAbs_FORWARD));
1045 // remember in the map the section edges to leave
1046 TopExp_Explorer aExp (aFaceNew, TopAbs_EDGE);
1047 for (; aExp.More(); aExp.Next()) {
1048 const TopoDS_Shape& aEdge = aExp.Current();
1049 if (myMapSEdgeFaces2.IsBound (aEdge))
1050 myEdgesToLeave.Add (aEdge);
1051 }
1052 }
1053 else {
1054 aRetValue = Standard_True;
1055 }
1056 }
1057 mySubst.Substitute(aFace, aListToSubst);
1058
1059 // update history
1060 if (mySubst.IsCopied(aFace)) {
1061 // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind(theFace, TopTools_ListOfShape());
1062 TopTools_ListOfShape aListOfShape;
1063 myMapModif.Bind(theFace, aListOfShape);
1064 myMapModif(theFace).Append (aListToSubst);
1065 }
1066
1067 return aRetValue;
1068}
1069
1070//=======================================================================
1071//function : GetVecIntoFace
1072//purpose : static
1073//=======================================================================
1074
1075static Standard_Boolean
1076GetVecIntoFace (const TopoDS_Face& theFace,
1077 const TopoDS_Edge& theEdge,
1078 gp_Pnt& thePntOnEdge,
1079 gp_Vec& theVecIntoFace)
1080{
1081 TopoDS_Shape aDummy = theFace.Oriented(TopAbs_FORWARD);
1082 TopoDS_Face aFace = TopoDS::Face(aDummy);
1083 TopoDS_Edge aEdge; // theEdge extracted from theFace (with orientation)
1084
1085 TopExp_Explorer aExp (aFace, TopAbs_EDGE);
1086 for (; aExp.More(); aExp.Next()) {
1087 aEdge = TopoDS::Edge (aExp.Current());
1088 if (aEdge.IsSame(theEdge)) break;
1089 }
1090 if (!aExp.More()) return Standard_False;
1091
1092 TopAbs_Orientation aOrient = aEdge.Orientation();
1093 if (aOrient != TopAbs_FORWARD && aOrient != TopAbs_REVERSED)
1094 return Standard_False;
1095
1096 Standard_Real aParF, aParL;
1097 Handle(Geom2d_Curve) aCrv = BRep_Tool::CurveOnSurface(aEdge, aFace, aParF, aParL);
1098 if (aCrv.IsNull()) return Standard_False;
1099 if (aCrv->Continuity() < GeomAbs_C1) return Standard_False;
1100
1101 // get middle point on edge and normal
1102 Standard_Real aParM = aParF + (aParL - aParF) * 0.618;
1103 gp_Pnt2d aPntOnCrv;
1104 gp_Vec2d aDeriv;
1105 aCrv->D1(aParM, aPntOnCrv, aDeriv);
1106 gp_Vec2d aNormal(-aDeriv.Y(), aDeriv.X());
1107 aNormal.Normalize();
1108 if (aOrient == TopAbs_REVERSED) aNormal.Reverse();
1109
1110 // translate middle point along the normal
1111 Standard_Real uMin, uMax, vMin, vMax;
1112 BRepTools::UVBounds(aFace, uMin, uMax, vMin, vMax);
1113 Standard_Real duv = Min(uMax - uMin, vMax - vMin) * 0.1;
1114 Standard_Real dtol = BRep_Tool::Tolerance(aEdge) * 100.;
1115 Standard_Real d = Min(duv, dtol);
1116 gp_Pnt2d aPntOnSurf = aPntOnCrv.Translated(aNormal * d);
1117
1118 // get 3d points
1119 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFace);
1120 gp_Pnt aPntOnFace;
1121 aSurf->D0(aPntOnSurf.X(), aPntOnSurf.Y(), aPntOnFace);
1122 aSurf->D0(aPntOnCrv.X(), aPntOnCrv.Y(), thePntOnEdge);
1123
1124 // compute theVecIntoFace
1125 theVecIntoFace = gp_Vec(thePntOnEdge, aPntOnFace);
1126 Standard_Real aNorm = theVecIntoFace.Magnitude();
1127 if (aNorm < Precision::Confusion())
1128 return Standard_False;
1129 theVecIntoFace.Divide(aNorm);
1130
1131 return Standard_True;
1132}
1133
1134//=======================================================================
1135//function : ClassifyFace
1136//purpose :
1137//=======================================================================
1138
1139TopAbs_State
1140QANewModTopOpe_Glue::ClassifyFace(const TopoDS_Face& theFace,
1141 const TopTools_ListOfShape& theListSE) const
1142{
1143 TopAbs_State aState = TopAbs_UNKNOWN;
1144
1145 TopTools_ListIteratorOfListOfShape aIterSE (theListSE);
1146 for (; aIterSE.More(); aIterSE.Next()) {
1147 const TopoDS_Edge& aEdge = TopoDS::Edge (aIterSE.Value());
1148
1149 // get a point on edge and a vector directed to inside face
1150 // relatively that point
1151 gp_Pnt aPntOnEdge;
1152 gp_Vec aVecIntoFace;
1153 if (BRep_Tool::Degenerated(aEdge) ||
1154 !GetVecIntoFace (theFace, aEdge, aPntOnEdge, aVecIntoFace))
1155 continue;
1156
1157 // get faces from solid
1158 if (!myMapSEdgeFaces1.IsBound(aEdge)) continue;
1159 TopTools_ListIteratorOfListOfShape aIterF (myMapSEdgeFaces1(aEdge));
1160 for (; aIterF.More(); aIterF.Next()) {
1161 const TopoDS_Face& aFaceSol = TopoDS::Face(aIterF.Value());
1162 TopAbs_Orientation aOrient = aFaceSol.Orientation();
1163 if (aOrient != TopAbs_FORWARD && aOrient != TopAbs_REVERSED)
1164 continue;
1165
1166 // classify theFace relatively aFaceSol
1167
1168 // get normal to the surface at the point aPntOnEdge
1169 Handle(Geom_Surface) aSurf = BRep_Tool::Surface(aFaceSol);
1170 GeomAPI_ProjectPointOnSurf aProjector(aPntOnEdge, aSurf);
1171 if (!aProjector.IsDone()) continue;
1172 Standard_Real u,v;
1173 aProjector.LowerDistanceParameters(u,v);
1174 gp_Vec d1u,d1v;
1175 gp_Pnt aPntProj;
1176 aSurf->D1(u, v, aPntProj, d1u, d1v);
1177 gp_Vec aNormal = d1u.Crossed(d1v);
1178 if (aOrient == TopAbs_REVERSED) aNormal.Reverse();
1179
1180 // compare normal and the vector "into face"
1181 Standard_Real aScalar = aVecIntoFace * aNormal;
1182 if (aScalar > Precision::Confusion()) {
1183 aState = TopAbs_OUT;
1184 break;
1185 }
1186 else if (aScalar < -Precision::Confusion())
1187 aState = TopAbs_IN;
1188 else
1189 aState = TopAbs_ON;
1190 }
1191 if (aState == TopAbs_IN || aState == TopAbs_ON)
1192 break;
1193 }
1194
1195 return aState;
1196}
1197
1198//=======================================================================
1199//function : IsVertexOnFaceBound
1200//purpose : static
1201//=======================================================================
1202
1203static Standard_Boolean
1204IsVertexOnFaceBound (const TopoDS_Vertex& theVer,
1205 const TopoDS_Face& theFace,
1206 TopoDS_Edge& theEdgeContacted,
1207 TopoDS_Vertex& theVerContacted,
1208 Standard_Real& thePar,
1209 Standard_Real& theDist)
1210{
1211 Standard_Real aDist, aPar, aTol2;
1212 theDist = RealLast();
1213 gp_Pnt aPnt(BRep_Tool::Pnt(theVer));
1214 Standard_Boolean isContactByVer = Standard_False;
1215
1216 TopExp_Explorer aExp (theFace.Oriented(TopAbs_FORWARD), TopAbs_EDGE);
1217 for (; aExp.More() && theDist > Precision::Confusion(); aExp.Next()) {
1218 const TopoDS_Edge& aEdge = TopoDS::Edge (aExp.Current());
1219
1220 // first compare by vertices
1221 TopoDS_Iterator aIter (aEdge, Standard_False);
1222 for (; aIter.More(); aIter.Next()) {
1223 const TopoDS_Vertex& aVer = TopoDS::Vertex (aIter.Value());
1224 if (aVer.IsSame(theVer)) {
1225 theEdgeContacted = aEdge;
1226 theVerContacted = aVer;
1227 return Standard_True;
1228 }
1229 if (QANewModTopOpe_Glue::CompareVertices (aVer, theVer, aDist)) {
1230 if (aDist < theDist) {
1231 theEdgeContacted = aEdge;
1232 theVerContacted = aVer;
1233 theDist = aDist;
1234 thePar = BRep_Tool::Parameter (aVer, aEdge);
1235 aTol2 = BRep_Tool::Tolerance (aVer);
1236 isContactByVer = Standard_True;
1237 }
1238 }
1239 }
1240
1241 if (!isContactByVer) {
1242 // project on edge
1243 if (!BRep_Tool::Degenerated(aEdge)) {
1244 if (QANewModTopOpe_Glue::ProjPointOnEdge (aPnt, aEdge, aPar, aDist)) {
1245 if (aDist < theDist) {
1246 theEdgeContacted = aEdge;
1247 theVerContacted.Nullify();
1248 theDist = aDist;
1249 thePar = aPar;
1250 aTol2 = BRep_Tool::Tolerance(aEdge);
1251 }
1252 }
1253 }
1254 }
1255 }
1256
1257 if (theDist <= BRep_Tool::Tolerance(theVer) || theDist <= aTol2)
1258 return Standard_True;
1259
1260 return Standard_False;
1261}
1262
1263//=======================================================================
1264//function : UpdateMapNewOld
1265//purpose : static
1266//=======================================================================
1267
1268static void
1269UpdateMapNewOld (const TopoDS_Shape& theSh, const BRepTools_Substitution& theSubst,
1270 TopTools_DataMapOfShapeShape& theMapNewOld)
1271{
1272 TopTools_IndexedMapOfShape aMapSh;
1273 TopExp::MapShapes (theSh, aMapSh);
1274
1275 for (Standard_Integer i=1; i<=aMapSh.Extent(); i++) {
1276 const TopoDS_Shape& aSubSh = aMapSh(i);
1277 if (!aSubSh.IsSame(theSh) && theSubst.IsCopied (aSubSh)) {
1278 TopTools_ListIteratorOfListOfShape aIt (theSubst.Copy(aSubSh));
1279 for (; aIt.More(); aIt.Next()) {
1280 const TopoDS_Shape& aNewSubSh = aIt.Value();
1281 if (theMapNewOld.IsBound(aSubSh)) {
1282 TopoDS_Shape aOldSubSh = theMapNewOld(aSubSh);
1283 theMapNewOld.UnBind (aSubSh);
1284 theMapNewOld.Bind (aNewSubSh, aOldSubSh);
1285 }
1286 else {
1287 theMapNewOld.Bind (aNewSubSh, aSubSh);
1288 }
1289 }
1290 }
1291 }
1292}
1293
1294//=======================================================================
1295//function : DoLocalSubstitution
1296//purpose : static
1297//=======================================================================
1298
1299static void
1300DoLocalSubstitution (TopoDS_Shape& theSh, const TopoDS_Shape& theSubSh,
1301 const TopoDS_Shape& theNewSubSh,
1302 TopTools_DataMapOfShapeShape& theMapNewOld)
1303{
1304 BRepTools_Substitution aLocalSubst;
1305 TopTools_ListOfShape aList;
1306 aList.Append (theNewSubSh.Oriented(TopAbs_FORWARD));
1307 aLocalSubst.Substitute (theSubSh, aList);
1308 aLocalSubst.Build(theSh);
1309
1310 if (aLocalSubst.IsCopied(theSh)) {
1311 UpdateMapNewOld (theSh, aLocalSubst, theMapNewOld);
1312 theSh = aLocalSubst.Copy(theSh).First();
1313 }
1314}
1315
1316//=======================================================================
1317//function : SectionInsideFace
1318//purpose :
1319//=======================================================================
1320
1321void
1322QANewModTopOpe_Glue::SectionInsideFace(const TopoDS_Face& theFace,
1323 const TopTools_ListOfShape& theListSE,
1324 const Standard_Integer theShapeNum,
1325 const TopTools_MapOfShape& theGenEdges)
1326{
1327 if (mySubst.IsCopied(theFace)) return;
1328
1329 // theFace may contain edges which need to be substituted
1330 mySubst.Build(theFace);
1331 TopoDS_Face aFace;
1332 if (mySubst.IsCopied(theFace)) {
1333 if (mySubst.Copy(theFace).IsEmpty()) return;
1334 aFace = TopoDS::Face(mySubst.Copy(theFace).First());
1335 }
1336 else
1337 aFace = theFace;
1338
1339 // split the face's edges by section edges lying on boundary
1340 TopoDS_Face aFace1 = SplitFaceBoundary (aFace, mySubst, myDSFiller,
1341 myEdgesToLeave, Standard_True, myMapModif);
1342 TopTools_DataMapOfShapeShape aMapNewOrig;
1343 UpdateMapNewOld (theFace, mySubst, aMapNewOrig);
1344
1345 // process section edges contacting the face boundary:
1346 // insert internal vertices in the boundary
1347 const TopTools_DataMapOfShapeShape& aMapEF =
1348 (theShapeNum==0 ? myMapSEdgeCrossFace1 : myMapSEdgeCrossFace2);
1349 BRep_Builder aBld;
1350 TopTools_DataMapOfShapeShape aMapNewOld;
1351 TopTools_ListIteratorOfListOfShape aIterSE (theListSE);
1352
1353 TopTools_MapOfShape aVerGener;
1354
1355 for (; aIterSE.More(); aIterSE.Next()) {
1356 const TopoDS_Edge& aSEdge = TopoDS::Edge (aIterSE.Value());
1357 // skip edges lying on the boundary
1358 if (!aMapEF.IsBound (aSEdge)) continue;
1359
1360 // check if vertices of aSEdge contacts edges of aFace
1361 TopoDS_Iterator aIter (aSEdge, Standard_False);
1362 for (; aIter.More(); aIter.Next()) {
1363 const TopoDS_Vertex& aSVer = TopoDS::Vertex (aIter.Value());
1364 if (aSVer.Orientation() != TopAbs_FORWARD &&
1365 aSVer.Orientation() != TopAbs_REVERSED) continue;
1366
1367 TopoDS_Edge aEdge;
1368 TopoDS_Vertex aVer;
1369 Standard_Real aPar, aDist;
1370 if (IsVertexOnFaceBound (aSVer, aFace1, aEdge, aVer, aPar, aDist)) {
1371 // aSVer contacts aFace's boundary
1372
1373 if (!aVer.IsNull()) { // vertex contacted
1374 if (!aVer.IsSame(aSVer)) {
1375 // the vertices are coincided but not the same
1376 // => substitute aVer with aSVer
1377 Standard_Real aTol = Max (BRep_Tool::Tolerance(aSVer),
1378 BRep_Tool::Tolerance(aVer) + aDist);
1379 TopAbs_Orientation aOri = aVer.Orientation();
1380 if (aOri != TopAbs_FORWARD && aOri != TopAbs_REVERSED) {
1381 TopoDS_Shape aDummy = aSVer.Oriented(aOri);
1382 aBld.UpdateVertex (TopoDS::Vertex (aDummy),
1383 aPar, aEdge, aTol);
1384 }
1385 DoLocalSubstitution (aFace1, aVer, aSVer, aMapNewOld);
1386 // update history
1387 TopoDS_Shape aOrig = aMapNewOld(aSVer);
1388 if (aMapNewOrig.IsBound(aOrig)) aOrig = aMapNewOrig(aOrig);
1389 // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind(aOrig, TopTools_ListOfShape());
1390 TopTools_ListOfShape aListOfShape1;
1391 myMapModif.Bind(aOrig, aListOfShape1);
1392 myMapModif(aOrig).Append (aSVer);
1393 aVerGener.Add(aSVer);
1394 continue;
1395 }
1396 }
1397
1398 else { // contact inside edge
1399 // add the vertex as internal to the edge of the face
1400 TopoDS_Edge aNewEdge;
1401 InsertVertexInEdge (aEdge, aSVer, aPar, aNewEdge);
1402 // substitute edge
1403 DoLocalSubstitution (aFace1, aEdge, aNewEdge, aMapNewOld);
1404 // update history
1405 const TopoDS_Shape& aOld = aMapNewOld(aNewEdge);
1406 TopoDS_Shape aOrig;
1407 if (aMapNewOrig.IsBound(aOld)) {
1408 aOrig = aMapNewOrig(aOld);
1409 TopTools_ListOfShape& aListModif = myMapModif(aOrig);
1410 TopTools_ListIteratorOfListOfShape aIt (aListModif);
1411 for (; aIt.More(); aIt.Next())
1412 if (aIt.Value().IsSame(aOld)) {
1413 aListModif.Remove (aIt);
1414 break;
1415 }
1416 aListModif.Append (aNewEdge);
1417 }
1418 else {
1419 aOrig = aOld;
1420 // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind(aOrig, TopTools_ListOfShape());
1421 TopTools_ListOfShape aListOfShape2;
1422 myMapModif.Bind(aOrig, aListOfShape2);
1423 myMapModif(aOrig).Append (aNewEdge);
1424 }
1425 if (!myMapGener.IsBound (aOrig)) {
1426 // for Mandrake-10 - mkv,02.06.06 - myMapGener.Bind(aOrig, TopTools_ListOfShape());
1427 TopTools_ListOfShape aListOfShape3;
1428 myMapGener.Bind(aOrig, aListOfShape3);
1429 }
1430 myMapGener(aOrig).Append (aSVer);
1431 aVerGener.Add(aSVer);
1432 }
1433 }
1434 }
1435 }
1436
1437 // add the made replacements in the global substitution list
1438 TopTools_DataMapIteratorOfDataMapOfShapeShape aDIter (aMapNewOld);
1439 for (; aDIter.More(); aDIter.Next()) {
1440 TopTools_ListOfShape aList;
1441 const TopoDS_Shape& aOld = aDIter.Value();
1442 const TopoDS_Shape& aNew = aDIter.Key();
1443 aList.Append (aNew);
1444 mySubst.Substitute (aOld, aList);
1445 }
1446
1447 // make wires from section edges
1448 Handle(BRepAlgo_EdgeConnector) aConnector = new BRepAlgo_EdgeConnector;
1449 TopTools_ListOfShape aListGener;
1450 TopoDS_Vertex aV1, aV2;
1451 for (aIterSE.Initialize (theListSE); aIterSE.More(); aIterSE.Next()) {
1452 const TopoDS_Edge& aSEdge = TopoDS::Edge (aIterSE.Value());
1453 if (aMapEF.IsBound (aSEdge)) {
1454 aConnector->Add (aSEdge);
1455 aConnector->AddStart (aSEdge);
1456 if(theGenEdges.Contains(aSEdge)) {
1457 aListGener.Append (aSEdge);
1458 TopExp::Vertices(aSEdge, aV1, aV2);
1459 if(aVerGener.Add(aV1)) aListGener.Append (aV1);
1460 if(aVerGener.Add(aV2)) aListGener.Append (aV2);
1461 }
1462 }
1463 }
1464 const TopTools_ListOfShape& aListW = aConnector->MakeBlock();
1465 if (aConnector->IsDone()) {
1466 // add new wires to face
1467 TopoDS_Face aNewFace = aFace1;
1468 aNewFace.EmptyCopy();
1469 aNewFace.Orientation(TopAbs_FORWARD);
1470 aBld.NaturalRestriction (aNewFace, BRep_Tool::NaturalRestriction(aFace1));
1471 // add old subshapes
1472 TopoDS_Iterator aIterF (aFace1, Standard_False);
1473 for (; aIterF.More(); aIterF.Next()) {
1474 aBld.Add (aNewFace, aIterF.Value());
1475 }
1476 // add new wires as internal
1477 TopTools_ListIteratorOfListOfShape aIterL (aListW);
1478 for (; aIterL.More(); aIterL.Next()) {
1479 TopoDS_Shape aWire = aIterL.Value();
1480 // check if there is a wire containing the same set of edges;
1481 // in this case use the old wire
1482 aWire = FindWireOrUpdateMap (aWire, myMapEdgeWires);
1483 aBld.Add (aNewFace, aWire.Oriented(TopAbs_INTERNAL));
1484 }
1485 // substitute face
1486 TopTools_ListOfShape aList;
1487 aList.Append(aNewFace);
1488 mySubst.Substitute(aFace, aList);
1489 // update history
1490 // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind(theFace, TopTools_ListOfShape());
1491 TopTools_ListOfShape aListOfShape4;
1492 myMapModif.Bind(theFace, aListOfShape4);
1493 myMapModif(theFace).Append (aList);
1494 if(!aListGener.IsEmpty()) {
1495 // for Mandrake-10 - mkv,02.06.06 - myMapGener.Bind(theFace, TopTools_ListOfShape());
1496 TopTools_ListOfShape aListOfShape5;
1497 myMapGener.Bind(theFace, aListOfShape5);
1498 myMapGener(theFace).Append (aListGener);
1499 }
1500 }
1501#ifdef DEB
1502 else if (!aListW.IsEmpty()) {
1503 cout<<"QANewModTopOpe_Glue::SectionInsideFace : can't connect edges"<<endl;
1504 }
1505#endif
1506}