1 // Created on: 2009-05-05
2 // Created by: Sergey ZARITCHNY
3 // Copyright (c) 2009-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.
22 #include <DNaming_BooleanOperationDriver.ixx>
23 #include <TFunction_Function.hxx>
24 #include <TDataStd_Real.hxx>
25 #include <TDataStd_Integer.hxx>
26 #include <TFunction_Logbook.hxx>
27 #include <TNaming.hxx>
28 #include <TNaming_NamedShape.hxx>
29 #include <BRepCheck_Analyzer.hxx>
30 #include <TopLoc_Location.hxx>
32 #include <TopoDS_Solid.hxx>
33 #include <TopoDS_Vertex.hxx>
34 #include <Standard_GUID.hxx>
35 #include <Standard_Real.hxx>
36 #include <TDF_Label.hxx>
37 #include <ModelDefinitions.hxx>
39 #include <DNaming.hxx>
40 #include <TNaming_Builder.hxx>
41 #include <BRepAlgoAPI_Fuse.hxx>
42 #include <BRepAlgoAPI_Cut.hxx>
43 #include <BRepAlgoAPI_Common.hxx>
44 #include <TopoDS_Iterator.hxx>
45 #include <TopTools_MapOfShape.hxx>
46 #include <TopExp_Explorer.hxx>
48 #include <TopTools_ListIteratorOfListOfShape.hxx>
49 #include <TopTools_IndexedMapOfShape.hxx>
50 #include <BRepLib.hxx>
51 #include <Precision.hxx>
52 #include <BRepCheck_ListIteratorOfListOfStatus.hxx>
53 #include <BRepCheck_Result.hxx>
54 #include <BRepCheck_ListOfStatus.hxx>
55 #include <BRepAdaptor_Surface.hxx>
56 #include <Adaptor3d_HCurve.hxx>
57 #include <GeomAbs_SurfaceType.hxx>
59 static Standard_Boolean FixSameParameter(const TopoDS_Shape& theShape,
60 BRepCheck_Analyzer& theAnalyzer,
61 const Standard_Boolean bIgnoreNotSPErrors = Standard_False );
62 static void FindSPErrorEdges(const TopoDS_Shape& theShape,
63 const BRepCheck_Analyzer& theAnalyzer,
64 TopTools_IndexedMapOfShape& theMap);
66 static Standard_Boolean FindOtherErrors(const TopoDS_Shape& theShape,
67 const BRepCheck_Analyzer& theAnalyzer,
68 const TopTools_IndexedMapOfShape& theMap);
70 //=======================================================================
71 //function : DNaming_BooleanOperationDriver
72 //purpose : Constructor
73 //=======================================================================
74 DNaming_BooleanOperationDriver::DNaming_BooleanOperationDriver()
77 //=======================================================================
79 //purpose : Validates labels of a function in <log>.
80 //=======================================================================
81 void DNaming_BooleanOperationDriver::Validate(TFunction_Logbook& theLog) const
84 //=======================================================================
85 //function : MustExecute
86 //purpose : Analyse in <log> if the loaded function must be executed
87 //=======================================================================
88 Standard_Boolean DNaming_BooleanOperationDriver::MustExecute(const TFunction_Logbook& theLog) const
93 //=======================================================================
95 //purpose : Execute the function and push in <log> the impacted labels
96 //=======================================================================
97 Standard_Integer DNaming_BooleanOperationDriver::Execute(TFunction_Logbook& theLog) const
99 Handle(TFunction_Function) aFunction;
100 Label().FindAttribute(TFunction_Function::GetID(),aFunction);
101 if(aFunction.IsNull()) return -1;
103 // Handle(TDataStd_UAttribute) anObject = DNaming::GetObjectFromFunction(aFunction);
104 // if(anObject.IsNull()) return -1;
105 // Handle(TNaming_NamedShape) anObjectNS = DNaming::GetObjectValue(anObject);
106 Handle(TFunction_Function) aPrevFun = DNaming::GetPrevFunction(aFunction);
107 if(aPrevFun.IsNull()) return -1;
108 const TDF_Label& aLab = RESPOSITION(aPrevFun);
109 Handle(TNaming_NamedShape) anObjectNS;
110 aLab.FindAttribute(TNaming_NamedShape::GetID(), anObjectNS);
111 if (anObjectNS.IsNull() || anObjectNS->IsEmpty()) {
113 cout<<"BooleanOperationDriver:: Object is empty"<<endl;
115 aFunction->SetFailure(WRONG_ARGUMENT);
119 Handle(TDataStd_UAttribute) aToolObj = DNaming::GetObjectArg(aFunction,BOOL_TOOL);
120 Handle(TNaming_NamedShape) aToolNS = DNaming::GetObjectValue(aToolObj);
122 if (aToolNS.IsNull() || aToolNS->IsEmpty()) {
124 cout<<"BooleanOperationDriver:: Tool is empty"<<endl;
126 aFunction->SetFailure(WRONG_ARGUMENT);
130 TopoDS_Shape aTOOL = aToolNS->Get();
131 TopoDS_Shape anOBJECT = anObjectNS->Get();
132 if (aTOOL.IsNull() || anOBJECT.IsNull()) {
134 cout<<"BooleanOperationDriver:: Tool is null"<<endl;
136 aFunction->SetFailure(WRONG_ARGUMENT);
140 Standard_Boolean anIsDone = Standard_False;
143 if(aFunction->GetDriverGUID() == FUSE_GUID){
144 BRepAlgoAPI_Fuse aMkFuse (anOBJECT, aTOOL);
145 anIsDone = CheckAndLoad(aMkFuse, aFunction);
148 else if(aFunction->GetDriverGUID() == CUT_GUID){
149 BRepAlgoAPI_Cut aMkCut (anOBJECT, aTOOL);
150 anIsDone = CheckAndLoad(aMkCut, aFunction);
153 else if(aFunction->GetDriverGUID() == COMMON_GUID){
154 BRepAlgoAPI_Common aMkCom (anOBJECT, aTOOL);
155 anIsDone = CheckAndLoad(aMkCom, aFunction);
158 aFunction->SetFailure(UNSUPPORTED_FUNCTION);
161 if(!anIsDone) return -1;
163 theLog.SetValid(RESPOSITION(aFunction),Standard_True);
164 aFunction->SetFailure(DONE);
169 //===================================================================
170 //=======================================================================
171 //function : ShapeType
173 //=======================================================================
175 static TopAbs_ShapeEnum ShapeType(const TopoDS_Shape& theShape) {
176 TopAbs_ShapeEnum TypeSh = theShape.ShapeType();
177 if (TypeSh == TopAbs_COMPOUND || TypeSh == TopAbs_COMPSOLID) {
178 TopoDS_Iterator itr(theShape);
179 if (!itr.More()) return TypeSh;
180 TypeSh = ShapeType(itr.Value());
181 if(TypeSh == TopAbs_COMPOUND) return TypeSh;
183 for(; itr.More(); itr.Next())
184 if(ShapeType(itr.Value()) != TypeSh) return TopAbs_COMPOUND;
188 //=====================================================================
189 static Standard_Boolean IsValidSurfType(const TopoDS_Face& theFace) {
190 BRepAdaptor_Surface anAdapt(theFace);
191 Handle( Adaptor3d_HCurve ) aBasisCurve;
192 const GeomAbs_SurfaceType& aType = anAdapt.GetType();
193 if(aType == GeomAbs_Sphere)
194 return Standard_True;
195 /* if(aType == GeomAbs_Cylinder || aType == GeomAbs_Cone || Type == GeomAbs_Sphere)
196 return Standard_True;
197 else if(aType == GeomAbs_SurfaceOfRevolution){
198 aBasisCurve = anAdapt.BasisCurve();
199 if (aBasisCurve->GetType() == GeomAbs_Line)
200 return Standard_True;
202 else if(aType == GeomAbs_SurfaceOfExtrusion) {
203 aBasisCurve = anAdapt.BasisCurve();
204 if (aBasisCurve->GetType() == GeomAbs_Circle || aBasisCurve->GetType() == GeomAbs_Ellipse)
205 return Standard_True;
209 //ModDbgTools_Write(theFace, "Surf");
211 return Standard_False;
213 //=======================================================================
214 //function : IsWRCase
216 //=======================================================================
218 static Standard_Boolean IsWRCase(const BRepAlgoAPI_BooleanOperation& MS) {
220 const TopoDS_Shape& ObjSh = MS.Shape1();
221 const TopoDS_Shape& ToolSh = MS.Shape2();
222 const TopAbs_ShapeEnum& Type1 = ShapeType(ObjSh);
223 if(Type1 == TopAbs_COMPOUND || Type1 > TopAbs_FACE) return Standard_False;
224 const TopAbs_ShapeEnum& Type2 = ShapeType(ToolSh);
225 if(Type2 == TopAbs_COMPOUND || Type2 > TopAbs_FACE) return Standard_False;
226 TopTools_ListOfShape aList;
228 if(Type1 != TopAbs_FACE) {
229 TopExp_Explorer anExp(ObjSh, TopAbs_FACE);
230 for(;anExp.More();anExp.Next()) {
231 if(IsValidSurfType(TopoDS::Face(anExp.Current())))
232 aList.Append(anExp.Current());
235 if(IsValidSurfType(TopoDS::Face(ObjSh)))
238 if(aList.Extent() == 0) {
239 if(Type2 != TopAbs_FACE) {
240 TopExp_Explorer anExp(ToolSh, TopAbs_FACE);
241 for(;anExp.More();anExp.Next()) {
242 if(IsValidSurfType(TopoDS::Face(anExp.Current())))
243 aList.Append(anExp.Current());
246 if(IsValidSurfType(TopoDS::Face(ToolSh)))
247 aList.Append(ToolSh);
249 if(aList.Extent() > 0) return Standard_True;
250 return Standard_False;
253 //=======================================================================
254 //function : LoadNamingDS
256 //=======================================================================
257 void DNaming_BooleanOperationDriver::LoadNamingDS (const TDF_Label& theResultLabel,
258 BRepAlgoAPI_BooleanOperation& MS) const
261 const TopoDS_Shape& ResSh = MS.Shape();
262 const TopoDS_Shape& ObjSh = MS.Shape1();
263 const TopoDS_Shape& ToolSh = MS.Shape2();
264 if (ResSh.IsNull()) {
266 cout<<"LoadFuseNamingDS: The result of the boolean operation is null"<<endl;
272 DNaming::LoadResult(theResultLabel, MS);
274 TopTools_DataMapOfShapeShape SubShapes;
275 TopExp_Explorer Exp(ResSh, TopAbs_FACE);
276 for (; Exp.More(); Exp.Next()) {
277 SubShapes.Bind(Exp.Current(),Exp.Current());
280 // Naming of modified faces:
281 TNaming_Builder modFB (theResultLabel.NewChild()); //FindChild(1,Standard_True));
282 DNaming::LoadAndOrientModifiedShapes (MS, ObjSh, TopAbs_FACE, modFB,SubShapes);
283 DNaming::LoadAndOrientModifiedShapes (MS, ToolSh, TopAbs_FACE, modFB, SubShapes);
285 // Naming of deleted faces:
287 TNaming_Builder delB (theResultLabel.NewChild()); // FindChild(2,Standard_True));
288 DNaming::LoadDeletedShapes (MS, ObjSh, TopAbs_FACE, delB);
289 DNaming::LoadDeletedShapes (MS, ToolSh, TopAbs_FACE, delB);
294 Exp.Init(ResSh, TopAbs_EDGE);
295 for (; Exp.More(); Exp.Next()) {
296 SubShapes.Bind(Exp.Current(),Exp.Current());
299 const TopTools_ListOfShape& aList = MS.SectionEdges();
300 Standard_Boolean theCase(Standard_False);
301 TopTools_MapOfShape aView;
302 if(aList.Extent() > 0 && aList.Extent() < 3)
303 theCase = Standard_True;
305 TopTools_ListIteratorOfListOfShape it(aList);
306 for(;it.More();it.Next()) {
307 TopoDS_Shape newShape = it.Value();
308 if (SubShapes.IsBound(newShape))
309 newShape.Orientation((SubShapes(newShape)).Orientation());
310 TNaming_Builder secED (theResultLabel.NewChild());
311 secED.Generated(newShape);
313 TopoDS_Vertex Vfirst, Vlast;
314 TopExp::Vertices(TopoDS::Edge(newShape), Vfirst, Vlast, Standard_True);
315 if(aView.Add(Vfirst)) {
316 TNaming_Builder secV (theResultLabel.NewChild());
317 secV.Generated(Vfirst);
319 if(aView.Add(Vlast)) {
320 TNaming_Builder secV (theResultLabel.NewChild());
321 secV.Generated(Vlast);
328 //=======================================================================
329 //function : CheckAndLoad
330 //purpose : checks result of operation and performs Topological Naming
331 //=======================================================================
332 Standard_Boolean DNaming_BooleanOperationDriver::CheckAndLoad
333 (BRepAlgoAPI_BooleanOperation& theMkOpe,
334 const Handle(TFunction_Function)& theFunction) const
337 if (theMkOpe.IsDone() && !theMkOpe.Shape().IsNull()) {
339 Standard_CString aFileName = "BoolOp.brep";
340 Write(theMkOpe.Shape(), aFileName);
342 if (theMkOpe.Shape().ShapeType() == TopAbs_COMPOUND) {
343 TopoDS_Iterator anItr(theMkOpe.Shape());
345 theFunction->SetFailure(NULL_RESULT);
346 return Standard_False;
349 BRepCheck_Analyzer aCheck (theMkOpe.Shape());
350 Standard_Boolean aResIsValid = Standard_True;
351 if(!aCheck.IsValid(theMkOpe.Shape()))
352 aResIsValid = FixSameParameter(theMkOpe.Shape(), aCheck);
354 if(theFunction->GetDriverGUID() == FUSE_GUID) {
355 LoadNamingDS(RESPOSITION(theFunction), theMkOpe);
357 else if(theFunction->GetDriverGUID() == CUT_GUID) {
358 LoadNamingDS(RESPOSITION(theFunction), theMkOpe); // the same naming only for case of solids
359 } else if(theFunction->GetDriverGUID() == COMMON_GUID) {
360 LoadNamingDS(RESPOSITION(theFunction), theMkOpe);
363 theFunction->SetFailure(DONE);
364 return Standard_True;
366 theFunction->SetFailure(RESULT_NOT_VALID);
367 return Standard_False;
370 theFunction->SetFailure(ALGO_FAILED);
371 return Standard_False;
374 // ------------------------------------------------------------------------
375 // static function: FixSameParameter
377 // ------------------------------------------------------------------------
378 Standard_Boolean FixSameParameter(const TopoDS_Shape& theShape,
379 BRepCheck_Analyzer& theAnalyzer,
380 const Standard_Boolean bIgnoreNotSPErrors) {
382 Standard_Integer bDoFix = Standard_True;
383 TopTools_IndexedMapOfShape aMapE;
385 FindSPErrorEdges(theShape, theAnalyzer, aMapE);
387 if(!bIgnoreNotSPErrors) {
388 if(FindOtherErrors(theShape, theAnalyzer, aMapE)) {
389 bDoFix = Standard_False;
394 Standard_Integer i = 0;
396 for(i = 1; i <= aMapE.Extent(); i++) {
397 const TopoDS_Shape& aE = aMapE(i);
398 BRepLib::SameParameter(aE, Precision::Confusion(), Standard_True);
401 if(!aMapE.IsEmpty()) {
402 theAnalyzer.Init(theShape);
403 return theAnalyzer.IsValid();
406 return Standard_False;
409 // ------------------------------------------------------------------------
410 // static function: FindSPErrorEdges
412 // ------------------------------------------------------------------------
413 void FindSPErrorEdges(const TopoDS_Shape& theShape,
414 const BRepCheck_Analyzer& theAnalyzer,
415 TopTools_IndexedMapOfShape& theMap) {
416 BRepCheck_ListIteratorOfListOfStatus itl;
418 TopoDS_Iterator anIt(theShape);
420 for (; anIt.More(); anIt.Next()) {
421 FindSPErrorEdges(anIt.Value(), theAnalyzer, theMap);
424 if(theShape.ShapeType() == TopAbs_FACE) {
425 TopExp_Explorer anExpE(theShape, TopAbs_EDGE);
427 for(; anExpE.More(); anExpE.Next()) {
428 Handle(BRepCheck_Result) aResult = theAnalyzer.Result(anExpE.Current());
430 if(aResult.IsNull() || theMap.Contains(anExpE.Current()))
433 for (aResult->InitContextIterator();
434 aResult->MoreShapeInContext();
435 aResult->NextShapeInContext()) {
436 if (aResult->ContextualShape().IsSame(theShape)) {
437 itl.Initialize(aResult->StatusOnShape());
439 for(; itl.More(); itl.Next()) {
440 if((itl.Value() == BRepCheck_InvalidSameParameterFlag) ||
441 (itl.Value() == BRepCheck_InvalidCurveOnSurface)) {
442 theMap.Add(anExpE.Current());
450 else if(theShape.ShapeType() == TopAbs_EDGE) {
451 Handle(BRepCheck_Result) aResult = theAnalyzer.Result(theShape);
452 itl.Initialize(aResult->Status());
454 for(; itl.More(); itl.Next()) {
455 if((itl.Value() == BRepCheck_InvalidSameParameterFlag) ||
456 (itl.Value() == BRepCheck_InvalidCurveOnSurface)) {
457 theMap.Add(theShape);
464 // ------------------------------------------------------------------------
465 // static function: FindOtherErrors
467 // ------------------------------------------------------------------------
468 Standard_Boolean FindOtherErrors(const TopoDS_Shape& theShape,
469 const BRepCheck_Analyzer& theAnalyzer,
470 const TopTools_IndexedMapOfShape& theMap) {
472 Standard_Boolean bOtherFound = Standard_False;
473 BRepCheck_ListIteratorOfListOfStatus itl;
474 TopoDS_Iterator anIt(theShape);
476 for (; anIt.More(); anIt.Next()) {
477 if(FindOtherErrors(anIt.Value(), theAnalyzer, theMap))
478 return Standard_True;
480 Handle(BRepCheck_Result) aResult = theAnalyzer.Result(theShape);
482 if (!aResult.IsNull()) {
484 if(!theMap.Contains(theShape) && !aResult->Status().IsEmpty()) {
485 if(aResult->Status().First() != BRepCheck_NoError) {
486 bOtherFound = Standard_True;
489 TopExp_Explorer anExpF(theShape, TopAbs_FACE);
491 for(; anExpF.More(); anExpF.Next()) {
492 TopExp_Explorer anExpE(anExpF.Current(), TopAbs_EDGE);
494 for(; anExpE.More(); anExpE.Next()) {
495 Handle(BRepCheck_Result) aResultE = theAnalyzer.Result(anExpE.Current());
497 if(aResultE.IsNull())
499 bOtherFound = Standard_False;
501 for (aResultE->InitContextIterator();
502 aResultE->MoreShapeInContext();
503 aResultE->NextShapeInContext()) {
505 if (aResultE->ContextualShape().IsSame(anExpF.Current()) ||
506 aResultE->ContextualShape().IsSame(theShape)) {
507 itl.Initialize(aResultE->StatusOnShape());
512 if(itl.Value() != BRepCheck_NoError) {
513 if(theMap.Contains(anExpE.Current())) {
514 for(; itl.More(); itl.Next()) {
516 if((itl.Value() != BRepCheck_InvalidSameParameterFlag) &&
517 (itl.Value() != BRepCheck_InvalidCurveOnSurface) &&
518 (itl.Value() != BRepCheck_NoError)) {
519 return Standard_True;
524 return Standard_True;
534 for (aResult->InitContextIterator();
535 !bOtherFound && aResult->MoreShapeInContext();
536 aResult->NextShapeInContext()) {
537 if(!aResult->StatusOnShape().IsEmpty()) {
538 bOtherFound = (aResult->StatusOnShape().First() != BRepCheck_NoError);
544 TopAbs_ShapeEnum aType = theShape.ShapeType();
546 if((aType == TopAbs_VERTEX) ||
547 (aType == TopAbs_EDGE) ||
548 (aType == TopAbs_WIRE) ||
549 (aType == TopAbs_FACE) ||
550 (aType == TopAbs_SHELL)) {
551 for (aResult->InitContextIterator();
552 aResult->MoreShapeInContext();
553 aResult->NextShapeInContext()) {
554 if(!aResult->StatusOnShape().IsEmpty()) {
555 if(aResult->StatusOnShape().First() != BRepCheck_NoError) {
556 return Standard_True;
564 itl.Initialize(aResult->Status());
566 for(; itl.More(); itl.Next()) {
567 if((itl.Value() != BRepCheck_InvalidSameParameterFlag) &&
568 (itl.Value() != BRepCheck_InvalidCurveOnSurface) &&
569 (itl.Value() != BRepCheck_NoError)) {
570 return Standard_True;