1 // Created on: 2009-05-05
2 // Created by: Sergey ZARITCHNY
3 // Copyright (c) 2009-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
17 #include <BRepAdaptor_Surface.hxx>
18 #include <BRepAlgoAPI_Common.hxx>
19 #include <BRepAlgoAPI_Cut.hxx>
20 #include <BRepAlgoAPI_Fuse.hxx>
21 #include <BRepAlgoAPI_Section.hxx>
22 #include <BRepCheck_Analyzer.hxx>
23 #include <BRepCheck_ListOfStatus.hxx>
24 #include <BRepCheck_Result.hxx>
25 #include <BRepLib.hxx>
26 #include <DNaming.hxx>
27 #include <DNaming_BooleanOperationDriver.hxx>
28 #include <GeomAbs_SurfaceType.hxx>
29 #include <ModelDefinitions.hxx>
30 #include <Precision.hxx>
31 #include <Standard_Real.hxx>
32 #include <Standard_Type.hxx>
33 #include <TDataStd_Integer.hxx>
34 #include <TDF_Label.hxx>
35 #include <TFunction_Function.hxx>
36 #include <TFunction_Logbook.hxx>
37 #include <TNaming.hxx>
38 #include <TNaming_Builder.hxx>
39 #include <TNaming_NamedShape.hxx>
41 #include <TopExp_Explorer.hxx>
43 #include <TopoDS_Iterator.hxx>
44 #include <TopoDS_Vertex.hxx>
45 #include <TopTools_IndexedMapOfShape.hxx>
46 #include <TopTools_MapOfShape.hxx>
48 IMPLEMENT_STANDARD_RTTIEXT(DNaming_BooleanOperationDriver,TFunction_Driver)
50 static Standard_Boolean FixSameParameter(const TopoDS_Shape& theShape,
51 BRepCheck_Analyzer& theAnalyzer,
52 const Standard_Boolean bIgnoreNotSPErrors = Standard_False );
53 static void FindSPErrorEdges(const TopoDS_Shape& theShape,
54 const BRepCheck_Analyzer& theAnalyzer,
55 TopTools_IndexedMapOfShape& theMap);
57 static Standard_Boolean FindOtherErrors(const TopoDS_Shape& theShape,
58 const BRepCheck_Analyzer& theAnalyzer,
59 const TopTools_IndexedMapOfShape& theMap);
61 //=======================================================================
62 //function : DNaming_BooleanOperationDriver
63 //purpose : Constructor
64 //=======================================================================
65 DNaming_BooleanOperationDriver::DNaming_BooleanOperationDriver()
68 //=======================================================================
70 //purpose : Validates labels of a function in <log>.
71 //=======================================================================
72 void DNaming_BooleanOperationDriver::Validate(Handle(TFunction_Logbook)&) const
75 //=======================================================================
76 //function : MustExecute
77 //purpose : Analyse in <log> if the loaded function must be executed
78 //=======================================================================
79 Standard_Boolean DNaming_BooleanOperationDriver::MustExecute(const Handle(TFunction_Logbook)&) const
84 //=======================================================================
86 //purpose : Execute the function and push in <log> the impacted labels
87 //=======================================================================
88 Standard_Integer DNaming_BooleanOperationDriver::Execute(Handle(TFunction_Logbook)& theLog) const
90 Handle(TFunction_Function) aFunction;
91 Label().FindAttribute(TFunction_Function::GetID(),aFunction);
92 if(aFunction.IsNull()) return -1;
94 // Handle(TDataStd_UAttribute) anObject = DNaming::GetObjectFromFunction(aFunction);
95 // if(anObject.IsNull()) return -1;
96 // Handle(TNaming_NamedShape) anObjectNS = DNaming::GetObjectValue(anObject);
97 Handle(TFunction_Function) aPrevFun = DNaming::GetPrevFunction(aFunction);
98 if(aPrevFun.IsNull()) return -1;
99 const TDF_Label& aLab = RESPOSITION(aPrevFun);
100 Handle(TNaming_NamedShape) anObjectNS;
101 aLab.FindAttribute(TNaming_NamedShape::GetID(), anObjectNS);
102 if (anObjectNS.IsNull() || anObjectNS->IsEmpty()) {
104 std::cout<<"BooleanOperationDriver:: Object is empty"<<std::endl;
106 aFunction->SetFailure(WRONG_ARGUMENT);
110 Handle(TDataStd_UAttribute) aToolObj = DNaming::GetObjectArg(aFunction,BOOL_TOOL);
111 Handle(TNaming_NamedShape) aToolNS = DNaming::GetObjectValue(aToolObj);
113 if (aToolNS.IsNull() || aToolNS->IsEmpty()) {
115 std::cout<<"BooleanOperationDriver:: Tool is empty"<<std::endl;
117 aFunction->SetFailure(WRONG_ARGUMENT);
121 TopoDS_Shape aTOOL = aToolNS->Get();
122 TopoDS_Shape anOBJECT = anObjectNS->Get();
123 if (aTOOL.IsNull() || anOBJECT.IsNull()) {
125 std::cout<<"BooleanOperationDriver:: Tool is null"<<std::endl;
127 aFunction->SetFailure(WRONG_ARGUMENT);
131 Standard_Boolean anIsDone = Standard_False;
134 if(aFunction->GetDriverGUID() == FUSE_GUID){
135 BRepAlgoAPI_Fuse aMkFuse (anOBJECT, aTOOL);
136 anIsDone = CheckAndLoad(aMkFuse, aFunction);
139 else if(aFunction->GetDriverGUID() == CUT_GUID){
140 BRepAlgoAPI_Cut aMkCut (anOBJECT, aTOOL);
141 anIsDone = CheckAndLoad(aMkCut, aFunction);
144 else if(aFunction->GetDriverGUID() == COMMON_GUID){
145 BRepAlgoAPI_Common aMkCom (anOBJECT, aTOOL);
146 anIsDone = CheckAndLoad(aMkCom, aFunction);
149 else if(aFunction->GetDriverGUID() == SECTION_GUID){
150 BRepAlgoAPI_Section aMkSect (anOBJECT, aTOOL);
151 anIsDone = CheckAndLoad(aMkSect, aFunction);
154 aFunction->SetFailure(UNSUPPORTED_FUNCTION);
157 if(!anIsDone) return -1;
159 theLog->SetValid(RESPOSITION(aFunction),Standard_True);
160 aFunction->SetFailure(DONE);
165 //===================================================================
166 //=======================================================================
167 //function : ShapeType
169 //=======================================================================
171 static TopAbs_ShapeEnum ShapeType(const TopoDS_Shape& theShape) {
172 TopAbs_ShapeEnum TypeSh = theShape.ShapeType();
173 if (TypeSh == TopAbs_COMPOUND || TypeSh == TopAbs_COMPSOLID) {
174 TopoDS_Iterator itr(theShape);
175 if (!itr.More()) return TypeSh;
176 TypeSh = ShapeType(itr.Value());
177 if(TypeSh == TopAbs_COMPOUND) return TypeSh;
179 for(; itr.More(); itr.Next())
180 if(ShapeType(itr.Value()) != TypeSh) return TopAbs_COMPOUND;
184 //=====================================================================
185 static Standard_Boolean IsValidSurfType(const TopoDS_Face& theFace) {
186 BRepAdaptor_Surface anAdapt(theFace);
187 Handle( Adaptor3d_Curve ) aBasisCurve;
188 const GeomAbs_SurfaceType& aType = anAdapt.GetType();
189 if(aType == GeomAbs_Sphere)
190 return Standard_True;
191 /* if(aType == GeomAbs_Cylinder || aType == GeomAbs_Cone || Type == GeomAbs_Sphere)
192 return Standard_True;
193 else if(aType == GeomAbs_SurfaceOfRevolution){
194 aBasisCurve = anAdapt.BasisCurve();
195 if (aBasisCurve->GetType() == GeomAbs_Line)
196 return Standard_True;
198 else if(aType == GeomAbs_SurfaceOfExtrusion) {
199 aBasisCurve = anAdapt.BasisCurve();
200 if (aBasisCurve->GetType() == GeomAbs_Circle || aBasisCurve->GetType() == GeomAbs_Ellipse)
201 return Standard_True;
205 //ModDbgTools_Write(theFace, "Surf");
207 return Standard_False;
209 //=======================================================================
210 //function : IsWRCase
212 //=======================================================================
214 static Standard_Boolean IsWRCase(const BRepAlgoAPI_BooleanOperation& MS) {
216 const TopoDS_Shape& ObjSh = MS.Shape1();
217 const TopoDS_Shape& ToolSh = MS.Shape2();
218 const TopAbs_ShapeEnum& Type1 = ShapeType(ObjSh);
219 if(Type1 == TopAbs_COMPOUND || Type1 > TopAbs_FACE) return Standard_False;
220 const TopAbs_ShapeEnum& Type2 = ShapeType(ToolSh);
221 if(Type2 == TopAbs_COMPOUND || Type2 > TopAbs_FACE) return Standard_False;
222 TopTools_ListOfShape aList;
224 if(Type1 != TopAbs_FACE) {
225 TopExp_Explorer anExp(ObjSh, TopAbs_FACE);
226 for(;anExp.More();anExp.Next()) {
227 if(IsValidSurfType(TopoDS::Face(anExp.Current())))
228 aList.Append(anExp.Current());
231 if(IsValidSurfType(TopoDS::Face(ObjSh)))
234 if(aList.Extent() == 0) {
235 if(Type2 != TopAbs_FACE) {
236 TopExp_Explorer anExp(ToolSh, TopAbs_FACE);
237 for(;anExp.More();anExp.Next()) {
238 if(IsValidSurfType(TopoDS::Face(anExp.Current())))
239 aList.Append(anExp.Current());
242 if(IsValidSurfType(TopoDS::Face(ToolSh)))
243 aList.Append(ToolSh);
245 if(aList.Extent() > 0) return Standard_True;
246 return Standard_False;
249 //=======================================================================
250 //function : LoadNamingDS
252 //=======================================================================
253 void DNaming_BooleanOperationDriver::LoadNamingDS (const TDF_Label& theResultLabel,
254 BRepAlgoAPI_BooleanOperation& MS) const
257 const TopoDS_Shape& ResSh = MS.Shape();
258 const TopoDS_Shape& ObjSh = MS.Shape1();
259 const TopoDS_Shape& ToolSh = MS.Shape2();
260 if (ResSh.IsNull()) {
262 std::cout<<"LoadFuseNamingDS: The result of the boolean operation is null"<<std::endl;
268 DNaming::LoadResult(theResultLabel, MS);
270 TopTools_DataMapOfShapeShape SubShapes;
271 TopExp_Explorer Exp(ResSh, TopAbs_FACE);
272 for (; Exp.More(); Exp.Next()) {
273 SubShapes.Bind(Exp.Current(),Exp.Current());
276 // Naming of modified faces:
277 TNaming_Builder modFB (theResultLabel.NewChild()); //FindChild(1,Standard_True));
278 DNaming::LoadAndOrientModifiedShapes (MS, ObjSh, TopAbs_FACE, modFB,SubShapes);
279 DNaming::LoadAndOrientModifiedShapes (MS, ToolSh, TopAbs_FACE, modFB, SubShapes);
281 // Naming of deleted faces:
283 TNaming_Builder delB (theResultLabel.NewChild()); // FindChild(2,Standard_True));
284 DNaming::LoadDeletedShapes (MS, ObjSh, TopAbs_FACE, delB);
285 DNaming::LoadDeletedShapes (MS, ToolSh, TopAbs_FACE, delB);
290 Exp.Init(ResSh, TopAbs_EDGE);
291 for (; Exp.More(); Exp.Next()) {
292 SubShapes.Bind(Exp.Current(),Exp.Current());
295 const TopTools_ListOfShape& aList = MS.SectionEdges();
296 Standard_Boolean theCase(Standard_False);
297 TopTools_MapOfShape aView;
298 if(aList.Extent() > 0 && aList.Extent() < 3)
299 theCase = Standard_True;
301 TopTools_ListIteratorOfListOfShape it(aList);
302 for(;it.More();it.Next()) {
303 TopoDS_Shape newShape = it.Value();
304 if (SubShapes.IsBound(newShape))
305 newShape.Orientation((SubShapes(newShape)).Orientation());
306 TNaming_Builder secED (theResultLabel.NewChild());
307 secED.Generated(newShape);
309 TopoDS_Vertex Vfirst, Vlast;
310 TopExp::Vertices(TopoDS::Edge(newShape), Vfirst, Vlast, Standard_True);
311 if(aView.Add(Vfirst)) {
312 TNaming_Builder secV (theResultLabel.NewChild());
313 secV.Generated(Vfirst);
315 if(aView.Add(Vlast)) {
316 TNaming_Builder secV (theResultLabel.NewChild());
317 secV.Generated(Vlast);
324 //=======================================================================
325 //function : LoadNamingDS
327 //=======================================================================
328 void DNaming_BooleanOperationDriver::LoadSectionNDS (const TDF_Label& theResultLabel,
329 BRepAlgoAPI_BooleanOperation& MS) const
332 const TopoDS_Shape& ResSh = MS.Shape();
333 const TopoDS_Shape& ObjSh = MS.Shape1();
334 const TopoDS_Shape& ToolSh = MS.Shape2();
335 if (ResSh.IsNull()) {
337 std::cout<<"LoadSectionNamingDS: The result of the boolean operation is null"<<std::endl;
343 DNaming::LoadResult(theResultLabel, MS);
345 TopTools_DataMapOfShapeShape SubShapes;
346 TopExp_Explorer Exp(ResSh, TopAbs_EDGE);
347 for (; Exp.More(); Exp.Next()) {
348 SubShapes.Bind(Exp.Current(),Exp.Current());
351 // Naming of modified faces:
352 TNaming_Builder genEdB (theResultLabel.NewChild()); //FindChild(1,Standard_True));
353 DNaming::LoadAndOrientGeneratedShapes (MS, ObjSh, TopAbs_FACE, genEdB,SubShapes);
354 DNaming::LoadAndOrientGeneratedShapes (MS, ToolSh, TopAbs_FACE, genEdB, SubShapes);
357 //=======================================================================
358 //function : CheckAndLoad
359 //purpose : checks result of operation and performs Topological Naming
360 //=======================================================================
361 Standard_Boolean DNaming_BooleanOperationDriver::CheckAndLoad
362 (BRepAlgoAPI_BooleanOperation& theMkOpe,
363 const Handle(TFunction_Function)& theFunction) const
366 if (theMkOpe.IsDone() && !theMkOpe.Shape().IsNull()) {
367 if (theMkOpe.Shape().ShapeType() == TopAbs_COMPOUND) {
368 if (theMkOpe.Shape().NbChildren() == 0) {
369 theFunction->SetFailure(NULL_RESULT);
370 return Standard_False;
373 BRepCheck_Analyzer aCheck (theMkOpe.Shape());
374 Standard_Boolean aResIsValid = Standard_True;
375 if(!aCheck.IsValid(theMkOpe.Shape()))
376 aResIsValid = FixSameParameter(theMkOpe.Shape(), aCheck);
378 if(theFunction->GetDriverGUID() == FUSE_GUID) {
379 LoadNamingDS(RESPOSITION(theFunction), theMkOpe);
381 else if(theFunction->GetDriverGUID() == CUT_GUID) {
382 LoadNamingDS(RESPOSITION(theFunction), theMkOpe); // the same naming only for case of solids
383 } else if(theFunction->GetDriverGUID() == COMMON_GUID) {
384 LoadNamingDS(RESPOSITION(theFunction), theMkOpe);
385 } else if(theFunction->GetDriverGUID() == SECTION_GUID) {
386 LoadSectionNDS(RESPOSITION(theFunction), theMkOpe);
389 theFunction->SetFailure(DONE);
390 return Standard_True;
392 theFunction->SetFailure(RESULT_NOT_VALID);
393 return Standard_False;
396 theFunction->SetFailure(ALGO_FAILED);
397 return Standard_False;
400 // ------------------------------------------------------------------------
401 // static function: FixSameParameter
403 // ------------------------------------------------------------------------
404 Standard_Boolean FixSameParameter(const TopoDS_Shape& theShape,
405 BRepCheck_Analyzer& theAnalyzer,
406 const Standard_Boolean bIgnoreNotSPErrors) {
408 Standard_Integer bDoFix = Standard_True;
409 TopTools_IndexedMapOfShape aMapE;
411 FindSPErrorEdges(theShape, theAnalyzer, aMapE);
413 if(!bIgnoreNotSPErrors) {
414 if(FindOtherErrors(theShape, theAnalyzer, aMapE)) {
415 bDoFix = Standard_False;
420 Standard_Integer i = 0;
422 for(i = 1; i <= aMapE.Extent(); i++) {
423 const TopoDS_Shape& aE = aMapE(i);
424 BRepLib::SameParameter(aE, Precision::Confusion(), Standard_True);
427 if(!aMapE.IsEmpty()) {
428 theAnalyzer.Init(theShape);
429 return theAnalyzer.IsValid();
432 return Standard_False;
435 // ------------------------------------------------------------------------
436 // static function: FindSPErrorEdges
438 // ------------------------------------------------------------------------
439 void FindSPErrorEdges(const TopoDS_Shape& theShape,
440 const BRepCheck_Analyzer& theAnalyzer,
441 TopTools_IndexedMapOfShape& theMap) {
442 BRepCheck_ListIteratorOfListOfStatus itl;
444 TopoDS_Iterator anIt(theShape);
446 for (; anIt.More(); anIt.Next()) {
447 FindSPErrorEdges(anIt.Value(), theAnalyzer, theMap);
450 if(theShape.ShapeType() == TopAbs_FACE) {
451 TopExp_Explorer anExpE(theShape, TopAbs_EDGE);
453 for(; anExpE.More(); anExpE.Next()) {
454 Handle(BRepCheck_Result) aResult = theAnalyzer.Result(anExpE.Current());
456 if(aResult.IsNull() || theMap.Contains(anExpE.Current()))
459 for (aResult->InitContextIterator();
460 aResult->MoreShapeInContext();
461 aResult->NextShapeInContext()) {
462 if (aResult->ContextualShape().IsSame(theShape)) {
463 itl.Initialize(aResult->StatusOnShape());
465 for(; itl.More(); itl.Next()) {
466 if((itl.Value() == BRepCheck_InvalidSameParameterFlag) ||
467 (itl.Value() == BRepCheck_InvalidCurveOnSurface)) {
468 theMap.Add(anExpE.Current());
476 else if(theShape.ShapeType() == TopAbs_EDGE) {
477 Handle(BRepCheck_Result) aResult = theAnalyzer.Result(theShape);
478 itl.Initialize(aResult->Status());
480 for(; itl.More(); itl.Next()) {
481 if((itl.Value() == BRepCheck_InvalidSameParameterFlag) ||
482 (itl.Value() == BRepCheck_InvalidCurveOnSurface)) {
483 theMap.Add(theShape);
490 // ------------------------------------------------------------------------
491 // static function: FindOtherErrors
493 // ------------------------------------------------------------------------
494 Standard_Boolean FindOtherErrors(const TopoDS_Shape& theShape,
495 const BRepCheck_Analyzer& theAnalyzer,
496 const TopTools_IndexedMapOfShape& theMap) {
498 Standard_Boolean bOtherFound = Standard_False;
499 BRepCheck_ListIteratorOfListOfStatus itl;
500 TopoDS_Iterator anIt(theShape);
502 for (; anIt.More(); anIt.Next()) {
503 if(FindOtherErrors(anIt.Value(), theAnalyzer, theMap))
504 return Standard_True;
506 Handle(BRepCheck_Result) aResult = theAnalyzer.Result(theShape);
508 if (!aResult.IsNull()) {
510 if(!theMap.Contains(theShape) && !aResult->Status().IsEmpty()) {
511 if(aResult->Status().First() != BRepCheck_NoError) {
512 bOtherFound = Standard_True;
515 TopExp_Explorer anExpF(theShape, TopAbs_FACE);
517 for(; anExpF.More(); anExpF.Next()) {
518 TopExp_Explorer anExpE(anExpF.Current(), TopAbs_EDGE);
520 for(; anExpE.More(); anExpE.Next()) {
521 Handle(BRepCheck_Result) aResultE = theAnalyzer.Result(anExpE.Current());
523 if(aResultE.IsNull())
525 bOtherFound = Standard_False;
527 for (aResultE->InitContextIterator();
528 aResultE->MoreShapeInContext();
529 aResultE->NextShapeInContext()) {
531 if (aResultE->ContextualShape().IsSame(anExpF.Current()) ||
532 aResultE->ContextualShape().IsSame(theShape)) {
533 itl.Initialize(aResultE->StatusOnShape());
538 if(itl.Value() != BRepCheck_NoError) {
539 if(theMap.Contains(anExpE.Current())) {
540 for(; itl.More(); itl.Next()) {
542 if((itl.Value() != BRepCheck_InvalidSameParameterFlag) &&
543 (itl.Value() != BRepCheck_InvalidCurveOnSurface) &&
544 (itl.Value() != BRepCheck_NoError)) {
545 return Standard_True;
550 return Standard_True;
560 for (aResult->InitContextIterator();
561 !bOtherFound && aResult->MoreShapeInContext();
562 aResult->NextShapeInContext()) {
563 if(!aResult->StatusOnShape().IsEmpty()) {
564 bOtherFound = (aResult->StatusOnShape().First() != BRepCheck_NoError);
570 TopAbs_ShapeEnum aType = theShape.ShapeType();
572 if((aType == TopAbs_VERTEX) ||
573 (aType == TopAbs_EDGE) ||
574 (aType == TopAbs_WIRE) ||
575 (aType == TopAbs_FACE) ||
576 (aType == TopAbs_SHELL)) {
577 for (aResult->InitContextIterator();
578 aResult->MoreShapeInContext();
579 aResult->NextShapeInContext()) {
580 if(!aResult->StatusOnShape().IsEmpty()) {
581 if(aResult->StatusOnShape().First() != BRepCheck_NoError) {
582 return Standard_True;
590 itl.Initialize(aResult->Status());
592 for(; itl.More(); itl.Next()) {
593 if((itl.Value() != BRepCheck_InvalidSameParameterFlag) &&
594 (itl.Value() != BRepCheck_InvalidCurveOnSurface) &&
595 (itl.Value() != BRepCheck_NoError)) {
596 return Standard_True;