Back to index

salome-geom  6.5.0
GEOMImpl_BooleanDriver.cxx
Go to the documentation of this file.
00001 // Copyright (C) 2007-2012  CEA/DEN, EDF R&D, OPEN CASCADE
00002 //
00003 // Copyright (C) 2003-2007  OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
00004 // CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
00005 //
00006 // This library is free software; you can redistribute it and/or
00007 // modify it under the terms of the GNU Lesser General Public
00008 // License as published by the Free Software Foundation; either
00009 // version 2.1 of the License.
00010 //
00011 // This library is distributed in the hope that it will be useful,
00012 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00013 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014 // Lesser General Public License for more details.
00015 //
00016 // You should have received a copy of the GNU Lesser General Public
00017 // License along with this library; if not, write to the Free Software
00018 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00019 //
00020 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
00021 //
00022 
00023 #include <GEOMImpl_BooleanDriver.hxx>
00024 #include <GEOMImpl_IBoolean.hxx>
00025 #include <GEOMImpl_Types.hxx>
00026 #include <GEOMImpl_GlueDriver.hxx>
00027 #include <GEOM_Function.hxx>
00028 
00029 #include <TNaming_CopyShape.hxx>
00030 
00031 #include <ShapeFix_ShapeTolerance.hxx>
00032 #include <ShapeFix_Shape.hxx>
00033 
00034 #include <BRep_Builder.hxx>
00035 #include <BRepAlgo.hxx>
00036 #include <BRepAlgoAPI_Common.hxx>
00037 #include <BRepAlgoAPI_Cut.hxx>
00038 #include <BRepAlgoAPI_Fuse.hxx>
00039 #include <BRepAlgoAPI_Section.hxx>
00040 #include <BRepCheck_Analyzer.hxx>
00041 
00042 #include <TopExp_Explorer.hxx>
00043 #include <TopoDS_Shape.hxx>
00044 #include <TopoDS_Compound.hxx>
00045 #include <TopoDS_Iterator.hxx>
00046 #include <TopTools_MapOfShape.hxx>
00047 #include <TopTools_ListOfShape.hxx>
00048 #include <TopTools_ListIteratorOfListOfShape.hxx>
00049 
00050 #include <TColStd_IndexedDataMapOfTransientTransient.hxx>
00051 
00052 #include <Precision.hxx>
00053 
00054 #include <Standard_ConstructionError.hxx>
00055 #include <StdFail_NotDone.hxx>
00056 
00057 //=======================================================================
00058 //function : GetID
00059 //purpose  :
00060 //=======================================================================
00061 const Standard_GUID& GEOMImpl_BooleanDriver::GetID()
00062 {
00063   static Standard_GUID aBooleanDriver("FF1BBB21-5D14-4df2-980B-3A668264EA16");
00064   return aBooleanDriver;
00065 }
00066 
00067 //=======================================================================
00068 //function : GEOMImpl_BooleanDriver
00069 //purpose  :
00070 //=======================================================================
00071 GEOMImpl_BooleanDriver::GEOMImpl_BooleanDriver()
00072 {
00073 }
00074 
00075 void AddSimpleShapes(TopoDS_Shape theShape, TopTools_ListOfShape& theList)
00076 {
00077   if (theShape.ShapeType() != TopAbs_COMPOUND &&
00078       theShape.ShapeType() != TopAbs_COMPSOLID) {
00079     theList.Append(theShape);
00080     return;
00081   }
00082 
00083   TopTools_MapOfShape mapShape;
00084   TopoDS_Iterator It (theShape, Standard_True, Standard_True);
00085 
00086   for (; It.More(); It.Next()) {
00087     TopoDS_Shape aShape_i = It.Value();
00088     if (mapShape.Add(aShape_i)) {
00089       if (aShape_i.ShapeType() == TopAbs_COMPOUND ||
00090           aShape_i.ShapeType() == TopAbs_COMPSOLID) {
00091         AddSimpleShapes(aShape_i, theList);
00092       } else {
00093         theList.Append(aShape_i);
00094       }
00095     }
00096   }
00097 }
00098 
00099 //=======================================================================
00100 //function : Execute
00101 //purpose  :
00102 //=======================================================================
00103 Standard_Integer GEOMImpl_BooleanDriver::Execute (TFunction_Logbook& log) const
00104 {
00105   if (Label().IsNull()) return 0;
00106   Handle(GEOM_Function) aFunction = GEOM_Function::GetFunction(Label());
00107 
00108   GEOMImpl_IBoolean aCI (aFunction);
00109   Standard_Integer aType = aFunction->GetType();
00110 
00111   TopoDS_Shape aShape;
00112 
00113   Handle(GEOM_Function) aRefShape1 = aCI.GetShape1();
00114   Handle(GEOM_Function) aRefShape2 = aCI.GetShape2();
00115   TopoDS_Shape aShape1 = aRefShape1->GetValue();
00116   TopoDS_Shape aShape2 = aRefShape2->GetValue();
00117 
00118   if (!aShape1.IsNull() && !aShape2.IsNull()) {
00119     // check arguments for Mantis issue 0021019
00120     BRepCheck_Analyzer ana (aShape1, Standard_True);
00121     if (!ana.IsValid())
00122       StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid");
00123     ana.Init(aShape2);
00124     if (!ana.IsValid())
00125       StdFail_NotDone::Raise("Boolean operation will not be performed, because argument shape is not valid");
00126 
00127     // perform COMMON operation
00128     if (aType == BOOLEAN_COMMON) {
00129       BRep_Builder B;
00130       TopoDS_Compound C;
00131       B.MakeCompound(C);
00132 
00133       TopTools_ListOfShape listShape1, listShape2;
00134       AddSimpleShapes(aShape1, listShape1);
00135       AddSimpleShapes(aShape2, listShape2);
00136 
00137       Standard_Boolean isCompound =
00138         (listShape1.Extent() > 1 || listShape2.Extent() > 1);
00139 
00140       TopTools_ListIteratorOfListOfShape itSub1 (listShape1);
00141       for (; itSub1.More(); itSub1.Next()) {
00142         TopoDS_Shape aValue1 = itSub1.Value();
00143         TopTools_ListIteratorOfListOfShape itSub2 (listShape2);
00144         for (; itSub2.More(); itSub2.Next()) {
00145           TopoDS_Shape aValue2 = itSub2.Value();
00146           BRepAlgoAPI_Common BO (aValue1, aValue2);
00147           if (!BO.IsDone()) {
00148             StdFail_NotDone::Raise("Common operation can not be performed on the given shapes");
00149           }
00150           if (isCompound) {
00151             TopoDS_Shape aStepResult = BO.Shape();
00152 
00153             // check result of this step: if it is a compound (boolean operations
00154             // allways return a compound), we add all sub-shapes of it.
00155             // This allows to avoid adding empty compounds,
00156             // resulting from COMMON on two non-intersecting shapes.
00157             if (aStepResult.ShapeType() == TopAbs_COMPOUND) {
00158               TopoDS_Iterator aCompIter (aStepResult);
00159               for (; aCompIter.More(); aCompIter.Next()) {
00160                 // add shape in a result
00161                 B.Add(C, aCompIter.Value());
00162               }
00163             }
00164             else {
00165               // add shape in a result
00166               B.Add(C, aStepResult);
00167             }
00168           }
00169           else
00170             aShape = BO.Shape();
00171         }
00172       }
00173 
00174       if (isCompound) {
00175         /*
00176         TopTools_ListOfShape listShapeC;
00177         AddSimpleShapes(C, listShapeC);
00178         TopTools_ListIteratorOfListOfShape itSubC (listShapeC);
00179         bool isOnlySolids = true;
00180         for (; itSubC.More(); itSubC.Next()) {
00181           TopoDS_Shape aValueC = itSubC.Value();
00182           if (aValueC.ShapeType() != TopAbs_SOLID) isOnlySolids = false;
00183         }
00184         if (isOnlySolids)
00185           aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion());
00186         else
00187           aShape = C;
00188         */
00189 
00190         // As GlueFaces has been improved to keep all kind of shapes
00191         TopExp_Explorer anExp (C, TopAbs_VERTEX);
00192         if (anExp.More())
00193           aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion(), Standard_True);
00194         else
00195           aShape = C;
00196       }
00197     }
00198 
00199     // perform CUT operation
00200     else if (aType == BOOLEAN_CUT) {
00201       BRep_Builder B;
00202       TopoDS_Compound C;
00203       B.MakeCompound(C);
00204 
00205       TopTools_ListOfShape listShapes, listTools;
00206       AddSimpleShapes(aShape1, listShapes);
00207       AddSimpleShapes(aShape2, listTools);
00208 
00209       Standard_Boolean isCompound = (listShapes.Extent() > 1);
00210 
00211       TopTools_ListIteratorOfListOfShape itSub1 (listShapes);
00212       for (; itSub1.More(); itSub1.Next()) {
00213         TopoDS_Shape aCut = itSub1.Value();
00214         // tools
00215         TopTools_ListIteratorOfListOfShape itSub2 (listTools);
00216         for (; itSub2.More(); itSub2.Next()) {
00217           TopoDS_Shape aTool = itSub2.Value();
00218           BRepAlgoAPI_Cut BO (aCut, aTool);
00219           if (!BO.IsDone()) {
00220             StdFail_NotDone::Raise("Cut operation can not be performed on the given shapes");
00221           }
00222           aCut = BO.Shape();
00223         }
00224         if (isCompound) {
00225           // check result of this step: if it is a compound (boolean operations
00226           // allways return a compound), we add all sub-shapes of it.
00227           // This allows to avoid adding empty compounds,
00228           // resulting from CUT of parts
00229           if (aCut.ShapeType() == TopAbs_COMPOUND) {
00230             TopoDS_Iterator aCompIter (aCut);
00231             for (; aCompIter.More(); aCompIter.Next()) {
00232               // add shape in a result
00233               B.Add(C, aCompIter.Value());
00234             }
00235           }
00236           else {
00237             // add shape in a result
00238             B.Add(C, aCut);
00239           }
00240         }
00241         else
00242           aShape = aCut;
00243       }
00244 
00245       if (isCompound) {
00246         /*
00247         TopTools_ListOfShape listShapeC;
00248         AddSimpleShapes(C, listShapeC);
00249         TopTools_ListIteratorOfListOfShape itSubC (listShapeC);
00250         bool isOnlySolids = true;
00251         for (; itSubC.More(); itSubC.Next()) {
00252           TopoDS_Shape aValueC = itSubC.Value();
00253           if (aValueC.ShapeType() != TopAbs_SOLID) isOnlySolids = false;
00254         }
00255         if (isOnlySolids)
00256           aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion());
00257         else
00258           aShape = C;
00259         */
00260 
00261         // As GlueFaces has been improved to keep all kind of shapes
00262         TopExp_Explorer anExp (C, TopAbs_VERTEX);
00263         if (anExp.More())
00264           aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion(), Standard_True);
00265         else
00266           aShape = C;
00267       }
00268     }
00269 
00270     // perform FUSE operation
00271     else if (aType == BOOLEAN_FUSE) {
00272       /* Fix for NPAL15379: refused
00273       // Check arguments
00274       TopTools_ListOfShape listShape1, listShape2;
00275       AddSimpleShapes(aShape1, listShape1);
00276       AddSimpleShapes(aShape2, listShape2);
00277 
00278       Standard_Boolean isIntersect = Standard_False;
00279 
00280       if (listShape1.Extent() > 1 && !isIntersect) {
00281         // check intersections inside the first compound
00282         TopTools_ListIteratorOfListOfShape it1 (listShape1);
00283         for (; it1.More() && !isIntersect; it1.Next()) {
00284           TopoDS_Shape aValue1 = it1.Value();
00285           TopTools_ListIteratorOfListOfShape it2 (listShape1);
00286           for (; it2.More() && !isIntersect; it2.Next()) {
00287             TopoDS_Shape aValue2 = it2.Value();
00288             if (aValue2 != aValue1) {
00289               BRepAlgoAPI_Section BO (aValue1, aValue2);
00290               if (BO.IsDone()) {
00291                 TopoDS_Shape aSect = BO.Shape();
00292                 TopExp_Explorer anExp (aSect, TopAbs_EDGE);
00293                 if (anExp.More()) {
00294                   isIntersect = Standard_True;
00295                 }
00296               }
00297             }
00298           }
00299         }
00300       }
00301 
00302       if (listShape2.Extent() > 1 && !isIntersect) {
00303         // check intersections inside the second compound
00304         TopTools_ListIteratorOfListOfShape it1 (listShape2);
00305         for (; it1.More() && !isIntersect; it1.Next()) {
00306           TopoDS_Shape aValue1 = it1.Value();
00307           TopTools_ListIteratorOfListOfShape it2 (listShape2);
00308           for (; it2.More() && !isIntersect; it2.Next()) {
00309             TopoDS_Shape aValue2 = it2.Value();
00310             if (aValue2 != aValue1) {
00311               BRepAlgoAPI_Section BO (aValue1, aValue2);
00312               if (BO.IsDone()) {
00313                 TopoDS_Shape aSect = BO.Shape();
00314                 TopExp_Explorer anExp (aSect, TopAbs_EDGE);
00315                 if (anExp.More()) {
00316                   isIntersect = Standard_True;
00317                 }
00318               }
00319             }
00320           }
00321         }
00322       }
00323 
00324       if (isIntersect) {
00325         // have intersections inside compounds
00326         // check intersections between compounds
00327         TopTools_ListIteratorOfListOfShape it1 (listShape1);
00328         for (; it1.More(); it1.Next()) {
00329           TopoDS_Shape aValue1 = it1.Value();
00330           TopTools_ListIteratorOfListOfShape it2 (listShape2);
00331           for (; it2.More(); it2.Next()) {
00332             TopoDS_Shape aValue2 = it2.Value();
00333             if (aValue2 != aValue1) {
00334               BRepAlgoAPI_Section BO (aValue1, aValue2);
00335               if (BO.IsDone()) {
00336                 TopoDS_Shape aSect = BO.Shape();
00337                 TopExp_Explorer anExp (aSect, TopAbs_EDGE);
00338                 if (anExp.More()) {
00339                   StdFail_NotDone::Raise("Bad argument for Fuse: compound with intersecting sub-shapes");
00340                 }
00341               }
00342             }
00343           }
00344         }
00345       }
00346       */
00347 
00348       // Perform
00349       BRepAlgoAPI_Fuse BO (aShape1, aShape2);
00350       if (!BO.IsDone()) {
00351         StdFail_NotDone::Raise("Fuse operation can not be performed on the given shapes");
00352       }
00353       aShape = BO.Shape();
00354     }
00355 
00356     // perform SECTION operation
00357     else if (aType == BOOLEAN_SECTION) {
00358       BRep_Builder B;
00359       TopoDS_Compound C;
00360       B.MakeCompound(C);
00361 
00362       TopTools_ListOfShape listShape1, listShape2;
00363       AddSimpleShapes(aShape1, listShape1);
00364       AddSimpleShapes(aShape2, listShape2);
00365 
00366       Standard_Boolean isCompound =
00367         (listShape1.Extent() > 1 || listShape2.Extent() > 1);
00368 
00369       TopTools_ListIteratorOfListOfShape itSub1 (listShape1);
00370       for (; itSub1.More(); itSub1.Next()) {
00371         TopoDS_Shape aValue1 = itSub1.Value();
00372         TopTools_ListIteratorOfListOfShape itSub2 (listShape2);
00373         for (; itSub2.More(); itSub2.Next()) {
00374           TopoDS_Shape aValue2 = itSub2.Value();
00375           BRepAlgoAPI_Section BO (aValue1, aValue2, Standard_False);
00376           // Set approximation to have an attached 3D BSpline geometry to each edge,
00377           // where analytic curve is not possible. Without this flag in some cases
00378           // we obtain BSpline curve of degree 1 (C0), which is slowly
00379           // processed by some algorithms (Partition for example).
00380           BO.Approximation(Standard_True);
00381          //modified by NIZNHY-PKV Tue Oct 18 14:34:16 2011f
00382          BO.ComputePCurveOn1(Standard_True);
00383          BO.ComputePCurveOn2(Standard_True);
00384          //modified by NIZNHY-PKV Tue Oct 18 14:34:18 2011t
00385          
00386           BO.Build();
00387           if (!BO.IsDone()) {
00388             StdFail_NotDone::Raise("Section operation can not be performed on the given shapes");
00389           }
00390           if (isCompound) {
00391             TopoDS_Shape aStepResult = BO.Shape();
00392 
00393             // check result of this step: if it is a compound (boolean operations
00394             // allways return a compound), we add all sub-shapes of it.
00395             // This allows to avoid adding empty compounds,
00396             // resulting from SECTION on two non-intersecting shapes.
00397             if (aStepResult.ShapeType() == TopAbs_COMPOUND) {
00398               TopoDS_Iterator aCompIter (aStepResult);
00399               for (; aCompIter.More(); aCompIter.Next()) {
00400                 // add shape in a result
00401                 B.Add(C, aCompIter.Value());
00402               }
00403             }
00404             else {
00405               // add shape in a result
00406               B.Add(C, aStepResult);
00407             }
00408           }
00409           else
00410             aShape = BO.Shape();
00411         }
00412       }
00413 
00414       if (isCompound) {
00415         //aShape = C;
00416 
00417         // As GlueFaces has been improved to keep all kind of shapes
00418         TopExp_Explorer anExp (C, TopAbs_VERTEX);
00419         if (anExp.More())
00420           aShape = GEOMImpl_GlueDriver::GlueFaces(C, Precision::Confusion(), Standard_True);
00421         else
00422           aShape = C;
00423       }
00424     }
00425 
00426     // UNKNOWN operation
00427     else {
00428     }
00429   }
00430 
00431   if (aShape.IsNull()) return 0;
00432 
00433   // as boolean operations always produce compound, lets simplify it
00434   // for the case, if it contains only one sub-shape
00435   TopTools_ListOfShape listShapeRes;
00436   AddSimpleShapes(aShape, listShapeRes);
00437   if (listShapeRes.Extent() == 1) {
00438     aShape = listShapeRes.First();
00439     if (aShape.IsNull()) return 0;
00440   }
00441 
00442   // 08.07.2008 skl for bug 19761 from Mantis
00443   BRepCheck_Analyzer ana (aShape, Standard_True);
00444   ana.Init(aShape);
00445   if (!ana.IsValid()) {
00446     ShapeFix_ShapeTolerance aSFT;
00447     aSFT.LimitTolerance(aShape, Precision::Confusion(),
00448                         Precision::Confusion(), TopAbs_SHAPE);
00449     Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape(aShape);
00450     aSfs->Perform();
00451     aShape = aSfs->Shape();
00452     ana.Init(aShape);
00453     if (!ana.IsValid())
00454       Standard_ConstructionError::Raise("Boolean operation aborted : non valid shape result");
00455   }
00456   //if (!BRepAlgo::IsValid(aShape)) {
00457   //  Standard_ConstructionError::Raise("Boolean operation aborted : non valid shape result");
00458   //}
00459 
00460   // BEGIN: Mantis issue 0021060: always limit tolerance of BOP result
00461   // 1. Get shape parameters for comparison
00462   int nbTypes [TopAbs_SHAPE];
00463   {
00464     for (int iType = 0; iType < TopAbs_SHAPE; ++iType)
00465       nbTypes[iType] = 0;
00466     nbTypes[aShape.ShapeType()]++;
00467 
00468     TopTools_MapOfShape aMapOfShape;
00469     aMapOfShape.Add(aShape);
00470     TopTools_ListOfShape aListOfShape;
00471     aListOfShape.Append(aShape);
00472 
00473     TopTools_ListIteratorOfListOfShape itL (aListOfShape);
00474     for (; itL.More(); itL.Next()) {
00475       TopoDS_Iterator it (itL.Value());
00476       for (; it.More(); it.Next()) {
00477         TopoDS_Shape s = it.Value();
00478         if (aMapOfShape.Add(s)) {
00479           aListOfShape.Append(s);
00480           nbTypes[s.ShapeType()]++;
00481         }
00482       }
00483     }
00484   }
00485 
00486   // 2. Limit tolerance
00487   TopoDS_Shape aShapeCopy;
00488   TColStd_IndexedDataMapOfTransientTransient aMapTShapes;
00489   TNaming_CopyShape::CopyTool(aShape, aMapTShapes, aShapeCopy);
00490   ShapeFix_ShapeTolerance aSFT;
00491   aSFT.LimitTolerance(aShapeCopy, Precision::Confusion(), Precision::Confusion(), TopAbs_SHAPE);
00492   Handle(ShapeFix_Shape) aSfs = new ShapeFix_Shape (aShapeCopy);
00493   aSfs->Perform();
00494   aShapeCopy = aSfs->Shape();
00495 
00496   // 3. Check parameters
00497   ana.Init(aShapeCopy);
00498   if (ana.IsValid()) {
00499     int iType, nbTypesCopy [TopAbs_SHAPE];
00500 
00501     for (iType = 0; iType < TopAbs_SHAPE; ++iType)
00502       nbTypesCopy[iType] = 0;
00503     nbTypesCopy[aShapeCopy.ShapeType()]++;
00504 
00505     TopTools_MapOfShape aMapOfShape;
00506     aMapOfShape.Add(aShapeCopy);
00507     TopTools_ListOfShape aListOfShape;
00508     aListOfShape.Append(aShapeCopy);
00509 
00510     TopTools_ListIteratorOfListOfShape itL (aListOfShape);
00511     for (; itL.More(); itL.Next()) {
00512       TopoDS_Iterator it (itL.Value());
00513       for (; it.More(); it.Next()) {
00514         TopoDS_Shape s = it.Value();
00515         if (aMapOfShape.Add(s)) {
00516           aListOfShape.Append(s);
00517           nbTypesCopy[s.ShapeType()]++;
00518         }
00519       }
00520     }
00521 
00522     bool isEqual = true;
00523     for (iType = 0; iType < TopAbs_SHAPE && isEqual; ++iType) {
00524       if (nbTypes[iType] != nbTypesCopy[iType])
00525         isEqual = false;
00526     }
00527     if (isEqual)
00528       aShape = aShapeCopy;
00529   }
00530   // END: Mantis issue 0021060
00531 
00532   //Alternative case to check shape result Mantis 0020604: EDF 1172
00533 /*  TopoDS_Iterator It (aShape, Standard_True, Standard_True);
00534   int nbSubshapes=0;
00535   for (; It.More(); It.Next())
00536     nbSubshapes++;
00537   if (!nbSubshapes)
00538     Standard_ConstructionError::Raise("Boolean operation aborted : result object is empty compound");*/
00539   //end of 0020604: EDF 1172
00541 
00542   aFunction->SetValue(aShape);
00543 
00544   log.SetTouched(Label());
00545 
00546   return 1;
00547 }
00548 
00549 
00550 //=======================================================================
00551 //function :  GEOMImpl_BooleanDriver_Type_
00552 //purpose  :
00553 //=======================================================================
00554 Standard_EXPORT Handle_Standard_Type& GEOMImpl_BooleanDriver_Type_()
00555 {
00556   static Handle_Standard_Type aType1 = STANDARD_TYPE(TFunction_Driver);
00557   if ( aType1.IsNull()) aType1 = STANDARD_TYPE(TFunction_Driver);
00558   static Handle_Standard_Type aType2 = STANDARD_TYPE(MMgt_TShared);
00559   if ( aType2.IsNull()) aType2 = STANDARD_TYPE(MMgt_TShared);
00560   static Handle_Standard_Type aType3 = STANDARD_TYPE(Standard_Transient);
00561   if ( aType3.IsNull()) aType3 = STANDARD_TYPE(Standard_Transient);
00562 
00563   static Handle_Standard_Transient _Ancestors[]= {aType1,aType2,aType3,NULL};
00564   static Handle_Standard_Type _aType = new Standard_Type("GEOMImpl_BooleanDriver",
00565                                                          sizeof(GEOMImpl_BooleanDriver),
00566                                                          1,
00567                                                          (Standard_Address)_Ancestors,
00568                                                          (Standard_Address)NULL);
00569 
00570   return _aType;
00571 }
00572 
00573 //=======================================================================
00574 //function : DownCast
00575 //purpose  :
00576 //=======================================================================
00577 const Handle(GEOMImpl_BooleanDriver) Handle(GEOMImpl_BooleanDriver)::DownCast(const Handle(Standard_Transient)& AnObject)
00578 {
00579   Handle(GEOMImpl_BooleanDriver) _anOtherObject;
00580 
00581   if (!AnObject.IsNull()) {
00582     if (AnObject->IsKind(STANDARD_TYPE(GEOMImpl_BooleanDriver))) {
00583       _anOtherObject = Handle(GEOMImpl_BooleanDriver)((Handle(GEOMImpl_BooleanDriver)&)AnObject);
00584     }
00585   }
00586 
00587   return _anOtherObject;
00588 }