1 // Created on: 2001-05-05
2 // Created by: Sergey KHROMOV
3 // Copyright (c) 2001-2012 OPEN CASCADE SAS
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.
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.
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.
20 #include <QANewModTopOpe_Glue.ixx>
21 #include <TopExp_Explorer.hxx>
23 #include <TopTools_ListIteratorOfListOfShape.hxx>
24 #include <TopTools_ListOfShape.hxx>
25 #include <TopoDS_Compound.hxx>
26 #include <TopTools_DataMapIteratorOfDataMapOfShapeListOfShape.hxx>
27 #include <TopTools_MapOfShape.hxx>
28 #include <TopTools_MapIteratorOfMapOfShape.hxx>
30 #include <QANewModTopOpe_Tools.hxx>
31 #include <BRep_Builder.hxx>
32 #include <BRep_Tool.hxx>
33 #include <Geom_TrimmedCurve.hxx>
34 #include <GeomProjLib.hxx>
35 #include <Precision.hxx>
36 #include <BRepAdaptor_Surface.hxx>
38 static Standard_Boolean isAnalitic(const TopoDS_Shape &theShape)
40 if (theShape.ShapeType() != TopAbs_FACE)
41 return Standard_False;
43 TopoDS_Face aFace = TopoDS::Face(theShape);
44 BRepAdaptor_Surface aSurf(aFace);
45 Standard_Boolean isAna = Standard_False;
47 switch (aSurf.GetType()) {
49 case GeomAbs_Cylinder :
53 isAna = Standard_True;
56 isAna = Standard_False;
62 static void DoPCurveOnF(const TopoDS_Edge &theEdge, const TopoDS_Face &theFace)
64 BRep_Builder aBuilder;
65 TopLoc_Location aCLoc;
66 TopLoc_Location aSLoc;
69 Handle(Geom_Curve) aCurve = BRep_Tool::Curve(theEdge, aCLoc, aF, aL);
70 Handle(Geom_TrimmedCurve) aTrCurve = new Geom_TrimmedCurve(aCurve, aF, aL);
71 Handle(Geom_Surface) aSurface = BRep_Tool::Surface(theFace, aSLoc);
72 TopLoc_Location aCTLoc = aSLoc.Inverted().Multiplied(aCLoc);
74 aTrCurve->Transform(aCTLoc.Transformation());
76 Handle(Geom2d_Curve) aCurve2d = GeomProjLib::Curve2d (aTrCurve, aSurface);
78 aBuilder.UpdateEdge(theEdge, aCurve2d, aSurface,
79 aSLoc, Precision::Confusion());
82 static TopoDS_Face GetAdjacentFace
83 (const TopoDS_Shape &theEdge,
84 const TopoDS_Shape &theFace,
85 const TopTools_IndexedDataMapOfShapeListOfShape &theAncMap)
89 if (theAncMap.Contains(theEdge)) {
90 const TopTools_ListOfShape &aLOfFaces =
91 theAncMap.FindFromKey(theEdge);
92 TopTools_ListIteratorOfListOfShape anIter(aLOfFaces);
94 for (; anIter.More(); anIter.Next()) {
95 const TopoDS_Shape &aLocalFace = anIter.Value();
97 if (!theFace.IsSame(aLocalFace)) {
98 aFace = TopoDS::Face(aLocalFace);
107 //=======================================================================
108 //function : SubstitudeSDFaces
110 //=======================================================================
112 Standard_Boolean QANewModTopOpe_Glue::SubstitudeSDFaces
113 (const TopoDS_Shape &theFirstSDFace,
114 const TopoDS_Shape &theSecondSDFace,
115 TopoDS_Shape &theNewSolid1,
116 TopoDS_Shape &theNewSolid2,
117 TopTools_DataMapOfShapeListOfShape &theMapOfChangedFaces)
119 // If the first face is already splited, we use its splits
120 // to recursively call this function.
121 if (theMapOfChangedFaces.IsBound(theFirstSDFace)) {
122 const TopTools_ListOfShape &aLocalList =
123 theMapOfChangedFaces(theFirstSDFace);
124 TopTools_ListIteratorOfListOfShape anIter(aLocalList);
126 for (;anIter.More(); anIter.Next()) {
127 const TopoDS_Shape &aNewShape = anIter.Value();
128 if (!SubstitudeSDFaces(aNewShape, theSecondSDFace,
129 theNewSolid1, theNewSolid2,
130 theMapOfChangedFaces))
131 return Standard_False;
133 return Standard_True;
136 // If the second face is already splited, we use its splits
137 // to recursively call this function.
138 if (theMapOfChangedFaces.IsBound(theSecondSDFace)) {
139 const TopTools_ListOfShape &aLocalList =
140 theMapOfChangedFaces(theSecondSDFace);
141 TopTools_ListIteratorOfListOfShape anIter(aLocalList);
143 for (;anIter.More(); anIter.Next()) {
144 const TopoDS_Shape &aNewShape = anIter.Value();
145 if (!SubstitudeSDFaces(theFirstSDFace, aNewShape,
146 theNewSolid1, theNewSolid2,
147 theMapOfChangedFaces))
148 return Standard_False;
150 return Standard_True;
154 // If neither the first face nor the second one were
155 // splited before, we begin calculation:
156 TopTools_IndexedDataMapOfShapeListOfShape aHistory;
157 Standard_Boolean isCommonFound;
159 if (!QANewModTopOpe_Tools::BoolOpe(theFirstSDFace.Oriented(TopAbs_FORWARD),
160 theSecondSDFace.Oriented(TopAbs_FORWARD),
161 isCommonFound, aHistory))
162 return Standard_False;
165 return Standard_True;
167 TopTools_IndexedDataMapOfShapeListOfShape anAncMap1;
168 TopTools_IndexedDataMapOfShapeListOfShape anAncMap2;
170 TopExp::MapShapesAndAncestors(theNewSolid1, TopAbs_EDGE,
171 TopAbs_FACE, anAncMap1);
172 TopExp::MapShapesAndAncestors(theNewSolid2, TopAbs_EDGE,
173 TopAbs_FACE, anAncMap2);
175 // Creation of a compound of old solids.
176 // The substitution operation will be built with this
178 BRep_Builder aBuilder;
179 TopoDS_Compound aCompound;
181 aBuilder.MakeCompound(aCompound);
182 aBuilder.Add(aCompound, theNewSolid1);
183 aBuilder.Add(aCompound, theNewSolid2);
185 // Substitution of updated sub-shapes of the first solid.
186 BRepTools_Substitution aSubstTool;
187 Standard_Integer aNbModifShape = aHistory.Extent();
190 for (i = 1; i <= aNbModifShape; i++) {
191 TopTools_ListOfShape aModifShapes;
192 const TopoDS_Shape &anAncestor = aHistory.FindKey(i);
193 TopTools_ListIteratorOfListOfShape anIter(aHistory.FindFromIndex(i));
195 if (anAncestor.IsSame(theSecondSDFace)) {
196 for (; anIter.More(); anIter.Next())
197 aModifShapes.Append(anIter.Value());
199 for (; anIter.More(); anIter.Next())
200 aModifShapes.Append(anIter.Value().Oriented(TopAbs_FORWARD));
203 if (anAncestor.ShapeType() == TopAbs_EDGE) {
204 // Check if the edges from common contain pcurves on both shapes.
205 // If they do not, create them.
206 TopoDS_Edge anAncEdge = TopoDS::Edge(anAncestor);
208 if (anAncMap1.Contains(anAncestor)) {
209 TopoDS_Face aFace = GetAdjacentFace(anAncestor, theFirstSDFace,
211 if(!aFace.IsNull()) {//added to fix 4086
212 Standard_Real aFirst;
215 anIter.Initialize(aHistory.FindFromIndex(i));
216 for (; anIter.More(); anIter.Next()) {
217 TopoDS_Edge aSplit = TopoDS::Edge(anIter.Value());
218 Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface
219 (aSplit, aFace, aFirst, aLast);
221 if (aPCurve.IsNull())
222 DoPCurveOnF(aSplit, aFace);
227 if (anAncMap2.Contains(anAncestor)) {
228 TopoDS_Face aFace = GetAdjacentFace(anAncestor, theSecondSDFace,
230 if(!aFace.IsNull()) {//added to fix 4086
231 Standard_Real aFirst;
234 anIter.Initialize(aHistory.FindFromIndex(i));
235 for (; anIter.More(); anIter.Next()) {
236 TopoDS_Edge aSplit = TopoDS::Edge(anIter.Value());
237 Handle(Geom2d_Curve) aPCurve = BRep_Tool::CurveOnSurface
238 (aSplit, aFace, aFirst, aLast);
240 if (aPCurve.IsNull())
241 DoPCurveOnF(aSplit, aFace);
247 //--------------------------------------------------------------
248 if (!myMapModif.IsBound(anAncestor))
249 myMapModif.Bind(anAncestor, aModifShapes);
250 //--------------------------------------------------------------
252 aSubstTool.Substitute(anAncestor, aModifShapes);
255 aSubstTool.Build(aCompound);
257 // Update the map theMapOfChangedFaces and
258 // obtain a new solid from the first one.
259 if (aSubstTool.IsCopied(theNewSolid1)) {
260 // Add changed faces of the first solid to theMapOfChangedFaces:
261 TopExp_Explorer anExp(theNewSolid1, TopAbs_FACE);
262 for (; anExp.More(); anExp.Next()) {
263 // For each face from solid
264 const TopoDS_Shape &aFace = anExp.Current();
266 if (aSubstTool.IsCopied(aFace)) {
267 const TopTools_ListOfShape &aList = aSubstTool.Copy(aFace);
269 TopTools_ListOfShape aNewList;
270 if (!theMapOfChangedFaces.IsBound(aFace))
271 theMapOfChangedFaces.Bind(aFace, aNewList);
273 TopTools_ListIteratorOfListOfShape anIter(aList);
274 for (; anIter.More(); anIter.Next()) {
275 TopoDS_Shape aLocalFace = anIter.Value();
277 if (aSubstTool.IsCopied(aLocalFace))
278 aLocalFace = aSubstTool.Copy(aLocalFace).First();
280 theMapOfChangedFaces(aFace).Append(aLocalFace);
284 // Obtain a new solid.
285 theNewSolid1 = aSubstTool.Copy(theNewSolid1).First();
288 // Update the map theMapOfChangedFaces and
289 // obtain a new solid from the second one.
290 if (aSubstTool.IsCopied(theNewSolid2)) {
291 // Add changed faces of the second solid to theMapOfChangedFaces:
292 TopExp_Explorer anExp(theNewSolid2, TopAbs_FACE);
293 for (; anExp.More(); anExp.Next()) {
294 // For each face from solid
295 const TopoDS_Shape &aFace = anExp.Current();
297 if (aSubstTool.IsCopied(aFace)) {
298 const TopTools_ListOfShape &aList = aSubstTool.Copy(aFace);
300 TopTools_ListOfShape aNewList;
301 if (!theMapOfChangedFaces.IsBound(aFace))
302 theMapOfChangedFaces.Bind(aFace, aNewList);
304 TopTools_ListIteratorOfListOfShape anIter(aList);
305 for (; anIter.More(); anIter.Next()) {
306 TopoDS_Shape aLocalFace = anIter.Value();
308 if (aSubstTool.IsCopied(aLocalFace))
309 aLocalFace = aSubstTool.Copy(aLocalFace).First();
311 theMapOfChangedFaces(aFace).Append(aLocalFace);
315 // Obtain a new solid.
316 theNewSolid2 = aSubstTool.Copy(theNewSolid2).First();
319 return Standard_True;
322 //=======================================================================
323 //function : PerformSolidSolid
325 //=======================================================================
328 QANewModTopOpe_Glue::PerformSDFaces()
330 TopExp_Explorer anExp;
331 TopoDS_Shape aS1, aS2;
332 Standard_Boolean aWire1 = Standard_False, aWire2 = Standard_False;
333 anExp.Init(myS1, TopAbs_WIRE, TopAbs_FACE);
336 aWire1 = Standard_True;
339 anExp.Init(myS1, TopAbs_EDGE, TopAbs_WIRE);
342 aWire1 = Standard_True;
346 anExp.Init(myS2, TopAbs_WIRE, TopAbs_FACE);
349 aWire2 = Standard_True;
352 anExp.Init(myS2, TopAbs_EDGE, TopAbs_WIRE);
355 aWire2 = Standard_True;
362 aBld.MakeCompound(TopoDS::Compound(myS1));
363 anExp.Init(aS1, TopAbs_COMPSOLID);
364 for(; anExp.More(); anExp.Next()) {
365 aBld.Add(myS1, anExp.Current());
368 anExp.Init(aS1, TopAbs_SOLID, TopAbs_COMPSOLID);
369 for(; anExp.More(); anExp.Next()) {
370 aBld.Add(myS1, anExp.Current());
373 anExp.Init(aS1, TopAbs_SHELL, TopAbs_SOLID);
374 for(; anExp.More(); anExp.Next()) {
375 aBld.Add(myS1, anExp.Current());
378 anExp.Init(aS1, TopAbs_FACE, TopAbs_SHELL);
379 for(; anExp.More(); anExp.Next()) {
380 aBld.Add(myS1, anExp.Current());
388 aBld.MakeCompound(TopoDS::Compound(myS2));
389 anExp.Init(aS2, TopAbs_COMPSOLID);
390 for(; anExp.More(); anExp.Next()) {
391 aBld.Add(myS2, anExp.Current());
394 anExp.Init(aS2, TopAbs_SOLID, TopAbs_COMPSOLID);
395 for(; anExp.More(); anExp.Next()) {
396 aBld.Add(myS2, anExp.Current());
399 anExp.Init(aS2, TopAbs_SHELL, TopAbs_SOLID);
400 for(; anExp.More(); anExp.Next()) {
401 aBld.Add(myS2, anExp.Current());
404 anExp.Init(aS2, TopAbs_FACE, TopAbs_SHELL);
405 for(; anExp.More(); anExp.Next()) {
406 aBld.Add(myS2, anExp.Current());
411 BRepAlgoAPI_BooleanOperation::Build();
412 if (!BuilderCanWork())
415 if(aWire1) myS1 = aS1;
416 if(aWire2) myS2 = aS2;
420 TopoDS_Shape aNewShape1 = myS1;
421 TopoDS_Shape aNewShape2 = myS2;
422 TopTools_DataMapOfShapeListOfShape theMapOfChangedFaces;
424 Standard_Boolean aHasSDF = Standard_False;
425 anExp.Init(myS1, TopAbs_FACE);
426 for (; anExp.More(); anExp.Next()) {
427 TopoDS_Shape aFirstFace = anExp.Current();
429 if (!isAnalitic(aFirstFace))
432 if (QANewModTopOpe_Tools::HasSameDomain(myBuilder, aFirstFace)) {
434 if(!aHasSDF) aHasSDF = Standard_True;
436 TopTools_ListOfShape aLOfSDFace;
437 TopTools_ListIteratorOfListOfShape anIter;
439 QANewModTopOpe_Tools::SameDomain(myBuilder, aFirstFace, aLOfSDFace);
440 anIter.Initialize(aLOfSDFace);
442 for(; anIter.More(); anIter.Next()) {
443 TopoDS_Shape aSecondFace = anIter.Value();
445 if (!isAnalitic(aSecondFace))
448 if (!SubstitudeSDFaces(aFirstFace, aSecondFace,
449 aNewShape1, aNewShape2,
450 theMapOfChangedFaces))
456 if(myS1.IsSame(aNewShape1) && myS2.IsSame(aNewShape2)) return;
459 BRep_Builder aBuilder;
461 // aBuilder.MakeCompSolid(TopoDS::CompSolid(myShape));
462 aBuilder.MakeCompound(TopoDS::Compound(myShape));
464 aBuilder.Add(myShape, aNewShape1);
465 aBuilder.Add(myShape, aNewShape2);
467 TopTools_DataMapIteratorOfDataMapOfShapeListOfShape anIter(theMapOfChangedFaces);
468 for(; anIter.More(); anIter.Next()) {
469 myMapModif.Bind(anIter.Key(), anIter.Value());
472 //--------------- creation myMapGener for common faces
474 TopExp_Explorer anExp1, anExp2;
475 TopTools_MapOfShape aM;
476 anExp1.Init(aNewShape1, TopAbs_FACE);
477 for(; anExp1.More(); anExp1.Next()) {
478 const TopoDS_Shape& aF1 = anExp1.Current();
479 anExp2.Init(aNewShape2, TopAbs_FACE);
480 for(; anExp2.More(); anExp2.Next()) {
481 const TopoDS_Shape& aF2 = anExp2.Current();
482 if(aF1.IsSame(aF2)) {
488 anIter.Initialize(myMapModif);
489 TopTools_ListIteratorOfListOfShape anI1;
490 TopTools_MapIteratorOfMapOfShape anI2;
491 for(; anIter.More(); anIter.Next()) {
492 const TopoDS_Shape& aS = anIter.Key();
493 if(aS.ShapeType() == TopAbs_FACE) {
494 anI1.Initialize(anIter.Value());
495 for(; anI1.More(); anI1.Next()) {
496 const TopoDS_Shape& aSS1 = anI1.Value();
498 for(; anI2.More(); anI2.Next()) {
499 const TopoDS_Shape& aSS2 = anI2.Key();
500 if(aSS1.IsSame(aSS2)) {
501 if(!myMapGener.IsBound(aS)) {
502 // for Mandrake-10 - mkv,02.06.06 - myMapGener.Bind(aS, TopTools_ListOfShape());
503 TopTools_ListOfShape aListOfShape1;
504 myMapGener.Bind(aS, aListOfShape1);
506 myMapGener(aS).Append(aSS1);
507 myMapModif(aS).Remove(anI1);
510 if(!anI1.More()) break;
514 // if(anIter.Value().Extent() == 0) myMapModif.UnBind(aS);
518 //--------------- creation myMapGener for common edges
521 anExp1.Init(aNewShape1, TopAbs_EDGE);
522 for(; anExp1.More(); anExp1.Next()) {
523 const TopoDS_Shape& anE1 = anExp1.Current();
524 if(aM.Contains(anE1)) continue;
525 anExp2.Init(aNewShape2, TopAbs_EDGE);
526 for(; anExp2.More(); anExp2.Next()) {
527 const TopoDS_Shape& anE2 = anExp2.Current();
528 if(aM.Contains(anE2)) continue;
529 if(anE1.IsSame(anE2)) {
535 TopTools_MapOfShape aComVerMap;
536 TopTools_MapOfShape aLocVerMap;
538 anExp1.Init(myS1, TopAbs_VERTEX);
539 for(; anExp1.More(); anExp1.Next()) aComVerMap.Add(anExp1.Current());
540 anExp1.Init(myS2, TopAbs_VERTEX);
541 for(; anExp1.More(); anExp1.Next()) aComVerMap.Add(anExp1.Current());
543 TopTools_ListOfShape aShapesToRemove; // record items to be removed from the map (should be done after iteration)
544 anIter.Initialize(myMapModif);
545 for(; anIter.More(); anIter.Next()) {
546 const TopoDS_Shape& aS = anIter.Key();
547 if(aS.ShapeType() == TopAbs_EDGE) {
549 anI1.Initialize(anIter.Value());
550 for(; anI1.More(); anI1.Next()) {
551 const TopoDS_Shape& aSS1 = anI1.Value();
553 for(; anI2.More(); anI2.Next()) {
554 const TopoDS_Shape& aSS2 = anI2.Key();
555 if(aSS1.IsSame(aSS2)) {
556 if(!aS.IsSame(aSS1)) {
557 if(!myMapGener.IsBound(aS)) {
558 // for Mandrake-10 - mkv,02.06.06 - myMapGener.Bind(aS, TopTools_ListOfShape());
559 TopTools_ListOfShape aListOfShape2;
560 myMapGener.Bind(aS, aListOfShape2);
562 myMapGener(aS).Append(aSS1);
563 TopoDS_Vertex aV1, aV2;
564 TopExp::Vertices(TopoDS::Edge(aSS1), aV1, aV2);
565 if(!aComVerMap.Contains(aV1)) {
566 if(aLocVerMap.Add(aV1)) {
567 myMapGener(aS).Append(aV1);
570 if(!aComVerMap.Contains(aV2)) {
571 if(aLocVerMap.Add(aV2)) {
572 myMapGener(aS).Append(aV2);
575 myMapModif(aS).Remove(anI1);
578 aShapesToRemove.Append (aS);
582 if(!anI1.More()) break;
587 // remove items from the data map
588 for(TopTools_ListIteratorOfListOfShape anIt(aShapesToRemove); anIt.More(); anIt.Next())
589 myMapModif.UnBind(anIt.Value());
592 anExp1.Init(myShape, TopAbs_VERTEX);
593 for(; anExp1.More(); anExp1.Next()) {
594 const TopoDS_Shape& aV = anExp1.Current();
595 aComVerMap.Remove(aV);
598 anI2.Initialize(aComVerMap);
599 for(; anI2.More(); anI2.Next()) {
600 // for Mandrake-10 - mkv,02.06.06 - myMapModif.Bind(anI2.Key(), TopTools_ListOfShape());
601 TopTools_ListOfShape aListOfShape3;
602 myMapModif.Bind(anI2.Key(), aListOfShape3);