Back to index

salome-geom  6.5.0
GEOMImpl_IBlocksOperations.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 #ifdef WNT
00024 #pragma warning( disable:4786 )
00025 #endif
00026 
00027 #include <Standard_Stream.hxx>
00028 
00029 #include <GEOMImpl_IBlocksOperations.hxx>
00030 
00031 #include <GEOMImpl_Types.hxx>
00032 
00033 #include <GEOMImpl_BlockDriver.hxx>
00034 #include <GEOMImpl_IBlocks.hxx>
00035 #include <GEOMImpl_IBlockTrsf.hxx>
00036 #include <GEOMImpl_CopyDriver.hxx>
00037 #include <GEOMImpl_Block6Explorer.hxx>
00038 #include <GEOMImpl_IShapesOperations.hxx>
00039 
00040 #include <GEOM_Function.hxx>
00041 #include <GEOM_PythonDump.hxx>
00042 
00043 #include <GEOMAlgo_GlueAnalyser.hxx>
00044 #include <GEOMAlgo_CoupleOfShapes.hxx>
00045 #include <GEOMAlgo_ListOfCoupleOfShapes.hxx>
00046 #include <GEOMAlgo_ListIteratorOfListOfCoupleOfShapes.hxx>
00047 #include <BlockFix_CheckTool.hxx>
00048 
00049 #include <Basics_OCCTVersion.hxx>
00050 
00051 #include "utilities.h"
00052 #include <OpUtil.hxx>
00053 #include <Utils_ExceptHandlers.hxx>
00054 
00055 #include <TFunction_DriverTable.hxx>
00056 #include <TFunction_Driver.hxx>
00057 #include <TFunction_Logbook.hxx>
00058 #include <TDataStd_Integer.hxx>
00059 #include <TDF_Tool.hxx>
00060 
00061 #include <BRep_Tool.hxx>
00062 #include <BRep_Builder.hxx>
00063 #include <BRepTools.hxx>
00064 #include <BRepTools_WireExplorer.hxx>
00065 #include <BRepGProp.hxx>
00066 #include <BRepBndLib.hxx>
00067 #include <BRepAdaptor_Surface.hxx>
00068 #include <BRepClass_FaceClassifier.hxx>
00069 #include <BRepClass3d_SolidClassifier.hxx>
00070 #include <BRepExtrema_DistShapeShape.hxx>
00071 
00072 #include <TopAbs.hxx>
00073 #include <TopoDS.hxx>
00074 #include <TopoDS_Edge.hxx>
00075 #include <TopoDS_Vertex.hxx>
00076 #include <TopoDS_Compound.hxx>
00077 #include <TopoDS_Iterator.hxx>
00078 #include <TopExp.hxx>
00079 #include <TopExp_Explorer.hxx>
00080 #include <TopTools_MapOfShape.hxx>
00081 #include <TopTools_Array1OfShape.hxx>
00082 #include <TopTools_IndexedMapOfShape.hxx>
00083 #include <TopTools_DataMapOfShapeInteger.hxx>
00084 #include <TopTools_ListIteratorOfListOfShape.hxx>
00085 #include <TopTools_IndexedDataMapOfShapeListOfShape.hxx>
00086 #include <TopTools_DataMapIteratorOfDataMapOfShapeInteger.hxx>
00087 
00088 #include <Bnd_Box.hxx>
00089 #include <GProp_GProps.hxx>
00090 
00091 #include <Geom_Surface.hxx>
00092 #include <ShapeAnalysis_Surface.hxx>
00093 
00094 #include <TColStd_MapOfInteger.hxx>
00095 #include <TColStd_Array1OfReal.hxx>
00096 #include <TColStd_Array1OfInteger.hxx>
00097 #include <TColStd_Array2OfInteger.hxx>
00098 
00099 //#include <OSD_Timer.hxx>
00100 
00101 #include <Precision.hxx>
00102 
00103 #include <Standard_Failure.hxx>
00104 #include <Standard_ErrorHandler.hxx> // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC
00105 
00106 //=============================================================================
00110 //=============================================================================
00111 GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations (GEOM_Engine* theEngine, int theDocID)
00112 : GEOM_IOperations(theEngine, theDocID)
00113 {
00114   MESSAGE("GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations");
00115 }
00116 
00117 //=============================================================================
00121 //=============================================================================
00122 GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations()
00123 {
00124   MESSAGE("GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations");
00125 }
00126 
00127 
00128 //=============================================================================
00132 //=============================================================================
00133 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad
00134                      (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2,
00135                       Handle(GEOM_Object) theEdge3, Handle(GEOM_Object) theEdge4)
00136 {
00137   SetErrorCode(KO);
00138 
00139   if (theEdge1.IsNull() || theEdge2.IsNull() ||
00140       theEdge3.IsNull() || theEdge4.IsNull()) return NULL;
00141 
00142   //Add a new Face object
00143   Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
00144 
00145   //Add a new Face function
00146   Handle(GEOM_Function) aFunction =
00147     aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_EDGES);
00148 
00149   //Check if the function is set correctly
00150   if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
00151 
00152   GEOMImpl_IBlocks aPI (aFunction);
00153 
00154   Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
00155   Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
00156   Handle(GEOM_Function) aRef3 = theEdge3->GetLastFunction();
00157   Handle(GEOM_Function) aRef4 = theEdge4->GetLastFunction();
00158   if (aRef1.IsNull() || aRef2.IsNull() ||
00159       aRef3.IsNull() || aRef4.IsNull()) return NULL;
00160 
00161   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
00162   aShapesSeq->Append(aRef1);
00163   aShapesSeq->Append(aRef2);
00164   aShapesSeq->Append(aRef3);
00165   aShapesSeq->Append(aRef4);
00166 
00167   aPI.SetShapes(aShapesSeq);
00168 
00169   //Compute the Face value
00170   try {
00171 #if OCC_VERSION_LARGE > 0x06010000
00172     OCC_CATCH_SIGNALS;
00173 #endif
00174     if (!GetSolver()->ComputeFunction(aFunction)) {
00175       SetErrorCode("Block driver failed to compute a face");
00176       return NULL;
00177     }
00178   }
00179   catch (Standard_Failure) {
00180     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
00181     SetErrorCode(aFail->GetMessageString());
00182     return NULL;
00183   }
00184 
00185   //Make a Python command
00186   GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad("
00187     << theEdge1 << ", " << theEdge2 << ", " << theEdge3 << ", " << theEdge4 << ")";
00188 
00189   SetErrorCode(OK);
00190   return aFace;
00191 }
00192 
00193 //=============================================================================
00197 //=============================================================================
00198 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad2Edges
00199                      (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2)
00200 {
00201   SetErrorCode(KO);
00202 
00203   if (theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
00204 
00205   //Add a new Face object
00206   Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
00207 
00208   //Add a new Face function
00209   Handle(GEOM_Function) aFunction =
00210     aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_TWO_EDGES);
00211 
00212   //Check if the function is set correctly
00213   if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
00214 
00215   GEOMImpl_IBlocks aPI (aFunction);
00216 
00217   Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction();
00218   Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction();
00219   if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
00220 
00221   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
00222   aShapesSeq->Append(aRef1);
00223   aShapesSeq->Append(aRef2);
00224 
00225   aPI.SetShapes(aShapesSeq);
00226 
00227   //Compute the Face value
00228   try {
00229 #if OCC_VERSION_LARGE > 0x06010000
00230     OCC_CATCH_SIGNALS;
00231 #endif
00232     if (!GetSolver()->ComputeFunction(aFunction)) {
00233       SetErrorCode("Block driver failed to compute a face");
00234       return NULL;
00235     }
00236   }
00237   catch (Standard_Failure) {
00238     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
00239     SetErrorCode(aFail->GetMessageString());
00240     return NULL;
00241   }
00242 
00243   //Make a Python command
00244   GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad2Edges("
00245                                << theEdge1 << ", " << theEdge2 << ")";
00246 
00247   SetErrorCode(OK);
00248   return aFace;
00249 }
00250 
00251 //=============================================================================
00255 //=============================================================================
00256 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad4Vertices
00257                      (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2,
00258                       Handle(GEOM_Object) thePnt3, Handle(GEOM_Object) thePnt4)
00259 {
00260   SetErrorCode(KO);
00261 
00262   if (thePnt1.IsNull() || thePnt2.IsNull() ||
00263       thePnt3.IsNull() || thePnt4.IsNull()) return NULL;
00264 
00265   //Add a new Face object
00266   Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE);
00267 
00268   //Add a new Face function
00269   Handle(GEOM_Function) aFunction =
00270     aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_PNT);
00271 
00272   //Check if the function is set correctly
00273   if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
00274 
00275   GEOMImpl_IBlocks aPI (aFunction);
00276 
00277   Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction();
00278   Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction();
00279   Handle(GEOM_Function) aRef3 = thePnt3->GetLastFunction();
00280   Handle(GEOM_Function) aRef4 = thePnt4->GetLastFunction();
00281   if (aRef1.IsNull() || aRef2.IsNull() ||
00282       aRef3.IsNull() || aRef4.IsNull()) return NULL;
00283 
00284   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
00285   aShapesSeq->Append(aRef1);
00286   aShapesSeq->Append(aRef2);
00287   aShapesSeq->Append(aRef3);
00288   aShapesSeq->Append(aRef4);
00289 
00290   aPI.SetShapes(aShapesSeq);
00291 
00292   //Compute the Face value
00293   try {
00294 #if OCC_VERSION_LARGE > 0x06010000
00295     OCC_CATCH_SIGNALS;
00296 #endif
00297     if (!GetSolver()->ComputeFunction(aFunction)) {
00298       SetErrorCode("Block driver failed to compute a face");
00299       return NULL;
00300     }
00301   }
00302   catch (Standard_Failure) {
00303     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
00304     SetErrorCode(aFail->GetMessageString());
00305     return NULL;
00306   }
00307 
00308   //Make a Python command
00309   GEOM::TPythonDump(aFunction) << aFace << " = geompy.MakeQuad4Vertices("
00310     << thePnt1 << ", " << thePnt2 << ", " << thePnt3 << ", " << thePnt4 << ")";
00311 
00312   SetErrorCode(OK);
00313   return aFace;
00314 }
00315 
00316 //=============================================================================
00320 //=============================================================================
00321 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa
00322                      (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2,
00323                       Handle(GEOM_Object) theFace3, Handle(GEOM_Object) theFace4,
00324                       Handle(GEOM_Object) theFace5, Handle(GEOM_Object) theFace6)
00325 {
00326   SetErrorCode(KO);
00327 
00328   if (theFace1.IsNull() || theFace2.IsNull() ||
00329       theFace3.IsNull() || theFace4.IsNull() ||
00330       theFace5.IsNull() || theFace6.IsNull()) return NULL;
00331 
00332   //Add a new Solid object
00333   Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
00334 
00335   //Add a new Block function
00336   Handle(GEOM_Function) aFunction =
00337     aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_SIX_FACES);
00338 
00339   //Check if the function is set correctly
00340   if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
00341 
00342   GEOMImpl_IBlocks aPI (aFunction);
00343 
00344   Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
00345   Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
00346   Handle(GEOM_Function) aRef3 = theFace3->GetLastFunction();
00347   Handle(GEOM_Function) aRef4 = theFace4->GetLastFunction();
00348   Handle(GEOM_Function) aRef5 = theFace5->GetLastFunction();
00349   Handle(GEOM_Function) aRef6 = theFace6->GetLastFunction();
00350   if (aRef1.IsNull() || aRef2.IsNull() ||
00351       aRef3.IsNull() || aRef4.IsNull() ||
00352       aRef5.IsNull() || aRef6.IsNull()) return NULL;
00353 
00354   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
00355   aShapesSeq->Append(aRef1);
00356   aShapesSeq->Append(aRef2);
00357   aShapesSeq->Append(aRef3);
00358   aShapesSeq->Append(aRef4);
00359   aShapesSeq->Append(aRef5);
00360   aShapesSeq->Append(aRef6);
00361 
00362   aPI.SetShapes(aShapesSeq);
00363 
00364   //Compute the Block value
00365   try {
00366 #if OCC_VERSION_LARGE > 0x06010000
00367     OCC_CATCH_SIGNALS;
00368 #endif
00369     if (!GetSolver()->ComputeFunction(aFunction)) {
00370       SetErrorCode("Block driver failed to compute a block");
00371       return NULL;
00372     }
00373   }
00374   catch (Standard_Failure) {
00375     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
00376     SetErrorCode(aFail->GetMessageString());
00377     return NULL;
00378   }
00379 
00380   //Make a Python command
00381   GEOM::TPythonDump(aFunction) << aBlock << " = geompy.MakeHexa("
00382     << theFace1 << ", " << theFace2 << ", " << theFace3 << ", "
00383       << theFace4 << ", " << theFace5 << ", " << theFace6 << ")";
00384 
00385   SetErrorCode(OK);
00386   return aBlock;
00387 }
00388 
00389 //=============================================================================
00393 //=============================================================================
00394 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa2Faces
00395                    (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2)
00396 {
00397   SetErrorCode(KO);
00398 
00399   if (theFace1.IsNull() || theFace2.IsNull()) return NULL;
00400 
00401   //Add a new Solid object
00402   Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK);
00403 
00404   //Add a new Block function
00405   Handle(GEOM_Function) aFunction =
00406     aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_TWO_FACES);
00407 
00408   //Check if the function is set correctly
00409   if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
00410 
00411   GEOMImpl_IBlocks aPI (aFunction);
00412 
00413   Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction();
00414   Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction();
00415   if (aRef1.IsNull() || aRef2.IsNull()) return NULL;
00416 
00417   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
00418   aShapesSeq->Append(aRef1);
00419   aShapesSeq->Append(aRef2);
00420 
00421   aPI.SetShapes(aShapesSeq);
00422 
00423   //Compute the Block value
00424   try {
00425 #if OCC_VERSION_LARGE > 0x06010000
00426     OCC_CATCH_SIGNALS;
00427 #endif
00428     if (!GetSolver()->ComputeFunction(aFunction)) {
00429       SetErrorCode("Block driver failed to compute a block");
00430       return NULL;
00431     }
00432   }
00433   catch (Standard_Failure) {
00434     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
00435     SetErrorCode(aFail->GetMessageString());
00436     return NULL;
00437   }
00438 
00439   //Make a Python command
00440   GEOM::TPythonDump(aFunction) << aBlock << " = geompy.MakeHexa2Faces("
00441                                << theFace1 << ", " << theFace2 << ")";
00442 
00443   SetErrorCode(OK);
00444   return aBlock;
00445 }
00446 
00447 //=============================================================================
00451 //=============================================================================
00452 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeBlockCompound
00453                                               (Handle(GEOM_Object) theCompound)
00454 {
00455   SetErrorCode(KO);
00456 
00457   if (theCompound.IsNull()) return NULL;
00458 
00459   //Add a new object
00460   Handle(GEOM_Object) aBlockComp = GetEngine()->AddObject(GetDocID(), GEOM_COMPOUND);
00461 
00462   //Add a new BlocksComp function
00463   Handle(GEOM_Function) aFunction =
00464     aBlockComp->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_GLUE);
00465 
00466   //Check if the function is set correctly
00467   if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
00468 
00469   GEOMImpl_IBlocks aPI (aFunction);
00470 
00471   Handle(GEOM_Function) aRef1 = theCompound->GetLastFunction();
00472   if (aRef1.IsNull()) return NULL;
00473 
00474   Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient;
00475   aShapesSeq->Append(aRef1);
00476 
00477   aPI.SetShapes(aShapesSeq);
00478 
00479   //Compute the Blocks Compound value
00480   try {
00481 #if OCC_VERSION_LARGE > 0x06010000
00482     OCC_CATCH_SIGNALS;
00483 #endif
00484     if (!GetSolver()->ComputeFunction(aFunction)) {
00485       SetErrorCode("Block driver failed to compute a blocks compound");
00486       return NULL;
00487     }
00488   }
00489   catch (Standard_Failure) {
00490     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
00491     SetErrorCode(aFail->GetMessageString());
00492     return NULL;
00493   }
00494 
00495   //Make a Python command
00496   GEOM::TPythonDump(aFunction) << aBlockComp
00497     << " = geompy.MakeBlockCompound(" << theCompound << ")";
00498 
00499   SetErrorCode(OK);
00500   return aBlockComp;
00501 }
00502 
00503 //=============================================================================
00507 //=============================================================================
00508 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetPoint
00509                                                (Handle(GEOM_Object) theShape,
00510                                                 const Standard_Real theX,
00511                                                 const Standard_Real theY,
00512                                                 const Standard_Real theZ,
00513                                                 const Standard_Real theEpsilon)
00514 {
00515   SetErrorCode(KO);
00516 
00517   //New Point object
00518   Handle(GEOM_Object) aResult;
00519 
00520   // Arguments
00521   if (theShape.IsNull()) return NULL;
00522 
00523   TopoDS_Shape aBlockOrComp = theShape->GetValue();
00524   if (aBlockOrComp.IsNull()) {
00525     SetErrorCode("Given shape is null");
00526     return NULL;
00527   }
00528 
00529   //Compute the Vertex value
00530   gp_Pnt P (theX, theY, theZ);
00531   Standard_Real eps = Max(theEpsilon, Precision::Confusion());
00532 
00533   TopoDS_Shape V;
00534   Standard_Integer isFound = 0;
00535   TopTools_MapOfShape mapShape;
00536   TopExp_Explorer exp (aBlockOrComp, TopAbs_VERTEX);
00537 
00538   for (; exp.More(); exp.Next()) {
00539     if (mapShape.Add(exp.Current())) {
00540       TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
00541       gp_Pnt aPi = BRep_Tool::Pnt(aVi);
00542       if (aPi.Distance(P) < eps) {
00543         V = aVi;
00544         isFound++;
00545       }
00546     }
00547   }
00548 
00549   if (isFound == 0) {
00550     SetErrorCode("Vertex has not been found");
00551     return NULL;
00552   } else if (isFound > 1) {
00553     SetErrorCode("Multiple vertices found by the given coordinates and epsilon");
00554     return NULL;
00555   } else {
00556     TopTools_IndexedMapOfShape anIndices;
00557     TopExp::MapShapes(aBlockOrComp, anIndices);
00558     Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
00559     anArray->SetValue(1, anIndices.FindIndex(V));
00560     aResult = GetEngine()->AddSubShape(theShape, anArray);
00561   }
00562 
00563   //The GetPoint() doesn't change object so no new function is required.
00564   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
00565 
00566   //Make a Python command
00567   GEOM::TPythonDump(aFunction, /*append=*/true)
00568     << aResult << " = geompy.GetPoint(" << theShape << ", "
00569     << theX << ", " << theY << ", " << theZ << ", " << theEpsilon << ")";
00570 
00571   SetErrorCode(OK);
00572   return aResult;
00573 }
00574 
00575 //=============================================================================
00579 //=============================================================================
00580 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetVertexNearPoint
00581                                                (Handle(GEOM_Object) theShape,
00582                                                 Handle(GEOM_Object) thePoint)
00583 {
00584   SetErrorCode(KO);
00585 
00586   // New Point object
00587   Handle(GEOM_Object) aResult;
00588 
00589   // Arguments
00590   if (theShape.IsNull() || thePoint.IsNull()) return NULL;
00591 
00592   TopoDS_Shape aBlockOrComp = theShape->GetValue();
00593   TopoDS_Shape aPoint       = thePoint->GetValue();
00594   if (aBlockOrComp.IsNull() || aPoint.IsNull()) {
00595     SetErrorCode("Given shape is null");
00596     return NULL;
00597   }
00598 
00599   if (aPoint.ShapeType() != TopAbs_VERTEX) {
00600     SetErrorCode("Element for vertex identification is not a vertex");
00601     return NULL;
00602   }
00603 
00604   TopoDS_Vertex aVert = TopoDS::Vertex(aPoint);
00605   gp_Pnt aP = BRep_Tool::Pnt(aVert);
00606 
00607   // Compute the Vertex value
00608   TopoDS_Shape V;
00609   bool isFound = false;
00610   Standard_Real aDist = RealLast();
00611   TopTools_MapOfShape mapShape;
00612 
00613   TopExp_Explorer exp (aBlockOrComp, TopAbs_VERTEX);
00614   for (; exp.More(); exp.Next()) {
00615     if (mapShape.Add(exp.Current())) {
00616       TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current());
00617       gp_Pnt aPi = BRep_Tool::Pnt(aVi);
00618       Standard_Real aDisti = aPi.Distance(aP);
00619       if (aDisti < aDist) {
00620         V = aVi;
00621         aDist = aDisti;
00622         isFound = true;
00623       }
00624     }
00625   }
00626 
00627   if (!isFound) {
00628     SetErrorCode("Vertex has not been found");
00629     return NULL;
00630   }
00631 
00632   TopTools_IndexedMapOfShape anIndices;
00633   TopExp::MapShapes(aBlockOrComp, anIndices);
00634   Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
00635   anArray->SetValue(1, anIndices.FindIndex(V));
00636   aResult = GetEngine()->AddSubShape(theShape, anArray);
00637 
00638   // The GetPoint() doesn't change object so no new function is required.
00639   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
00640 
00641   // Make a Python command
00642   GEOM::TPythonDump(aFunction, /*append=*/true)
00643     << aResult << " = geompy.GetVertexNearPoint("
00644     << theShape << ", " << thePoint << ")";
00645 
00646   SetErrorCode(OK);
00647   return aResult;
00648 }
00649 
00650 //=============================================================================
00654 //=============================================================================
00655 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdge
00656                                                 (Handle(GEOM_Object) theShape,
00657                                                  Handle(GEOM_Object) thePoint1,
00658                                                  Handle(GEOM_Object) thePoint2)
00659 {
00660   SetErrorCode(KO);
00661 
00662   //New Edge object
00663   Handle(GEOM_Object) aResult;
00664 
00665   // Arguments
00666   if (theShape.IsNull() || thePoint1.IsNull() || thePoint2.IsNull()) return NULL;
00667 
00668   TopoDS_Shape aBlockOrComp = theShape->GetValue();
00669   if (aBlockOrComp.IsNull()) {
00670     SetErrorCode("Given shape is null");
00671     return NULL;
00672   }
00673 
00674   TopoDS_Shape anArg1 = thePoint1->GetValue();
00675   TopoDS_Shape anArg2 = thePoint2->GetValue();
00676   if (anArg1.IsNull() || anArg2.IsNull()) {
00677     SetErrorCode("Null shape is given as argument");
00678     return NULL;
00679   }
00680   if (anArg1.ShapeType() != TopAbs_VERTEX ||
00681       anArg2.ShapeType() != TopAbs_VERTEX) {
00682     SetErrorCode("Element for edge identification is not a vertex");
00683     return NULL;
00684   }
00685 
00686   //Compute the Edge value
00687   try {
00688 #if OCC_VERSION_LARGE > 0x06010000
00689     OCC_CATCH_SIGNALS;
00690 #endif
00691     TopTools_IndexedDataMapOfShapeListOfShape MVE;
00692     GEOMImpl_Block6Explorer::MapShapesAndAncestors
00693       (aBlockOrComp, TopAbs_VERTEX, TopAbs_EDGE, MVE);
00694 
00695     TopoDS_Shape V1,V2;
00696     Standard_Integer ish, ext = MVE.Extent();
00697 
00698     if (MVE.Contains(anArg1)) {
00699       V1 = anArg1;
00700     } else {
00701       for (ish = 1; ish <= ext; ish++) {
00702         TopoDS_Shape aShi = MVE.FindKey(ish);
00703         if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
00704           V1 = aShi;
00705           break;
00706         }
00707       }
00708     }
00709 
00710     if (MVE.Contains(anArg2)) {
00711       V2 = anArg2;
00712     } else {
00713       for (ish = 1; ish <= ext; ish++) {
00714         TopoDS_Shape aShi = MVE.FindKey(ish);
00715         if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
00716           V2 = aShi;
00717           break;
00718         }
00719       }
00720     }
00721 
00722     if (V1.IsNull() || V2.IsNull()) {
00723       SetErrorCode("The given vertex does not belong to the shape");
00724       return NULL;
00725     }
00726 
00727     TopoDS_Shape anEdge;
00728     Standard_Integer isFound =
00729       GEOMImpl_Block6Explorer::FindEdge(anEdge, V1, V2, MVE, Standard_True);
00730     if (isFound == 0) {
00731       SetErrorCode("The given vertices do not belong to one edge of the given shape");
00732       return NULL;
00733     } else if (isFound > 1) {
00734       SetErrorCode("Multiple edges found by the given vertices of the shape");
00735       return NULL;
00736     } else {
00737       TopTools_IndexedMapOfShape anIndices;
00738       TopExp::MapShapes(aBlockOrComp, anIndices);
00739       Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
00740       anArray->SetValue(1, anIndices.FindIndex(anEdge));
00741       aResult = GetEngine()->AddSubShape(theShape, anArray);
00742     }
00743   } catch (Standard_Failure) {
00744     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
00745     SetErrorCode(aFail->GetMessageString());
00746     return NULL;
00747   }
00748 
00749   Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
00750 
00751   //Make a Python command
00752   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdge("
00753     << theShape << ", " << thePoint1 << ", " << thePoint2 << ")";
00754 
00755   SetErrorCode(OK);
00756   return aResult;
00757 }
00758 
00759 //=============================================================================
00763 //=============================================================================
00764 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdgeNearPoint
00765                                                 (Handle(GEOM_Object) theShape,
00766                                                  Handle(GEOM_Object) thePoint)
00767 {
00768   SetErrorCode(KO);
00769 
00770   //New object
00771   Handle(GEOM_Object) aResult;
00772 
00773   // Arguments
00774   if (theShape.IsNull() || thePoint.IsNull()) return NULL;
00775 
00776   TopoDS_Shape aBlockOrComp = theShape->GetValue();
00777   if (aBlockOrComp.IsNull()) {
00778     SetErrorCode("Given shape is null");
00779     return NULL;
00780   }
00781 
00782   TopoDS_Shape anArg = thePoint->GetValue();
00783   if (anArg.IsNull()) {
00784     SetErrorCode("Null shape is given as argument");
00785     return NULL;
00786   }
00787   if (anArg.ShapeType() != TopAbs_VERTEX) {
00788     SetErrorCode("Element for edge identification is not a vertex");
00789     return NULL;
00790   }
00791 
00792   //Compute the Edge value
00793   try {
00794 #if OCC_VERSION_LARGE > 0x06010000
00795     OCC_CATCH_SIGNALS;
00796 #endif
00797     TopoDS_Shape aShape;
00798 
00799     TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
00800 
00801     // 1. Explode blocks on edges
00802     TopTools_MapOfShape mapShape;
00803     Standard_Integer nbEdges = 0;
00804     TopExp_Explorer exp (aBlockOrComp, TopAbs_EDGE);
00805     for (; exp.More(); exp.Next()) {
00806       if (mapShape.Add(exp.Current())) {
00807         nbEdges++;
00808       }
00809     }
00810 
00811     if (nbEdges == 0) {
00812       SetErrorCode("Given shape contains no edges");
00813       return NULL;
00814     }
00815 
00816     mapShape.Clear();
00817     Standard_Integer ind = 1;
00818     TopTools_Array1OfShape anEdges (1, nbEdges);
00819     TColStd_Array1OfReal aDistances (1, nbEdges);
00820     for (exp.Init(aBlockOrComp, TopAbs_EDGE); exp.More(); exp.Next()) {
00821       if (mapShape.Add(exp.Current())) {
00822         TopoDS_Shape anEdge = exp.Current();
00823         anEdges(ind) = anEdge;
00824 
00825         // 2. Classify the point relatively each edge
00826         BRepExtrema_DistShapeShape aDistTool (aVert, anEdges(ind));
00827         if (!aDistTool.IsDone()) {
00828           SetErrorCode("Can not find a distance from the given point to one of edges");
00829           return NULL;
00830         }
00831         aDistances(ind) = aDistTool.Value();
00832         ind++;
00833       }
00834     }
00835 
00836     // 3. Define edge, having minimum distance to the point
00837     Standard_Real nearest = RealLast(), nbFound = 0;
00838     Standard_Real prec = Precision::Confusion();
00839     for (ind = 1; ind <= nbEdges; ind++) {
00840       if (Abs(aDistances(ind) - nearest) < prec) {
00841         nbFound++;
00842       } else if (aDistances(ind) < nearest) {
00843         nearest = aDistances(ind);
00844         aShape = anEdges(ind);
00845         nbFound = 1;
00846       } else {
00847       }
00848     }
00849     if (nbFound > 1) {
00850       SetErrorCode("Multiple edges near the given point are found");
00851       return NULL;
00852     } else if (nbFound == 0) {
00853       SetErrorCode("There are no edges near the given point");
00854       return NULL;
00855     } else {
00856       TopTools_IndexedMapOfShape anIndices;
00857       TopExp::MapShapes(aBlockOrComp, anIndices);
00858       Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
00859       anArray->SetValue(1, anIndices.FindIndex(aShape));
00860       aResult = GetEngine()->AddSubShape(theShape, anArray);
00861     }
00862   }
00863   catch (Standard_Failure) {
00864     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
00865     SetErrorCode(aFail->GetMessageString());
00866     return NULL;
00867   }
00868 
00869   Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
00870 
00871   //Make a Python command
00872   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetEdgeNearPoint("
00873                                << theShape << ", " << thePoint << ")";
00874 
00875   SetErrorCode(OK);
00876   return aResult;
00877 }
00878 
00879 //=============================================================================
00883 //=============================================================================
00884 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByPoints
00885                                                 (Handle(GEOM_Object) theShape,
00886                                                  Handle(GEOM_Object) thePoint1,
00887                                                  Handle(GEOM_Object) thePoint2,
00888                                                  Handle(GEOM_Object) thePoint3,
00889                                                  Handle(GEOM_Object) thePoint4)
00890 {
00891   SetErrorCode(KO);
00892 
00893   //New object
00894   Handle(GEOM_Object) aResult;
00895 
00896   // Arguments
00897   if (theShape.IsNull() ||
00898       thePoint1.IsNull() || thePoint2.IsNull() ||
00899       thePoint3.IsNull() || thePoint4.IsNull()) return NULL;
00900 
00901   TopoDS_Shape aBlockOrComp = theShape->GetValue();
00902   if (aBlockOrComp.IsNull()) {
00903     SetErrorCode("Block or compound is null");
00904     return NULL;
00905   }
00906 
00907   TopoDS_Shape anArg1 = thePoint1->GetValue();
00908   TopoDS_Shape anArg2 = thePoint2->GetValue();
00909   TopoDS_Shape anArg3 = thePoint3->GetValue();
00910   TopoDS_Shape anArg4 = thePoint4->GetValue();
00911   if (anArg1.IsNull() || anArg2.IsNull() ||
00912       anArg3.IsNull() || anArg4.IsNull()) {
00913     SetErrorCode("Null shape is given as argument");
00914     return NULL;
00915   }
00916   if (anArg1.ShapeType() != TopAbs_VERTEX ||
00917       anArg2.ShapeType() != TopAbs_VERTEX ||
00918       anArg3.ShapeType() != TopAbs_VERTEX ||
00919       anArg4.ShapeType() != TopAbs_VERTEX) {
00920     SetErrorCode("Element for face identification is not a vertex");
00921     return NULL;
00922   }
00923 
00924   //Compute the Face value
00925   try {
00926 #if OCC_VERSION_LARGE > 0x06010000
00927     OCC_CATCH_SIGNALS;
00928 #endif
00929     TopoDS_Shape aShape;
00930 
00931     TopTools_IndexedDataMapOfShapeListOfShape MVF;
00932     GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_VERTEX, TopAbs_FACE, MVF);
00933 
00934     TopoDS_Shape V1,V2,V3,V4;
00935     Standard_Integer ish, ext = MVF.Extent();
00936 
00937     if (MVF.Contains(anArg1)) {
00938       V1 = anArg1;
00939     } else {
00940       for (ish = 1; ish <= ext; ish++) {
00941         TopoDS_Shape aShi = MVF.FindKey(ish);
00942         if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) {
00943           V1 = aShi;
00944           break;
00945         }
00946       }
00947     }
00948 
00949     if (MVF.Contains(anArg2)) {
00950       V2 = anArg2;
00951     } else {
00952       for (ish = 1; ish <= ext; ish++) {
00953         TopoDS_Shape aShi = MVF.FindKey(ish);
00954         if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) {
00955           V2 = aShi;
00956           break;
00957         }
00958       }
00959     }
00960 
00961     if (MVF.Contains(anArg3)) {
00962       V3 = anArg3;
00963     } else {
00964       for (ish = 1; ish <= ext; ish++) {
00965         TopoDS_Shape aShi = MVF.FindKey(ish);
00966         if (BRepTools::Compare(TopoDS::Vertex(anArg3), TopoDS::Vertex(aShi))) {
00967           V3 = aShi;
00968           break;
00969         }
00970       }
00971     }
00972 
00973     if (MVF.Contains(anArg4)) {
00974       V4 = anArg4;
00975     } else {
00976       for (ish = 1; ish <= ext; ish++) {
00977         TopoDS_Shape aShi = MVF.FindKey(ish);
00978         if (BRepTools::Compare(TopoDS::Vertex(anArg4), TopoDS::Vertex(aShi))) {
00979           V4 = aShi;
00980           break;
00981         }
00982       }
00983     }
00984 
00985     if (V1.IsNull() || V2.IsNull() || V3.IsNull() || V4.IsNull()) {
00986       SetErrorCode("The given vertex does not belong to the shape");
00987       return NULL;
00988     }
00989 
00990     Standard_Integer isFound =
00991       GEOMImpl_Block6Explorer::FindFace(aShape, V1, V2, V3, V4, MVF, Standard_True);
00992     if (isFound == 0) {
00993       SetErrorCode("The given vertices do not belong to one face of the given shape");
00994       return NULL;
00995     } else if (isFound > 1) {
00996       SetErrorCode("The given vertices belong to several faces of the given shape");
00997       return NULL;
00998     } else {
00999       TopTools_IndexedMapOfShape anIndices;
01000       TopExp::MapShapes(aBlockOrComp, anIndices);
01001       Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
01002       anArray->SetValue(1, anIndices.FindIndex(aShape));
01003       aResult = GetEngine()->AddSubShape(theShape, anArray);
01004     }
01005   }
01006   catch (Standard_Failure) {
01007     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
01008     SetErrorCode(aFail->GetMessageString());
01009     return NULL;
01010   }
01011 
01012   Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
01013 
01014   //Make a Python command
01015   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByPoints("
01016     << theShape << ", " << thePoint1 << ", " << thePoint2
01017       << ", " << thePoint3 << ", " << thePoint4 << ")";
01018 
01019   SetErrorCode(OK);
01020   return aResult;
01021 }
01022 
01023 //=============================================================================
01027 //=============================================================================
01028 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByEdges
01029                                                 (Handle(GEOM_Object) theShape,
01030                                                  Handle(GEOM_Object) theEdge1,
01031                                                  Handle(GEOM_Object) theEdge2)
01032 {
01033   SetErrorCode(KO);
01034 
01035   //New object
01036   Handle(GEOM_Object) aResult;
01037 
01038   // Arguments
01039   if (theShape.IsNull() || theEdge1.IsNull() || theEdge2.IsNull()) return NULL;
01040 
01041   TopoDS_Shape aBlockOrComp = theShape->GetValue();
01042   if (aBlockOrComp.IsNull()) {
01043     SetErrorCode("Block or compound is null");
01044     return NULL;
01045   }
01046 
01047   TopoDS_Shape anArg1 = theEdge1->GetValue();
01048   TopoDS_Shape anArg2 = theEdge2->GetValue();
01049   if (anArg1.IsNull() || anArg2.IsNull()) {
01050     SetErrorCode("Null shape is given as argument");
01051     return NULL;
01052   }
01053   if (anArg1.ShapeType() != TopAbs_EDGE ||
01054       anArg2.ShapeType() != TopAbs_EDGE) {
01055     SetErrorCode("Element for face identification is not an edge");
01056     return NULL;
01057   }
01058 
01059   //Compute the Face value
01060   try {
01061 #if OCC_VERSION_LARGE > 0x06010000
01062     OCC_CATCH_SIGNALS;
01063 #endif
01064     TopoDS_Shape aShape;
01065 
01066     TopTools_IndexedDataMapOfShapeListOfShape MEF;
01067     GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_EDGE, TopAbs_FACE, MEF);
01068 
01069     TopoDS_Shape E1,E2;
01070     Standard_Integer ish, ext = MEF.Extent();
01071 
01072     if (MEF.Contains(anArg1)) {
01073       E1 = anArg1;
01074     } else {
01075       for (ish = 1; ish <= ext; ish++) {
01076         TopoDS_Shape aShi = MEF.FindKey(ish);
01077         if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg1, aShi)) {
01078           E1 = aShi;
01079         }
01080       }
01081     }
01082 
01083     if (MEF.Contains(anArg2)) {
01084       E2 = anArg2;
01085     } else {
01086       for (ish = 1; ish <= ext; ish++) {
01087         TopoDS_Shape aShi = MEF.FindKey(ish);
01088         if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg2, aShi)) {
01089           E2 = aShi;
01090         }
01091       }
01092     }
01093 
01094     if (E1.IsNull() || E2.IsNull()) {
01095       SetErrorCode("The given edge does not belong to the shape");
01096       return NULL;
01097     }
01098 
01099     const TopTools_ListOfShape& aFacesOfE1 = MEF.FindFromKey(E1);
01100     const TopTools_ListOfShape& aFacesOfE2 = MEF.FindFromKey(E2);
01101 
01102     Standard_Integer isFound = 0;
01103     TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfE1);
01104     for (; anIterF1.More(); anIterF1.Next()) {
01105 
01106       TopTools_ListIteratorOfListOfShape anIterF2 (aFacesOfE2);
01107       for (; anIterF2.More(); anIterF2.Next()) {
01108 
01109         if (anIterF1.Value().IsSame(anIterF2.Value())) {
01110           isFound++;
01111 
01112           // Store the face, defined by two edges
01113           aShape = anIterF1.Value();
01114         }
01115       }
01116     }
01117     if (isFound == 0) {
01118       SetErrorCode("The given edges do not belong to one face of the given shape");
01119       return NULL;
01120     } else if (isFound > 1) {
01121       SetErrorCode("The given edges belong to several faces of the given shape");
01122       return NULL;
01123     } else {
01124       TopTools_IndexedMapOfShape anIndices;
01125       TopExp::MapShapes(aBlockOrComp, anIndices);
01126       Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
01127       anArray->SetValue(1, anIndices.FindIndex(aShape));
01128       aResult = GetEngine()->AddSubShape(theShape, anArray);
01129     }
01130   }
01131   catch (Standard_Failure) {
01132     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
01133     SetErrorCode(aFail->GetMessageString());
01134     return NULL;
01135   }
01136 
01137   Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
01138 
01139   //Make a Python command
01140   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByEdges("
01141     << theShape << ", " << theEdge1 << ", " << theEdge2 << ")";
01142 
01143   SetErrorCode(OK);
01144   return aResult;
01145 }
01146 
01147 //=============================================================================
01151 //=============================================================================
01152 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetOppositeFace
01153                                                 (Handle(GEOM_Object) theShape,
01154                                                  Handle(GEOM_Object) theFace)
01155 {
01156   SetErrorCode(KO);
01157 
01158   //New object
01159   Handle(GEOM_Object) aResult;
01160 
01161   // Arguments
01162   if (theShape.IsNull() || theFace.IsNull()) return NULL;
01163 
01164   TopoDS_Shape aBlockOrComp = theShape->GetValue();
01165   if (aBlockOrComp.IsNull()) {
01166     SetErrorCode("Block is null");
01167     return NULL;
01168   }
01169   if (aBlockOrComp.ShapeType() != TopAbs_SOLID) {
01170     SetErrorCode("Shape is not a block");
01171     return NULL;
01172   }
01173 
01174   TopoDS_Shape anArg = theFace->GetValue();
01175   if (anArg.IsNull()) {
01176     SetErrorCode("Null shape is given as argument");
01177     return NULL;
01178   }
01179   if (anArg.ShapeType() != TopAbs_FACE) {
01180     SetErrorCode("Element for face identification is not a face");
01181     return NULL;
01182   }
01183 
01184   //Compute the Face value
01185   try {
01186 #if OCC_VERSION_LARGE > 0x06010000
01187     OCC_CATCH_SIGNALS;
01188 #endif
01189     TopoDS_Shape aShape;
01190 
01191     GEOMImpl_Block6Explorer aBlockTool;
01192     aBlockTool.InitByBlockAndFace(aBlockOrComp, anArg);
01193     aShape = aBlockTool.GetFace(2);
01194 
01195     TopTools_IndexedMapOfShape anIndices;
01196     TopExp::MapShapes(aBlockOrComp, anIndices);
01197     Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
01198     anArray->SetValue(1, anIndices.FindIndex(aShape));
01199     aResult = GetEngine()->AddSubShape(theShape, anArray);
01200   }
01201   catch (Standard_Failure) {
01202     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
01203     SetErrorCode(aFail->GetMessageString());
01204     return NULL;
01205   }
01206 
01207   Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
01208 
01209   //Make a Python command
01210   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetOppositeFace("
01211                                << theShape << ", " << theFace << ")";
01212 
01213   SetErrorCode(OK);
01214   return aResult;
01215 }
01216 
01217 //=============================================================================
01221 //=============================================================================
01222 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceNearPoint
01223                                                 (Handle(GEOM_Object) theShape,
01224                                                  Handle(GEOM_Object) thePoint)
01225 {
01226   SetErrorCode(KO);
01227 
01228   //New object
01229   Handle(GEOM_Object) aResult;
01230 
01231   // Arguments
01232   if (theShape.IsNull() || thePoint.IsNull()) return NULL;
01233 
01234   TopoDS_Shape aBlockOrComp = theShape->GetValue();
01235   if (aBlockOrComp.IsNull()) {
01236     SetErrorCode("Block or compound is null");
01237     return NULL;
01238   }
01239 
01240   TopoDS_Shape anArg = thePoint->GetValue();
01241   if (anArg.IsNull()) {
01242     SetErrorCode("Null shape is given as argument");
01243     return NULL;
01244   }
01245   if (anArg.ShapeType() != TopAbs_VERTEX) {
01246     SetErrorCode("Element for face identification is not a vertex");
01247     return NULL;
01248   }
01249 
01250   //Compute the Face value
01251   try {
01252 #if OCC_VERSION_LARGE > 0x06010000
01253     OCC_CATCH_SIGNALS;
01254 #endif
01255     TopoDS_Shape aShape;
01256 
01257     TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
01258     gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
01259     Standard_Real PX, PY, PZ;
01260     aPnt.Coord(PX, PY, PZ);
01261 
01262     // 1. Classify the point relatively each face
01263     Standard_Integer nearest = 2, nbFound = 0;
01264     TopTools_DataMapOfShapeInteger mapShapeDist;
01265     TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
01266     for (; exp.More(); exp.Next()) {
01267       TopoDS_Shape aFace = exp.Current();
01268 
01269       if (!mapShapeDist.IsBound(aFace)) {
01270         Standard_Integer aDistance = 2;
01271 
01272         // 1.a. Classify relatively Surface
01273         Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
01274         Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
01275         gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
01276         gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
01277         Standard_Real aDist = p3dOnSurf.Distance(aPnt);
01278         if (aDist > Precision::Confusion()) {
01279           // OUT of Surface
01280           aDistance = 1;
01281         } else {
01282           // 1.b. Classify relatively the face itself
01283           BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
01284           if (FC.State() == TopAbs_IN) {
01285             aDistance = -1;
01286           } else if (FC.State() == TopAbs_ON) {
01287             aDistance = 0;
01288           } else { // OUT
01289             aDistance = 1;
01290           }
01291         }
01292 
01293         if (aDistance < nearest) {
01294           nearest = aDistance;
01295           aShape = aFace;
01296           nbFound = 1;
01297 
01298           // A first found face, containing the point inside, will be returned.
01299           // It is the solution, if there are no
01300           // coincident or intersecting faces in the compound.
01301           if (nearest == -1) break;
01302 
01303         } else if (aDistance == nearest) {
01304           nbFound++;
01305         } else {
01306         }
01307 
01308         mapShapeDist.Bind(aFace, aDistance);
01309       } // if (!mapShapeDist.IsBound(aFace))
01310     }
01311 
01312     // 2. Define face, containing the point or having minimum distance to it
01313     if (nbFound > 1) {
01314       if (nearest == 0) {
01315         // The point is on boundary of some faces and there are
01316         // no faces, having the point inside
01317         SetErrorCode("Multiple faces near the given point are found");
01318         return NULL;
01319 
01320       } else if (nearest == 1) {
01321         // The point is outside some faces and there are
01322         // no faces, having the point inside or on boundary.
01323         // We will get a nearest face
01324         Standard_Real bigReal = RealLast();
01325         Standard_Real minDist = bigReal;
01326         TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
01327         for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
01328           if (mapShapeDistIter.Value() == 1) {
01329             TopoDS_Shape aFace = mapShapeDistIter.Key();
01330             Standard_Real aDist = bigReal;
01331 
01332             // 2.a. Fast check of distance - if point projection on surface is on face
01333             Handle(Geom_Surface) aSurf = BRep_Tool::Surface(TopoDS::Face(aFace));
01334             Handle(ShapeAnalysis_Surface) aSurfAna = new ShapeAnalysis_Surface (aSurf);
01335             gp_Pnt2d p2dOnSurf = aSurfAna->ValueOfUV(aPnt, Precision::Confusion());
01336             gp_Pnt p3dOnSurf = aSurfAna->Value(p2dOnSurf);
01337             aDist = p3dOnSurf.Distance(aPnt);
01338 
01339             BRepClass_FaceClassifier FC (TopoDS::Face(aFace), p2dOnSurf, Precision::Confusion());
01340             if (FC.State() == TopAbs_OUT) {
01341               if (aDist < minDist) {
01342                 // 2.b. Slow check - if point projection on surface is outside of face
01343                 BRepExtrema_DistShapeShape aDistTool (aVert, aFace);
01344                 if (!aDistTool.IsDone()) {
01345                   SetErrorCode("Can not find a distance from the given point to one of faces");
01346                   return NULL;
01347                 }
01348                 aDist = aDistTool.Value();
01349               } else {
01350                 aDist = bigReal;
01351               }
01352             }
01353 
01354             if (aDist < minDist) {
01355               minDist = aDist;
01356               aShape = aFace;
01357             }
01358           }
01359         }
01360       } else { // nearest == -1
01361 //        // The point is inside some faces.
01362 //        // We will get a face with nearest center
01363 //        Standard_Real minDist = RealLast();
01364 //        TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
01365 //        for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
01366 //          if (mapShapeDistIter.Value() == -1) {
01367 //            TopoDS_Shape aFace = mapShapeDistIter.Key();
01368 //            GProp_GProps aSystem;
01369 //            BRepGProp::SurfaceProperties(aFace, aSystem);
01370 //            gp_Pnt aCenterMass = aSystem.CentreOfMass();
01371 //
01372 //            Standard_Real aDist = aCenterMass.Distance(aPnt);
01373 //            if (aDist < minDist) {
01374 //              minDist = aDist;
01375 //              aShape = aFace;
01376 //            }
01377 //          }
01378 //        }
01379       }
01380     } // if (nbFound > 1)
01381 
01382     if (nbFound == 0) {
01383       SetErrorCode("There are no faces near the given point");
01384       return NULL;
01385     } else {
01386       TopTools_IndexedMapOfShape anIndices;
01387       TopExp::MapShapes(aBlockOrComp, anIndices);
01388       Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
01389       anArray->SetValue(1, anIndices.FindIndex(aShape));
01390       aResult = GetEngine()->AddSubShape(theShape, anArray);
01391     }
01392   }
01393   catch (Standard_Failure) {
01394     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
01395     SetErrorCode(aFail->GetMessageString());
01396     return NULL;
01397   }
01398 
01399   Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
01400 
01401   //Make a Python command
01402   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceNearPoint("
01403                                << theShape << ", " << thePoint << ")";
01404 
01405   SetErrorCode(OK);
01406   return aResult;
01407 }
01408 
01409 //=============================================================================
01413 //=============================================================================
01414 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByNormale
01415                                                 (Handle(GEOM_Object) theShape,
01416                                                  Handle(GEOM_Object) theVector)
01417 {
01418   SetErrorCode(KO);
01419 
01420   //New object
01421   Handle(GEOM_Object) aResult;
01422 
01423   // Arguments
01424   if (theShape.IsNull() || theVector.IsNull()) return NULL;
01425 
01426   TopoDS_Shape aBlockOrComp = theShape->GetValue();
01427   if (aBlockOrComp.IsNull()) {
01428     SetErrorCode("Block or compound is null");
01429     return NULL;
01430   }
01431 
01432   TopoDS_Shape anArg = theVector->GetValue();
01433   if (anArg.IsNull()) {
01434     SetErrorCode("Null shape is given as argument");
01435     return NULL;
01436   }
01437   if (anArg.ShapeType() != TopAbs_EDGE) {
01438     SetErrorCode("Element for normale identification is not an edge");
01439     return NULL;
01440   }
01441 
01442   //Compute the Face value
01443   try {
01444 #if OCC_VERSION_LARGE > 0x06010000
01445     OCC_CATCH_SIGNALS;
01446 #endif
01447     TopoDS_Shape aShape;
01448 
01449     TopoDS_Edge anEdge = TopoDS::Edge(anArg);
01450     TopoDS_Vertex V1, V2;
01451     TopExp::Vertices(anEdge, V1, V2, Standard_True);
01452     gp_Pnt P1 = BRep_Tool::Pnt(V1);
01453     gp_Pnt P2 = BRep_Tool::Pnt(V2);
01454     gp_Vec aVec (P1, P2);
01455     if (aVec.Magnitude() < Precision::Confusion()) {
01456       SetErrorCode("Vector with null magnitude is given");
01457       return NULL;
01458     }
01459 
01460     Standard_Real minAngle = RealLast();
01461     TopTools_MapOfShape mapShape;
01462     TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE);
01463     for (; exp.More(); exp.Next()) {
01464       if (mapShape.Add(exp.Current())) {
01465         TopoDS_Face aFace = TopoDS::Face(exp.Current());
01466         BRepAdaptor_Surface SF (aFace);
01467 
01468         Standard_Real u, v, x;
01469 
01470         // find a point on the surface to get normal direction in
01471         u = SF.FirstUParameter();
01472         x = SF.LastUParameter();
01473         if (Precision::IsInfinite(u)) {
01474           u =  (Precision::IsInfinite(x)) ? 0. : x;
01475         } else if (!Precision::IsInfinite(x)) {
01476           u = (u+x) / 2.;
01477         }
01478 
01479         v = SF.FirstVParameter();
01480         x = SF.LastVParameter();
01481         if (Precision::IsInfinite(v)) {
01482           v =  (Precision::IsInfinite(x)) ? 0. : x;
01483         } else if (!Precision::IsInfinite(x)) {
01484           v = (v+x) / 2.;
01485         }
01486 
01487         // compute the normal direction
01488         gp_Vec Vec1,Vec2;
01489         SF.D1(u,v,P1,Vec1,Vec2);
01490         gp_Vec V = Vec1.Crossed(Vec2);
01491         x = V.Magnitude();
01492         if (V.Magnitude() < Precision::Confusion()) {
01493           SetErrorCode("Normal vector of a face has null magnitude");
01494           return NULL;
01495         }
01496 
01497         // consider the face orientation
01498         if (aFace.Orientation() == TopAbs_REVERSED ||
01499             aFace.Orientation() == TopAbs_INTERNAL) {
01500           V = - V;
01501         }
01502 
01503         // compute the angle and compare with the minimal one
01504         Standard_Real anAngle = aVec.Angle(V);
01505         if (anAngle < minAngle) {
01506           minAngle = anAngle;
01507           aShape = aFace;
01508         }
01509       }
01510     }
01511 
01512     if (aShape.IsNull()) {
01513       SetErrorCode("Failed to find a face by the given normale");
01514       return NULL;
01515     } else {
01516       TopTools_IndexedMapOfShape anIndices;
01517       TopExp::MapShapes(aBlockOrComp, anIndices);
01518       Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
01519       anArray->SetValue(1, anIndices.FindIndex(aShape));
01520       aResult = GetEngine()->AddSubShape(theShape, anArray);
01521     }
01522   }
01523   catch (Standard_Failure) {
01524     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
01525     SetErrorCode(aFail->GetMessageString());
01526     return NULL;
01527   }
01528 
01529   Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
01530 
01531   //Make a Python command
01532   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetFaceByNormale("
01533     << theShape << ", " << theVector << ")";
01534 
01535   SetErrorCode(OK);
01536   return aResult;
01537 }
01538 
01539 //=============================================================================
01543 //=============================================================================
01544 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetShapesNearPoint
01545                                          (Handle(GEOM_Object)    theShape,
01546                                           Handle(GEOM_Object)    thePoint,
01547                                           const Standard_Integer theShapeType,
01548                                           const Standard_Real    theConstTolerance)
01549 {
01550   SetErrorCode(KO);
01551 
01552   // New object
01553   Handle(GEOM_Object) aResult;
01554 
01555   // Arguments
01556   if (theShape.IsNull() || thePoint.IsNull()) return NULL;
01557 
01558   TopoDS_Shape aBlockOrComp = theShape->GetValue();
01559   if (aBlockOrComp.IsNull()) {
01560     SetErrorCode("Block or compound is null");
01561     return NULL;
01562   }
01563 
01564   TopoDS_Shape anArg = thePoint->GetValue();
01565   if (anArg.IsNull()) {
01566     SetErrorCode("Null shape is given as argument");
01567     return NULL;
01568   }
01569   if (anArg.ShapeType() != TopAbs_VERTEX) {
01570     SetErrorCode("Element for face identification is not a vertex");
01571     return NULL;
01572   }
01573 
01574   if (theShapeType < TopAbs_SOLID || TopAbs_VERTEX < theShapeType) {
01575     SetErrorCode("Invalid type of result is requested");
01576     return NULL;
01577   }
01578   
01579   Standard_Real theTolerance = theConstTolerance;
01580   if (theTolerance < Precision::Confusion()) {
01581     theTolerance = Precision::Confusion();
01582   }
01583 
01584   // Compute the result
01585   try {
01586 #if OCC_VERSION_LARGE > 0x06010000
01587     OCC_CATCH_SIGNALS;
01588 #endif
01589     TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
01590 
01591     TopTools_MapOfShape mapShape;
01592     Standard_Integer nbEdges = 0;
01593     TopExp_Explorer exp (aBlockOrComp, TopAbs_ShapeEnum(theShapeType));
01594     for (; exp.More(); exp.Next()) {
01595       if (mapShape.Add(exp.Current())) {
01596         nbEdges++;
01597       }
01598     }
01599 
01600     if (nbEdges == 0) {
01601       SetErrorCode("Given shape contains no sub-shapes of requested type");
01602       return NULL;
01603     }
01604 
01605     // Calculate distances and find min
01606     mapShape.Clear();
01607     Standard_Integer ind = 1;
01608     Standard_Real aMinDist = RealLast();
01609     TopTools_Array1OfShape anEdges (1, nbEdges);
01610     TColStd_Array1OfReal aDistances (1, nbEdges);
01611     for (exp.Init(aBlockOrComp, TopAbs_ShapeEnum(theShapeType)); exp.More(); exp.Next()) {
01612       if (mapShape.Add(exp.Current())) {
01613         TopoDS_Shape anEdge = exp.Current();
01614         anEdges(ind) = anEdge;
01615 
01616         BRepExtrema_DistShapeShape aDistTool (aVert, anEdges(ind));
01617         if (!aDistTool.IsDone()) {
01618           SetErrorCode("Can not find a distance from the given point to one of sub-shapes");
01619           return NULL;
01620         }
01621         aDistances(ind) = aDistTool.Value();
01622         if (aDistances(ind) < aMinDist) {
01623           aMinDist = aDistances(ind);
01624         }
01625         ind++;
01626       }
01627     }
01628 
01629     if (aMinDist < RealLast()) {
01630       // Collect sub-shapes with distance < (aMinDist + theTolerance)
01631       int nbSubShapes = 0;
01632       TopTools_Array1OfShape aNearShapes (1, nbEdges);
01633       for (ind = 1; ind <= nbEdges; ind++) {
01634         if (aDistances(ind) < aMinDist + theTolerance) {
01635           nbSubShapes++;
01636           aNearShapes(nbSubShapes) = anEdges(ind);
01637         }
01638       }
01639 
01640       // Add sub-shape
01641       TopTools_IndexedMapOfShape anIndices;
01642       TopExp::MapShapes(aBlockOrComp, anIndices);
01643       Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger (1, nbSubShapes);
01644       for (ind = 1; ind <= nbSubShapes; ind++) {
01645         anArray->SetValue(ind, anIndices.FindIndex(aNearShapes(ind)));
01646       }
01647       aResult = GetEngine()->AddSubShape(theShape, anArray);
01648     }
01649   }
01650   catch (Standard_Failure) {
01651     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
01652     SetErrorCode(aFail->GetMessageString());
01653     return NULL;
01654   }
01655 
01656   if (aResult.IsNull())
01657     return NULL;
01658 
01659   Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
01660 
01661   //Make a Python command
01662   GEOM::TPythonDump(aFunction)
01663     << aResult << " = geompy.GetShapesNearPoint(" << theShape << ", " << thePoint
01664     << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theTolerance << ")";
01665 
01666   SetErrorCode(OK);
01667   return aResult;
01668 }
01669 
01670 //=============================================================================
01674 //=============================================================================
01675 Standard_Boolean GEOMImpl_IBlocksOperations::IsCompoundOfBlocks
01676                                                 (Handle(GEOM_Object)    theCompound,
01677                                                  const Standard_Integer theMinNbFaces,
01678                                                  const Standard_Integer theMaxNbFaces,
01679                                                  Standard_Integer&      theNbBlocks)
01680 {
01681   SetErrorCode(KO);
01682   Standard_Boolean isCompOfBlocks = Standard_False;
01683   theNbBlocks = 0;
01684 
01685   if (theCompound.IsNull()) return isCompOfBlocks;
01686   TopoDS_Shape aBlockOrComp = theCompound->GetValue();
01687 
01688   //Check
01689   isCompOfBlocks = Standard_True;
01690   try {
01691 #if OCC_VERSION_LARGE > 0x06010000
01692     OCC_CATCH_SIGNALS;
01693 #endif
01694     TopTools_MapOfShape mapShape;
01695     TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
01696     for (; exp.More(); exp.Next()) {
01697       if (mapShape.Add(exp.Current())) {
01698         TopoDS_Shape aSolid = exp.Current();
01699 
01700         TopTools_MapOfShape mapFaces;
01701         TopExp_Explorer expF (aSolid, TopAbs_FACE);
01702         Standard_Integer nbFaces = 0;
01703         for (; expF.More(); expF.Next()) {
01704           if (mapFaces.Add(expF.Current())) {
01705             nbFaces++;
01706             if (nbFaces > theMaxNbFaces) {
01707               isCompOfBlocks = Standard_False;
01708               break;
01709             }
01710           }
01711         }
01712         if (nbFaces < theMinNbFaces || theMaxNbFaces < nbFaces) {
01713           isCompOfBlocks = Standard_False;
01714         } else {
01715           theNbBlocks++;
01716         }
01717       }
01718     }
01719   }
01720   catch (Standard_Failure) {
01721     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
01722     SetErrorCode(aFail->GetMessageString());
01723     return isCompOfBlocks;
01724   }
01725 
01726   SetErrorCode(OK);
01727   return isCompOfBlocks;
01728 }
01729 
01730 //=============================================================================
01734 //=============================================================================
01735 void GEOMImpl_IBlocksOperations::AddBlocksFrom (const TopoDS_Shape&   theShape,
01736                                                 TopTools_ListOfShape& BLO,
01737                                                 TopTools_ListOfShape& NOT,
01738                                                 TopTools_ListOfShape& EXT)
01739 {
01740   TopAbs_ShapeEnum aType = theShape.ShapeType();
01741   switch (aType) {
01742   case TopAbs_COMPOUND:
01743   case TopAbs_COMPSOLID:
01744     {
01745       TopoDS_Iterator It (theShape);
01746       for (; It.More(); It.Next()) {
01747         AddBlocksFrom(It.Value(), BLO, NOT, EXT);
01748       }
01749     }
01750     break;
01751   case TopAbs_SOLID:
01752     {
01753       // Check, if there are seam or degenerated edges
01754       BlockFix_CheckTool aTool;
01755       aTool.SetShape(theShape);
01756       aTool.Perform();
01757       if (aTool.NbPossibleBlocks() > 0) {
01758         EXT.Append(theShape);
01759       } else {
01760         // Count faces and edges in each face to recognize blocks
01761         TopTools_MapOfShape mapFaces;
01762         Standard_Integer nbFaces = 0;
01763         Standard_Boolean hasNonQuadr = Standard_False;
01764         TopExp_Explorer expF (theShape, TopAbs_FACE);
01765 
01766         for (; expF.More(); expF.Next()) {
01767           if (mapFaces.Add(expF.Current())) {
01768             nbFaces++;
01769             if (nbFaces > 6) break;
01770 
01771             // get wire
01772             TopoDS_Shape aF = expF.Current();
01773             TopExp_Explorer wires (aF, TopAbs_WIRE);
01774             if (!wires.More()) {
01775               // no wire in the face
01776               hasNonQuadr = Standard_True;
01777               break;
01778             }
01779             TopoDS_Shape aWire = wires.Current();
01780             wires.Next();
01781             if (wires.More()) {
01782               // multiple wires in the face
01783               hasNonQuadr = Standard_True;
01784               break;
01785             }
01786 
01787             // Check number of edges in the face
01788             Standard_Integer nbEdges = 0;
01789             TopTools_MapOfShape mapEdges;
01790             TopExp_Explorer expW (aWire, TopAbs_EDGE);
01791             for (; expW.More(); expW.Next()) {
01792               if (mapEdges.Add(expW.Current())) {
01793                 nbEdges++;
01794                 if (nbEdges > 4) break;
01795               }
01796             }
01797             if (nbEdges != 4) {
01798               hasNonQuadr = Standard_True;
01799             }
01800           }
01801         }
01802 
01803         if (nbFaces == 6 && !hasNonQuadr) {
01804           BLO.Append(theShape);
01805         } else {
01806           NOT.Append(theShape);
01807         }
01808       }
01809     }
01810     break;
01811   default:
01812     NOT.Append(theShape);
01813   }
01814 }
01815 
01816 void AddBlocksFromOld (const TopoDS_Shape&   theShape,
01817                        TopTools_ListOfShape& BLO,
01818                        TopTools_ListOfShape& NOT,
01819                        TopTools_ListOfShape& DEG,
01820                        TopTools_ListOfShape& SEA)
01821 {
01822   TopAbs_ShapeEnum aType = theShape.ShapeType();
01823   switch (aType) {
01824   case TopAbs_COMPOUND:
01825   case TopAbs_COMPSOLID:
01826     {
01827       TopoDS_Iterator It (theShape);
01828       for (; It.More(); It.Next()) {
01829         AddBlocksFromOld(It.Value(), BLO, NOT, DEG, SEA);
01830       }
01831     }
01832     break;
01833   case TopAbs_SOLID:
01834     {
01835       TopTools_MapOfShape mapFaces;
01836       TopExp_Explorer expF (theShape, TopAbs_FACE);
01837       Standard_Integer nbFaces = 0;
01838       Standard_Boolean hasNonQuadr = Standard_False;
01839       Standard_Boolean hasDegenerated = Standard_False;
01840       Standard_Boolean hasSeam = Standard_False;
01841       for (; expF.More(); expF.Next()) {
01842         if (mapFaces.Add(expF.Current())) {
01843           nbFaces++;
01844           if (nbFaces > 6) break;
01845 
01846           // Check number of edges in the face
01847           Standard_Integer nbEdges = 0;
01848           TopTools_MapOfShape mapEdges;
01849 
01850           // get wire
01851           TopoDS_Shape aF = expF.Current();
01852           TopExp_Explorer wires (aF, TopAbs_WIRE);
01853           if (!wires.More()) {
01854             // no wire in the face
01855             hasNonQuadr = Standard_True;
01856             break;
01857           }
01858           TopoDS_Shape aWire = wires.Current();
01859           wires.Next();
01860           if (wires.More()) {
01861             // multiple wires in the face
01862             hasNonQuadr = Standard_True;
01863             break;
01864           }
01865 
01866           // iterate on wire
01867           BRepTools_WireExplorer aWE (TopoDS::Wire(aWire), TopoDS::Face(aF));
01868           for (; aWE.More(); aWE.Next(), nbEdges++) {
01869             if (BRep_Tool::Degenerated(aWE.Current())) {
01870               // degenerated edge found
01871               hasDegenerated = Standard_True;
01872 //              break;
01873             }
01874             if (mapEdges.Contains(aWE.Current())) {
01875               // seam edge found
01876               hasSeam = Standard_True;
01877 //              break;
01878             }
01879             mapEdges.Add(aWE.Current());
01880           }
01881           if (nbEdges != 4) {
01882             hasNonQuadr = Standard_True;
01883           }
01884         }
01885       }
01886       if (nbFaces == 6) {
01887         if (hasDegenerated || hasSeam) {
01888           if (hasDegenerated) {
01889             DEG.Append(theShape);
01890           }
01891           if (hasSeam) {
01892             SEA.Append(theShape);
01893           }
01894         } else if (hasNonQuadr) {
01895           NOT.Append(theShape);
01896         } else {
01897           BLO.Append(theShape);
01898         }
01899       } else {
01900         NOT.Append(theShape);
01901       }
01902     }
01903     break;
01904   default:
01905     NOT.Append(theShape);
01906   }
01907 }
01908 
01909 #define REL_NOT_CONNECTED 0
01910 #define REL_OK            1
01911 #define REL_NOT_GLUED     2
01912 #define REL_COLLISION_VV  3
01913 #define REL_COLLISION_FF  4
01914 #define REL_COLLISION_EE  5
01915 #define REL_UNKNOWN       6
01916 
01917 Standard_Integer BlocksRelation (const TopoDS_Shape& theBlock1,
01918                                  const TopoDS_Shape& theBlock2)
01919 {
01920   // Compare bounding boxes before calling BRepExtrema_DistShapeShape
01921   Standard_Real Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1;
01922   Standard_Real Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2;
01923   Bnd_Box B1, B2;
01924   BRepBndLib::Add(theBlock1, B1);
01925   BRepBndLib::Add(theBlock2, B2);
01926   B1.Get(Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1);
01927   B2.Get(Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2);
01928   if (Xmax2 < Xmin1 || Xmax1 < Xmin2 ||
01929       Ymax2 < Ymin1 || Ymax1 < Ymin2 ||
01930       Zmax2 < Zmin1 || Zmax1 < Zmin2) {
01931     return REL_NOT_CONNECTED;
01932   }
01933 
01934   BRepExtrema_DistShapeShape dst (theBlock1, theBlock2);
01935   if (!dst.IsDone()) {
01936     return REL_UNKNOWN;
01937   }
01938 
01939   if (dst.Value() > Precision::Confusion()) {
01940     return REL_NOT_CONNECTED;
01941   }
01942 
01943   if (dst.InnerSolution()) {
01944     return REL_COLLISION_VV;
01945   }
01946 
01947   Standard_Integer nbSol = dst.NbSolution();
01948   Standard_Integer relation = REL_OK;
01949   Standard_Integer nbVerts = 0;
01950   Standard_Integer nbEdges = 0;
01951   Standard_Integer sol = 1;
01952   for (; sol <= nbSol; sol++) {
01953     BRepExtrema_SupportType supp1 = dst.SupportTypeShape1(sol);
01954     BRepExtrema_SupportType supp2 = dst.SupportTypeShape2(sol);
01955     if (supp1 == BRepExtrema_IsVertex && supp2 == BRepExtrema_IsVertex) {
01956       nbVerts++;
01957     } else if (supp1 == BRepExtrema_IsInFace || supp2 == BRepExtrema_IsInFace) {
01958       return REL_COLLISION_FF;
01959     } else if (supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsOnEdge) {
01960       nbEdges++;
01961     } else if ((supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsVertex) ||
01962                (supp2 == BRepExtrema_IsOnEdge && supp1 == BRepExtrema_IsVertex)) {
01963       relation = REL_COLLISION_EE;
01964     } else {
01965     }
01966   }
01967 
01968   if (relation != REL_OK) {
01969     return relation;
01970   }
01971 
01972   TColStd_Array1OfInteger vertSol (1, nbVerts);
01973   TopTools_Array1OfShape V1 (1, nbVerts);
01974   TopTools_Array1OfShape V2 (1, nbVerts);
01975   Standard_Integer ivs = 0;
01976   for (sol = 1; sol <= nbSol; sol++) {
01977     if (dst.SupportTypeShape1(sol) == BRepExtrema_IsVertex &&
01978         dst.SupportTypeShape2(sol) == BRepExtrema_IsVertex) {
01979       TopoDS_Vertex Vcur = TopoDS::Vertex(dst.SupportOnShape1(sol));
01980       // Check, that this vertex is far enough from other solution vertices.
01981       Standard_Integer ii = 1;
01982       for (; ii <= ivs; ii++) {
01983         if (BRepTools::Compare(TopoDS::Vertex(V1(ii)), Vcur)) {
01984           continue;
01985         }
01986       }
01987       ivs++;
01988       vertSol(ivs) = sol;
01989       V1(ivs) = Vcur;
01990       V2(ivs) = dst.SupportOnShape2(sol);
01991     }
01992   }
01993 
01994   // As we deal only with quadrangles,
01995   // 2, 3 or 4 vertex solutions can be found.
01996   if (ivs <= 1) {
01997     if (nbEdges > 0) {
01998       return REL_COLLISION_FF;
01999     }
02000     return REL_NOT_CONNECTED;
02001   }
02002   if (ivs > 4) {
02003     return REL_UNKNOWN;
02004   }
02005 
02006   // Check sharing of coincident entities.
02007   if (ivs == 2 || ivs == 3) {
02008     // Map vertices and edges of the blocks
02009     TopTools_IndexedDataMapOfShapeListOfShape MVE1, MVE2;
02010     GEOMImpl_Block6Explorer::MapShapesAndAncestors
02011       (theBlock1, TopAbs_VERTEX, TopAbs_EDGE, MVE1);
02012     GEOMImpl_Block6Explorer::MapShapesAndAncestors
02013       (theBlock2, TopAbs_VERTEX, TopAbs_EDGE, MVE2);
02014 
02015     if (ivs == 2) {
02016       // Find common edge
02017       TopoDS_Shape anEdge1, anEdge2;
02018       GEOMImpl_Block6Explorer::FindEdge(anEdge1, V1(1), V1(2), MVE1);
02019       if (anEdge1.IsNull()) return REL_UNKNOWN;
02020 
02021       GEOMImpl_Block6Explorer::FindEdge(anEdge2, V2(1), V2(2), MVE2);
02022       if (anEdge2.IsNull()) return REL_UNKNOWN;
02023 
02024       if (!anEdge1.IsSame(anEdge2)) return REL_NOT_GLUED;
02025 
02026     } else { // ivs == 3
02027       // Find common edges
02028       Standard_Integer e1_v1 = 1;
02029       Standard_Integer e1_v2 = 2;
02030       Standard_Integer e2_v1 = 3;
02031       Standard_Integer e2_v2 = 1;
02032 
02033       TopoDS_Shape anEdge11, anEdge12;
02034       GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
02035       if (anEdge11.IsNull()) {
02036         e1_v2 = 3;
02037         e2_v1 = 2;
02038         GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1);
02039         if (anEdge11.IsNull()) return REL_UNKNOWN;
02040       }
02041       GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
02042       if (anEdge12.IsNull()) {
02043         e2_v2 = 5 - e2_v1;
02044         GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1);
02045         if (anEdge12.IsNull()) return REL_UNKNOWN;
02046       }
02047 
02048       TopoDS_Shape anEdge21, anEdge22;
02049       GEOMImpl_Block6Explorer::FindEdge(anEdge21, V2(e1_v1), V2(e1_v2), MVE2);
02050       if (anEdge21.IsNull()) return REL_UNKNOWN;
02051       GEOMImpl_Block6Explorer::FindEdge(anEdge22, V2(e2_v1), V2(e2_v2), MVE2);
02052       if (anEdge22.IsNull()) return REL_UNKNOWN;
02053 
02054       // Check of edges coincidence (with some precision) have to be done here
02055       // if (!anEdge11.IsEqual(anEdge21)) return REL_UNKNOWN;
02056       // if (!anEdge12.IsEqual(anEdge22)) return REL_UNKNOWN;
02057 
02058       // Check of edges sharing
02059       if (!anEdge11.IsSame(anEdge21)) return REL_NOT_GLUED;
02060       if (!anEdge12.IsSame(anEdge22)) return REL_NOT_GLUED;
02061     }
02062   }
02063 
02064   if (ivs == 4) {
02065     // Map vertices and faces of the blocks
02066     TopTools_IndexedDataMapOfShapeListOfShape MVF1, MVF2;
02067     GEOMImpl_Block6Explorer::MapShapesAndAncestors
02068       (theBlock1, TopAbs_VERTEX, TopAbs_FACE, MVF1);
02069     GEOMImpl_Block6Explorer::MapShapesAndAncestors
02070       (theBlock2, TopAbs_VERTEX, TopAbs_FACE, MVF2);
02071 
02072     TopoDS_Shape aFace1, aFace2;
02073     GEOMImpl_Block6Explorer::FindFace(aFace1, V1(1), V1(2), V1(3), V1(4), MVF1);
02074     if (aFace1.IsNull()) return REL_UNKNOWN;
02075     GEOMImpl_Block6Explorer::FindFace(aFace2, V2(1), V2(2), V2(3), V2(4), MVF2);
02076     if (aFace2.IsNull()) return REL_UNKNOWN;
02077 
02078     // Check of faces coincidence (with some precision) have to be done here
02079     // if (!aFace1.IsEqual(aFace2)) return REL_UNKNOWN;
02080 
02081     // Check of faces sharing
02082     if (!aFace1.IsSame(aFace2)) return REL_NOT_GLUED;
02083   }
02084 
02085   return REL_OK;
02086 }
02087 
02088 void FindConnected (const Standard_Integer         theBlockIndex,
02089                     const TColStd_Array2OfInteger& theRelations,
02090                     TColStd_MapOfInteger&          theProcessedMap,
02091                     TColStd_MapOfInteger&          theConnectedMap)
02092 {
02093   theConnectedMap.Add(theBlockIndex);
02094   theProcessedMap.Add(theBlockIndex);
02095 
02096   Standard_Integer nbBlocks = theRelations.ColLength();
02097   Standard_Integer col = 1;
02098   for (; col <= nbBlocks; col++) {
02099     if (theRelations(theBlockIndex, col) == REL_OK ||
02100         theRelations(theBlockIndex, col) == REL_NOT_GLUED) {
02101       if (!theProcessedMap.Contains(col)) {
02102         FindConnected(col, theRelations, theProcessedMap, theConnectedMap);
02103       }
02104     }
02105   }
02106 }
02107 
02108 Standard_Boolean HasAnyConnection (const Standard_Integer         theBlockIndex,
02109                                    const TColStd_MapOfInteger&    theWith,
02110                                    const TColStd_Array2OfInteger& theRelations,
02111                                    TColStd_MapOfInteger&          theProcessedMap)
02112 {
02113   theProcessedMap.Add(theBlockIndex);
02114 
02115   Standard_Integer nbBlocks = theRelations.ColLength();
02116   Standard_Integer col = 1;
02117   for (; col <= nbBlocks; col++) {
02118     if (theRelations(theBlockIndex, col) != REL_NOT_CONNECTED) {
02119       if (!theProcessedMap.Contains(col)) {
02120         if (theWith.Contains(col))
02121           return Standard_True;
02122         if (HasAnyConnection(col, theWith, theRelations, theProcessedMap))
02123           return Standard_True;
02124       }
02125     }
02126   }
02127 
02128   return Standard_False;
02129 }
02130 
02131 //=============================================================================
02135 //=============================================================================
02136 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocksOld
02137                                                 (Handle(GEOM_Object) theCompound,
02138                                                  std::list<BCError>&      theErrors)
02139 {
02140   SetErrorCode(KO);
02141 
02142   if (theCompound.IsNull()) return Standard_False;
02143   TopoDS_Shape aBlockOrComp = theCompound->GetValue();
02144 
02145   Standard_Boolean isCompOfBlocks = Standard_True;
02146 
02147   // Map sub-shapes and their indices
02148   TopTools_IndexedMapOfShape anIndices;
02149   TopExp::MapShapes(aBlockOrComp, anIndices);
02150 
02151   // 1. Report non-blocks
02152   TopTools_ListOfShape NOT; // Not blocks
02153   TopTools_ListOfShape DEG; // Hexahedral solids, having degenerated edges
02154   TopTools_ListOfShape SEA; // Hexahedral solids, having seam edges
02155   TopTools_ListOfShape BLO; // All blocks from the given compound
02156   AddBlocksFromOld(aBlockOrComp, BLO, NOT, DEG, SEA);
02157 
02158   if (NOT.Extent() > 0) {
02159     isCompOfBlocks = Standard_False;
02160     BCError anErr;
02161     anErr.error = NOT_BLOCK;
02162     TopTools_ListIteratorOfListOfShape it (NOT);
02163     for (; it.More(); it.Next()) {
02164       anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
02165     }
02166     theErrors.push_back(anErr);
02167   }
02168 
02169   if (DEG.Extent() > 0 || SEA.Extent() > 0) {
02170     isCompOfBlocks = Standard_False;
02171     BCError anErr;
02172     anErr.error = EXTRA_EDGE;
02173 
02174     TopTools_ListIteratorOfListOfShape itDEG (DEG);
02175     for (; itDEG.More(); itDEG.Next()) {
02176       anErr.incriminated.push_back(anIndices.FindIndex(itDEG.Value()));
02177     }
02178 
02179     TopTools_ListIteratorOfListOfShape itSEA (SEA);
02180     for (; itSEA.More(); itSEA.Next()) {
02181       anErr.incriminated.push_back(anIndices.FindIndex(itSEA.Value()));
02182     }
02183 
02184     theErrors.push_back(anErr);
02185   }
02186 
02187   Standard_Integer nbBlocks = BLO.Extent();
02188   if (nbBlocks == 0) {
02189     isCompOfBlocks = Standard_False;
02190     SetErrorCode(OK);
02191     return isCompOfBlocks;
02192   }
02193   if (nbBlocks == 1) {
02194     SetErrorCode(OK);
02195     return isCompOfBlocks;
02196   }
02197 
02198   // Convert list of blocks into array for easy and fast access
02199   Standard_Integer ibl = 1;
02200   TopTools_Array1OfShape aBlocks (1, nbBlocks);
02201   TopTools_ListIteratorOfListOfShape BLOit (BLO);
02202   for (; BLOit.More(); BLOit.Next(), ibl++) {
02203     aBlocks.SetValue(ibl, BLOit.Value());
02204   }
02205 
02206   // 2. Find relations between all blocks,
02207   //    report connection errors (NOT_GLUED and INVALID_CONNECTION)
02208   TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
02209   aRelations.Init(REL_NOT_CONNECTED);
02210 
02211   Standard_Integer row = 1;
02212   for (row = 1; row <= nbBlocks; row++) {
02213     TopoDS_Shape aBlock = aBlocks.Value(row);
02214 
02215     Standard_Integer col = row + 1;
02216     for (; col <= nbBlocks; col++) {
02217       Standard_Integer aRel = BlocksRelation(aBlock, aBlocks.Value(col));
02218       if (aRel != REL_NOT_CONNECTED) {
02219         aRelations.SetValue(row, col, aRel);
02220         aRelations.SetValue(col, row, aRel);
02221         if (aRel == REL_NOT_GLUED) {
02222           // report connection error
02223           isCompOfBlocks = Standard_False;
02224           BCError anErr;
02225           anErr.error = NOT_GLUED;
02226           anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
02227           anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
02228           theErrors.push_back(anErr);
02229         } else if (aRel == REL_COLLISION_VV ||
02230                    aRel == REL_COLLISION_FF ||
02231                    aRel == REL_COLLISION_EE ||
02232                    aRel == REL_UNKNOWN) {
02233           // report connection error
02234           isCompOfBlocks = Standard_False;
02235           BCError anErr;
02236           anErr.error = INVALID_CONNECTION;
02237           anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row)));
02238           anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col)));
02239           theErrors.push_back(anErr);
02240         } else {
02241         }
02242       }
02243     }
02244   }
02245 
02246   // 3. Find largest set of connected (good connection or not glued) blocks
02247   TColStd_MapOfInteger aProcessedMap;
02248   TColStd_MapOfInteger aLargestSet;
02249   TColStd_MapOfInteger aCurrentSet;
02250   for (ibl = 1; ibl <= nbBlocks; ibl++) {
02251     if (!aProcessedMap.Contains(ibl)) {
02252       aCurrentSet.Clear();
02253       FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
02254       if (aCurrentSet.Extent() > aLargestSet.Extent()) {
02255         aLargestSet = aCurrentSet;
02256       }
02257     }
02258   }
02259 
02260   // 4. Report all blocks, isolated from <aLargestSet>
02261   BCError anErr;
02262   anErr.error = NOT_CONNECTED;
02263   Standard_Boolean hasIsolated = Standard_False;
02264   for (ibl = 1; ibl <= nbBlocks; ibl++) {
02265     if (!aLargestSet.Contains(ibl)) {
02266       aProcessedMap.Clear();
02267       if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
02268         // report connection absence
02269         hasIsolated = Standard_True;
02270         anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(ibl)));
02271       }
02272     }
02273   }
02274   if (hasIsolated) {
02275     isCompOfBlocks = Standard_False;
02276     theErrors.push_back(anErr);
02277   }
02278 
02279   SetErrorCode(OK);
02280   return isCompOfBlocks;
02281 }
02282 
02283 //=============================================================================
02287 //=============================================================================
02288 TCollection_AsciiString GEOMImpl_IBlocksOperations::PrintBCErrors
02289                                                 (Handle(GEOM_Object)  theCompound,
02290                                                  const std::list<BCError>& theErrors)
02291 {
02292   TCollection_AsciiString aDescr;
02293 
02294   std::list<BCError>::const_iterator errIt = theErrors.begin();
02295   int i = 0;
02296   for (; errIt != theErrors.end(); i++, errIt++) {
02297     BCError errStruct = *errIt;
02298 
02299     switch (errStruct.error) {
02300     case NOT_BLOCK:
02301       aDescr += "\n\tNot a Blocks: ";
02302       break;
02303     case EXTRA_EDGE:
02304       aDescr += "\n\tHexahedral solids with degenerated and/or seam edges: ";
02305       break;
02306     case INVALID_CONNECTION:
02307       aDescr += "\n\tInvalid connection between two blocks: ";
02308       break;
02309     case NOT_CONNECTED:
02310       aDescr += "\n\tBlocks, not connected with main body: ";
02311       break;
02312     case NOT_GLUED:
02313       aDescr += "\n\tNot glued blocks: ";
02314       break;
02315     default:
02316       break;
02317     }
02318 
02319     std::list<int> sshList = errStruct.incriminated;
02320     std::list<int>::iterator sshIt = sshList.begin();
02321     int jj = 0;
02322     for (; sshIt != sshList.end(); jj++, sshIt++) {
02323       if (jj > 0)
02324         aDescr += ", ";
02325       aDescr += TCollection_AsciiString(*sshIt);
02326     }
02327   }
02328 
02329   return aDescr;
02330 }
02331 
02332 //=============================================================================
02336 //=============================================================================
02337 Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks
02338                                               (Handle(GEOM_Object) theCompound,
02339                                                std::list<BCError>& theErrors)
02340 {
02341   SetErrorCode(KO);
02342 
02343   if (theCompound.IsNull()) return Standard_False;
02344   TopoDS_Shape aBlockOrComp = theCompound->GetValue();
02345 
02346   Standard_Boolean isCompOfBlocks = Standard_True;
02347 
02348   // Map sub-shapes and their indices
02349   TopTools_IndexedMapOfShape anIndices;
02350   TopExp::MapShapes(aBlockOrComp, anIndices);
02351 
02352   // 1. Separate blocks from non-blocks
02353   TopTools_ListOfShape NOT; // Not blocks
02354   TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
02355   TopTools_ListOfShape BLO; // All blocks from the given compound
02356   AddBlocksFrom(aBlockOrComp, BLO, NOT, EXT);
02357 
02358   // Report non-blocks
02359   if (NOT.Extent() > 0) {
02360     isCompOfBlocks = Standard_False;
02361     BCError anErr;
02362     anErr.error = NOT_BLOCK;
02363     TopTools_ListIteratorOfListOfShape it (NOT);
02364     for (; it.More(); it.Next()) {
02365       anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
02366     }
02367     theErrors.push_back(anErr);
02368   }
02369 
02370   // Report solids, having degenerated and/or seam edges
02371   if (EXT.Extent() > 0) {
02372     isCompOfBlocks = Standard_False;
02373     BCError anErr;
02374     anErr.error = EXTRA_EDGE;
02375     TopTools_ListIteratorOfListOfShape it (EXT);
02376     for (; it.More(); it.Next()) {
02377       anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
02378     }
02379     theErrors.push_back(anErr);
02380   }
02381 
02382   Standard_Integer nbBlocks = BLO.Extent();
02383   if (nbBlocks == 0) {
02384     isCompOfBlocks = Standard_False;
02385     SetErrorCode(OK);
02386     return isCompOfBlocks;
02387   }
02388   if (nbBlocks == 1) {
02389     SetErrorCode(OK);
02390     return isCompOfBlocks;
02391   }
02392 
02393   // Prepare data for 2. and 3.
02394   TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
02395   aRelations.Init(REL_NOT_CONNECTED);
02396 
02397   TopTools_IndexedMapOfShape mapBlocks;
02398 
02399   BRep_Builder BB;
02400   TopoDS_Compound aComp;
02401   BB.MakeCompound(aComp);
02402 
02403   TopTools_ListIteratorOfListOfShape BLOit (BLO);
02404   for (; BLOit.More(); BLOit.Next()) {
02405     mapBlocks.Add(BLOit.Value());
02406     BB.Add(aComp, BLOit.Value());
02407   }
02408 
02409   // 2. Find glued blocks (having shared faces)
02410   TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
02411   GEOMImpl_Block6Explorer::MapShapesAndAncestors
02412     (aComp, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
02413 
02414   Standard_Integer prevInd = 0, curInd = 0;
02415   Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
02416   for (; ind <= nbFaces; ind++) {
02417     const TopTools_ListOfShape& aGluedBlocks = mapFaceBlocks.FindFromIndex(ind);
02418     if (aGluedBlocks.Extent() > 1) { // Shared face found
02419       TopTools_ListIteratorOfListOfShape aGluedBlocksIt (aGluedBlocks);
02420       TopoDS_Shape prevBlock, curBlock;
02421       for (; aGluedBlocksIt.More(); aGluedBlocksIt.Next()) {
02422         curBlock = aGluedBlocksIt.Value();
02423         if (!prevBlock.IsNull()) {
02424           prevInd = mapBlocks.FindIndex(prevBlock);
02425           curInd  = mapBlocks.FindIndex(curBlock);
02426           aRelations.SetValue(prevInd, curInd, REL_OK);
02427           aRelations.SetValue(curInd, prevInd, REL_OK);
02428         }
02429         prevBlock = curBlock;
02430       }
02431     }
02432   }
02433 
02434   // 3. Find not glued blocks
02435   GEOMAlgo_GlueAnalyser aGD;
02436 
02437   aGD.SetShape(aComp);
02438   aGD.SetTolerance(Precision::Confusion());
02439   aGD.SetCheckGeometry(Standard_True);
02440   aGD.Perform();
02441 
02442   Standard_Integer iErr, iWrn;
02443   iErr = aGD.ErrorStatus();
02444   if (iErr) {
02445     SetErrorCode("Error in GEOMAlgo_GlueAnalyser");
02446     return isCompOfBlocks;
02447   }
02448   iWrn = aGD.WarningStatus();
02449   if (iWrn) {
02450     MESSAGE("Warning in GEOMAlgo_GlueAnalyser");
02451   }
02452 
02453   // Report not glued blocks
02454   if (aGD.HasSolidsToGlue()) {
02455     isCompOfBlocks = Standard_False;
02456     Standard_Integer aSx1Ind, aSx2Ind;
02457 
02458     const GEOMAlgo_ListOfCoupleOfShapes& aLCS = aGD.SolidsToGlue();
02459     GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS (aLCS);
02460     for (; aItCS.More(); aItCS.Next()) {
02461       const GEOMAlgo_CoupleOfShapes& aCS = aItCS.Value();
02462       const TopoDS_Shape& aSx1 = aCS.Shape1();
02463       const TopoDS_Shape& aSx2 = aCS.Shape2();
02464 
02465       aSx1Ind = mapBlocks.FindIndex(aSx1);
02466       aSx2Ind = mapBlocks.FindIndex(aSx2);
02467       aRelations.SetValue(aSx1Ind, aSx2Ind, NOT_GLUED);
02468       aRelations.SetValue(aSx2Ind, aSx1Ind, NOT_GLUED);
02469 
02470       BCError anErr;
02471       anErr.error = NOT_GLUED;
02472       anErr.incriminated.push_back(anIndices.FindIndex(aSx1));
02473       anErr.incriminated.push_back(anIndices.FindIndex(aSx2));
02474       theErrors.push_back(anErr);
02475     }
02476   }
02477 
02478   // 4. Find largest set of connected (good connection or not glued) blocks
02479   Standard_Integer ibl = 1;
02480   TColStd_MapOfInteger aProcessedMap;
02481   TColStd_MapOfInteger aLargestSet;
02482   TColStd_MapOfInteger aCurrentSet;
02483   for (ibl = 1; ibl <= nbBlocks; ibl++) {
02484     if (!aProcessedMap.Contains(ibl)) {
02485       aCurrentSet.Clear();
02486       FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
02487       if (aCurrentSet.Extent() > aLargestSet.Extent()) {
02488         aLargestSet = aCurrentSet;
02489       }
02490     }
02491   }
02492 
02493   // 5. Report all blocks, isolated from <aLargestSet>
02494   BCError anErr;
02495   anErr.error = NOT_CONNECTED;
02496   Standard_Boolean hasIsolated = Standard_False;
02497   for (ibl = 1; ibl <= nbBlocks; ibl++) {
02498     if (!aLargestSet.Contains(ibl)) {
02499       aProcessedMap.Clear();
02500       if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
02501         // report connection absence
02502         hasIsolated = Standard_True;
02503         anErr.incriminated.push_back(anIndices.FindIndex(mapBlocks.FindKey(ibl)));
02504       }
02505     }
02506   }
02507   if (hasIsolated) {
02508     isCompOfBlocks = Standard_False;
02509     theErrors.push_back(anErr);
02510   }
02511 
02512   SetErrorCode(OK);
02513   return isCompOfBlocks;
02514 }
02515 
02516 //=============================================================================
02520 //=============================================================================
02521 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::RemoveExtraEdges
02522                                      (Handle(GEOM_Object) theObject,
02523                                       const Standard_Integer theOptimumNbFaces)
02524 {
02525   SetErrorCode(KO);
02526 
02527   if (theObject.IsNull()) return NULL;
02528 
02529   Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
02530   if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
02531 
02532   //Add a new Copy object
02533   Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
02534 
02535   //Add a function
02536   Handle(GEOM_Function) aFunction =
02537     aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_REMOVE_EXTRA);
02538 
02539   //Check if the function is set correctly
02540   if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
02541 
02542   GEOMImpl_IBlockTrsf aTI (aFunction);
02543   aTI.SetOriginal(aLastFunction);
02544   aTI.SetOptimumNbFaces(theOptimumNbFaces);
02545 
02546   //Compute the fixed shape
02547   try {
02548 #if OCC_VERSION_LARGE > 0x06010000
02549     OCC_CATCH_SIGNALS;
02550 #endif
02551     if (!GetSolver()->ComputeFunction(aFunction)) {
02552       SetErrorCode("Block driver failed to remove extra edges of the given shape");
02553       return NULL;
02554     }
02555   }
02556   catch (Standard_Failure) {
02557     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
02558     SetErrorCode(aFail->GetMessageString());
02559     return NULL;
02560   }
02561 
02562   //Make a Python command
02563   std::string doUnionFaces = (theOptimumNbFaces < 0) ? "False" : "True";
02564   GEOM::TPythonDump(aFunction) << aCopy << " = geompy.RemoveExtraEdges("
02565                                << theObject << ", " << doUnionFaces.data() << ")";
02566 
02567   SetErrorCode(OK);
02568   return aCopy;
02569 }
02570 
02571 //=============================================================================
02575 //=============================================================================
02576 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::CheckAndImprove
02577                                              (Handle(GEOM_Object) theObject)
02578 {
02579   SetErrorCode(KO);
02580 
02581   if (theObject.IsNull()) return NULL;
02582 
02583   Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
02584   if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
02585 
02586   //Add a new Copy object
02587   Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
02588 
02589   //Add a function
02590   Handle(GEOM_Function) aFunction =
02591     aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_IMPROVE);
02592 
02593   //Check if the function is set correctly
02594   if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
02595 
02596   GEOMImpl_IBlockTrsf aTI (aFunction);
02597   aTI.SetOriginal(aLastFunction);
02598 
02599   // -1 means do not unite faces on common surface (?except case of seam edge between them?)
02600   //aTI.SetOptimumNbFaces(-1);
02601   aTI.SetOptimumNbFaces(6);
02602 
02603   //Compute the fixed shape
02604   try {
02605 #if OCC_VERSION_LARGE > 0x06010000
02606     OCC_CATCH_SIGNALS;
02607 #endif
02608     if (!GetSolver()->ComputeFunction(aFunction)) {
02609       SetErrorCode("Block driver failed to improve the given blocks compound");
02610       return NULL;
02611     }
02612   }
02613   catch (Standard_Failure) {
02614     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
02615     SetErrorCode(aFail->GetMessageString());
02616     return NULL;
02617   }
02618 
02619   //Make a Python command
02620   GEOM::TPythonDump(aFunction) << aCopy
02621     << " = geompy.CheckAndImprove(" << theObject << ")";
02622 
02623   SetErrorCode(OK);
02624   return aCopy;
02625 }
02626 
02627 //=============================================================================
02631 //=============================================================================
02632 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::ExplodeCompoundOfBlocks
02633                                                 (Handle(GEOM_Object)    theCompound,
02634                                                  const Standard_Integer theMinNbFaces,
02635                                                  const Standard_Integer theMaxNbFaces)
02636 {
02637   SetErrorCode(KO);
02638 
02639   if (theCompound.IsNull()) return NULL;
02640   TopoDS_Shape aBlockOrComp = theCompound->GetValue();
02641   if (aBlockOrComp.IsNull()) return NULL;
02642 
02643   Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
02644   Handle(GEOM_Object) anObj;
02645   Handle(GEOM_Function) aFunction;
02646 
02647   TopTools_MapOfShape mapShape;
02648   TCollection_AsciiString anAsciiList, anEntry;
02649 
02650   // Map shapes
02651   TopTools_IndexedMapOfShape anIndices;
02652   TopExp::MapShapes(aBlockOrComp, anIndices);
02653   Handle(TColStd_HArray1OfInteger) anArray;
02654 
02655   // Explode
02656   try {
02657 #if OCC_VERSION_LARGE > 0x06010000
02658     OCC_CATCH_SIGNALS;
02659 #endif
02660     TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
02661     for (; exp.More(); exp.Next()) {
02662       if (mapShape.Add(exp.Current())) {
02663         TopoDS_Shape aSolid = exp.Current();
02664 
02665         TopTools_MapOfShape mapFaces;
02666         TopExp_Explorer expF (aSolid, TopAbs_FACE);
02667         Standard_Integer nbFaces = 0;
02668         for (; expF.More(); expF.Next()) {
02669           if (mapFaces.Add(expF.Current())) {
02670             nbFaces++;
02671           }
02672         }
02673 
02674         if (theMinNbFaces <= nbFaces && nbFaces <= theMaxNbFaces) {
02675           anArray = new TColStd_HArray1OfInteger(1,1);
02676           anArray->SetValue(1, anIndices.FindIndex(aSolid));
02677           anObj = GetEngine()->AddSubShape(theCompound, anArray);
02678           aBlocks->Append(anObj);
02679 
02680           //Make a Python command
02681           TDF_Tool::Entry(anObj->GetEntry(), anEntry);
02682           anAsciiList += anEntry + ", ";
02683         }
02684       }
02685     }
02686   }
02687   catch (Standard_Failure) {
02688     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
02689     SetErrorCode(aFail->GetMessageString());
02690     return aBlocks;
02691   }
02692 
02693   if (aBlocks->IsEmpty()) {
02694     SetErrorCode("There are no specified blocks in the given shape");
02695     return aBlocks;
02696   }
02697 
02698   anAsciiList.Trunc(anAsciiList.Length() - 2);
02699 
02700   //The explode doesn't change object so no new function is required.
02701   aFunction = theCompound->GetLastFunction();
02702 
02703   //Make a Python command
02704   GEOM::TPythonDump(aFunction, /*append=*/true)
02705     << "[" << anAsciiList.ToCString() << "] = geompy.MakeBlockExplode("
02706     << theCompound << ", " << theMinNbFaces << ", " << theMaxNbFaces << ")";
02707 
02708   SetErrorCode(OK);
02709   return aBlocks;
02710 }
02711 
02712 //=============================================================================
02716 //=============================================================================
02717 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockNearPoint
02718                                                 (Handle(GEOM_Object) theCompound,
02719                                                  Handle(GEOM_Object) thePoint)
02720 {
02721   SetErrorCode(KO);
02722 
02723   //New object
02724   Handle(GEOM_Object) aResult;
02725 
02726   // Arguments
02727   if (theCompound.IsNull() || thePoint.IsNull()) return NULL;
02728 
02729   TopoDS_Shape aBlockOrComp = theCompound->GetValue();
02730   if (aBlockOrComp.IsNull()) {
02731     SetErrorCode("Compound is null");
02732     return NULL;
02733   }
02734   if (aBlockOrComp.ShapeType() != TopAbs_COMPOUND &&
02735       aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) {
02736     SetErrorCode("Shape to find block in is not a compound");
02737     return NULL;
02738   }
02739 
02740   TopoDS_Shape anArg = thePoint->GetValue();
02741   if (anArg.IsNull()) {
02742     SetErrorCode("Point is null");
02743     return NULL;
02744   }
02745   if (anArg.ShapeType() != TopAbs_VERTEX) {
02746     SetErrorCode("Shape for block identification is not a vertex");
02747     return NULL;
02748   }
02749 
02750   //Compute the Block value
02751   try {
02752 #if OCC_VERSION_LARGE > 0x06010000
02753     OCC_CATCH_SIGNALS;
02754 #endif
02755     TopoDS_Shape aShape;
02756 
02757     TopoDS_Vertex aVert = TopoDS::Vertex(anArg);
02758     gp_Pnt aPnt = BRep_Tool::Pnt(aVert);
02759     Standard_Real PX, PY, PZ;
02760     aPnt.Coord(PX, PY, PZ);
02761 
02762     // 1. Classify the point relatively each block
02763     Standard_Integer nearest = 2, nbFound = 0;
02764     TopTools_DataMapOfShapeInteger mapShapeDist;
02765     TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
02766     for (; exp.More(); exp.Next()) {
02767       TopoDS_Shape aSolid = exp.Current();
02768 
02769       if (!mapShapeDist.IsBound(aSolid)) {
02770         Standard_Integer aDistance = 2;
02771 
02772         // 1.a. Classify relatively Bounding box
02773         Standard_Real Xmin, Ymin, Zmin, Xmax, Ymax, Zmax;
02774         Bnd_Box BB;
02775         BRepBndLib::Add(aSolid, BB);
02776         BB.Get(Xmin, Ymin, Zmin, Xmax, Ymax, Zmax);
02777         if (PX < Xmin || Xmax < PX ||
02778             PY < Ymin || Ymax < PY ||
02779             PZ < Zmin || Zmax < PZ) {
02780           // OUT of bounding box
02781           aDistance = 1;
02782         } else {
02783           // 1.b. Classify relatively the solid itself
02784           BRepClass3d_SolidClassifier SC (aSolid, aPnt, Precision::Confusion());
02785           if (SC.State() == TopAbs_IN) {
02786             aDistance = -1;
02787           } else if (SC.State() == TopAbs_ON) {
02788             aDistance = 0;
02789           } else { // OUT
02790             aDistance = 1;
02791           }
02792         }
02793 
02794         if (aDistance < nearest) {
02795           nearest = aDistance;
02796           aShape = aSolid;
02797           nbFound = 1;
02798 
02799           // A first found block, containing the point inside, will be returned.
02800           // It is the solution, if there are no intersecting blocks in the compound.
02801           if (nearest == -1) break;
02802 
02803         } else if (aDistance == nearest) {
02804           nbFound++;
02805         } else {
02806         }
02807 
02808         mapShapeDist.Bind(aSolid, aDistance);
02809       } // if (!mapShapeDist.IsBound(aSolid))
02810     }
02811 
02812     // 2. Define block, containing the point or having minimum distance to it
02813     if (nbFound > 1) {
02814       if (nearest == 0) {
02815         // The point is on boundary of some blocks and there are
02816         // no blocks, having the point inside their volume
02817         SetErrorCode("Multiple blocks near the given point are found");
02818         return NULL;
02819 
02820       } else if (nearest == 1) {
02821         // The point is outside some blocks and there are
02822         // no blocks, having the point inside or on boundary.
02823         // We will get a nearest block
02824         Standard_Real minDist = RealLast();
02825         TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
02826         for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
02827           if (mapShapeDistIter.Value() == 1) {
02828             TopoDS_Shape aSolid = mapShapeDistIter.Key();
02829             BRepExtrema_DistShapeShape aDistTool (aVert, aSolid);
02830             if (!aDistTool.IsDone()) {
02831               SetErrorCode("Can not find a distance from the given point to one of blocks");
02832               return NULL;
02833             }
02834             Standard_Real aDist = aDistTool.Value();
02835             if (aDist < minDist) {
02836               minDist = aDist;
02837               aShape = aSolid;
02838             }
02839           }
02840         }
02841       } else { // nearest == -1
02842 //        // The point is inside some blocks.
02843 //        // We will get a block with nearest center
02844 //        Standard_Real minDist = RealLast();
02845 //        TopTools_DataMapIteratorOfDataMapOfShapeInteger mapShapeDistIter (mapShapeDist);
02846 //        for (; mapShapeDistIter.More(); mapShapeDistIter.Next()) {
02847 //          if (mapShapeDistIter.Value() == -1) {
02848 //            TopoDS_Shape aSolid = mapShapeDistIter.Key();
02849 //            GProp_GProps aSystem;
02850 //            BRepGProp::VolumeProperties(aSolid, aSystem);
02851 //            gp_Pnt aCenterMass = aSystem.CentreOfMass();
02852 //
02853 //            Standard_Real aDist = aCenterMass.Distance(aPnt);
02854 //            if (aDist < minDist) {
02855 //              minDist = aDist;
02856 //              aShape = aSolid;
02857 //            }
02858 //          }
02859 //        }
02860       }
02861     } // if (nbFound > 1)
02862 
02863     if (nbFound == 0) {
02864       SetErrorCode("There are no blocks near the given point");
02865       return NULL;
02866     } else {
02867       TopTools_IndexedMapOfShape anIndices;
02868       TopExp::MapShapes(aBlockOrComp, anIndices);
02869       Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
02870       anArray->SetValue(1, anIndices.FindIndex(aShape));
02871       aResult = GetEngine()->AddSubShape(theCompound, anArray);
02872     }
02873   }
02874   catch (Standard_Failure) {
02875     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
02876     SetErrorCode(aFail->GetMessageString());
02877     return NULL;
02878   }
02879 
02880   Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
02881 
02882   //Make a Python command
02883   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockNearPoint("
02884                                << theCompound << ", " << thePoint << ")";
02885 
02886   SetErrorCode(OK);
02887   return aResult;
02888 }
02889 
02890 //=============================================================================
02894 //=============================================================================
02895 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockByParts
02896                       (Handle(GEOM_Object)                         theCompound,
02897                        const Handle(TColStd_HSequenceOfTransient)& theParts)
02898 {
02899   SetErrorCode(KO);
02900 
02901   Handle(GEOM_Object) aResult;
02902 
02903   if (theCompound.IsNull() || theParts.IsNull()) return NULL;
02904   TopoDS_Shape aBlockOrComp = theCompound->GetValue();
02905   if (aBlockOrComp.IsNull()) return NULL;
02906 
02907   //Get the parts
02908   Standard_Integer argi, aLen = theParts->Length();
02909   TopTools_Array1OfShape anArgs (1, aLen);
02910   TCollection_AsciiString anEntry, aPartsDescr;
02911   for (argi = 1; argi <= aLen; argi++) {
02912     Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
02913     Handle(GEOM_Function) aRef = anObj->GetLastFunction();
02914     if (aRef.IsNull()) return NULL;
02915 
02916     TopoDS_Shape anArg = aRef->GetValue();
02917     if (anArg.IsNull()) {
02918       SetErrorCode("Null shape is given as argument");
02919       return NULL;
02920     }
02921     anArgs(argi) = anArg;
02922 
02923     // For Python command
02924     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
02925     if (argi > 1) aPartsDescr += ", ";
02926     aPartsDescr += anEntry;
02927   }
02928 
02929   //Compute the Block value
02930   try {
02931 #if OCC_VERSION_LARGE > 0x06010000
02932     OCC_CATCH_SIGNALS;
02933 #endif
02934     // 1. Explode compound on solids
02935     TopTools_MapOfShape mapShape;
02936     Standard_Integer nbSolids = 0;
02937     TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
02938     for (; exp.More(); exp.Next()) {
02939       if (mapShape.Add(exp.Current())) {
02940         nbSolids++;
02941       }
02942     }
02943 
02944     mapShape.Clear();
02945     Standard_Integer ind = 1;
02946     TopTools_Array1OfShape aSolids (1, nbSolids);
02947     TColStd_Array1OfInteger aNbParts (1, nbSolids);
02948     for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
02949       if (mapShape.Add(exp.Current())) {
02950         TopoDS_Shape aSolid = exp.Current();
02951         aSolids(ind) = aSolid;
02952         aNbParts(ind) = 0;
02953 
02954         // 2. Define quantity of parts, contained in each solid
02955         TopTools_IndexedMapOfShape aSubShapes;
02956         TopExp::MapShapes(aSolid, aSubShapes);
02957         for (argi = 1; argi <= aLen; argi++) {
02958           if (aSubShapes.Contains(anArgs(argi))) {
02959             aNbParts(ind)++;
02960           }
02961         }
02962       }
02963     }
02964 
02965     // 3. Define solid, containing maximum quantity of parts
02966     Standard_Integer maxNb = 0, nbFound = 0;
02967     TopoDS_Shape aShape;
02968     for (ind = 1; ind <= nbSolids; ind++) {
02969       if (aNbParts(ind) > maxNb) {
02970         maxNb = aNbParts(ind);
02971         aShape = aSolids(ind);
02972         nbFound = 1;
02973       } else if (aNbParts(ind) == maxNb) {
02974         nbFound++;
02975       } else {
02976       }
02977     }
02978     if (nbFound > 1) {
02979       SetErrorCode("Multiple blocks, containing maximum quantity of the given parts, are found");
02980       return NULL;
02981     } else if (nbFound == 0) {
02982       SetErrorCode("There are no blocks, containing the given parts");
02983       return NULL;
02984     } else {
02985       TopTools_IndexedMapOfShape anIndices;
02986       TopExp::MapShapes(aBlockOrComp, anIndices);
02987       Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
02988       anArray->SetValue(1, anIndices.FindIndex(aShape));
02989       aResult = GetEngine()->AddSubShape(theCompound, anArray);
02990     }
02991   } catch (Standard_Failure) {
02992     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
02993     SetErrorCode(aFail->GetMessageString());
02994     return NULL;
02995   }
02996 
02997   Handle(GEOM_Function) aFunction = aResult->GetLastFunction();
02998 
02999   //Make a Python command
03000   GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetBlockByParts("
03001     << theCompound << ", [" << aPartsDescr.ToCString() << "])";
03002 
03003   SetErrorCode(OK);
03004   return aResult;
03005 }
03006 
03007 //=============================================================================
03011 //=============================================================================
03012 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::GetBlocksByParts
03013                       (Handle(GEOM_Object)                         theCompound,
03014                        const Handle(TColStd_HSequenceOfTransient)& theParts)
03015 {
03016   SetErrorCode(KO);
03017 
03018   if (theCompound.IsNull() || theParts.IsNull()) return NULL;
03019   TopoDS_Shape aBlockOrComp = theCompound->GetValue();
03020   if (aBlockOrComp.IsNull()) return NULL;
03021 
03022   Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient;
03023   Handle(GEOM_Object) anObj;
03024   Handle(GEOM_Function) aFunction;
03025 
03026   //Get the parts
03027   Standard_Integer argi, aLen = theParts->Length();
03028   TopTools_Array1OfShape anArgs (1, aLen);
03029   TCollection_AsciiString anEntry, aPartsDescr, anAsciiList;
03030 
03031   for (argi = 1; argi <= aLen; argi++) {
03032     Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi));
03033     Handle(GEOM_Function) aRef = anObj->GetLastFunction();
03034     if (aRef.IsNull()) return NULL;
03035 
03036     TopoDS_Shape anArg = aRef->GetValue();
03037     if (anArg.IsNull()) {
03038       SetErrorCode("Null shape is given as argument");
03039       return NULL;
03040     }
03041     anArgs(argi) = anArg;
03042 
03043     // For Python command
03044     TDF_Tool::Entry(anObj->GetEntry(), anEntry);
03045     aPartsDescr += anEntry + ", ";
03046   }
03047 
03048   //Get the Blocks
03049   try {
03050 #if OCC_VERSION_LARGE > 0x06010000
03051     OCC_CATCH_SIGNALS;
03052 #endif
03053     TopTools_MapOfShape mapShape;
03054     Standard_Integer nbSolids = 0;
03055     TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID);
03056     for (; exp.More(); exp.Next()) {
03057       if (mapShape.Add(exp.Current())) {
03058         nbSolids++;
03059       }
03060     }
03061 
03062     mapShape.Clear();
03063     Standard_Integer ind = 1;
03064     TopTools_Array1OfShape aSolids (1, nbSolids);
03065     TColStd_Array1OfInteger aNbParts (1, nbSolids);
03066     for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) {
03067       if (mapShape.Add(exp.Current())) {
03068         TopoDS_Shape aSolid = exp.Current();
03069         aSolids(ind) = aSolid;
03070         aNbParts(ind) = 0;
03071 
03072         // 2. Define quantity of parts, contained in each solid
03073         TopTools_IndexedMapOfShape aSubShapes;
03074         TopExp::MapShapes(aSolid, aSubShapes);
03075         for (argi = 1; argi <= aLen; argi++) {
03076           if (aSubShapes.Contains(anArgs(argi))) {
03077             aNbParts(ind)++;
03078           }
03079         }
03080       }
03081     }
03082 
03083     // 3. Define solid, containing maximum quantity of parts
03084     Standard_Integer maxNb = 0, nbFound = 0;
03085     for (ind = 1; ind <= nbSolids; ind++) {
03086       if (aNbParts(ind) > maxNb) {
03087         maxNb = aNbParts(ind);
03088         nbFound = 1;
03089       } else if (aNbParts(ind) == maxNb) {
03090         nbFound++;
03091       } else {
03092       }
03093     }
03094     if (nbFound == 0) {
03095       SetErrorCode("There are no blocks, containing the given parts");
03096       return NULL;
03097     }
03098 
03099     // Map shapes
03100     TopTools_IndexedMapOfShape anIndices;
03101     TopExp::MapShapes(aBlockOrComp, anIndices);
03102     Handle(TColStd_HArray1OfInteger) anArray;
03103 
03104     for (ind = 1; ind <= nbSolids; ind++) {
03105       if (aNbParts(ind) == maxNb) {
03106         anArray = new TColStd_HArray1OfInteger(1,1);
03107         anArray->SetValue(1, anIndices.FindIndex(aSolids(ind)));
03108         anObj = GetEngine()->AddSubShape(theCompound, anArray);
03109         aBlocks->Append(anObj);
03110 
03111         // For Python command
03112         TDF_Tool::Entry(anObj->GetEntry(), anEntry);
03113         anAsciiList += anEntry + ", ";
03114         if (aFunction.IsNull())
03115           aFunction = anObj->GetLastFunction();
03116       }
03117     }
03118   }
03119   catch (Standard_Failure) {
03120     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
03121     SetErrorCode(aFail->GetMessageString());
03122     return NULL;
03123   }
03124 
03125   //Make a Python command
03126   aPartsDescr.Trunc(aPartsDescr.Length() - 2);
03127   anAsciiList.Trunc(anAsciiList.Length() - 2);
03128 
03129   GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
03130     << "] = geompy.GetBlocksByParts(" << theCompound
03131       << ", [" << aPartsDescr.ToCString() << "])";
03132 
03133   SetErrorCode(OK);
03134   return aBlocks;
03135 }
03136 
03137 //=============================================================================
03141 //=============================================================================
03142 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation1D
03143                                              (Handle(GEOM_Object)    theObject,
03144                                               const Standard_Integer theDirFace1,
03145                                               const Standard_Integer theDirFace2,
03146                                               const Standard_Integer theNbTimes)
03147 {
03148   SetErrorCode(KO);
03149 
03150   if (theObject.IsNull()) return NULL;
03151 
03152   Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
03153   if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
03154 
03155   //Add a new Copy object
03156   Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
03157 
03158   //Add a translate function
03159   Handle(GEOM_Function) aFunction =
03160     aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_1D);
03161 
03162   //Check if the function is set correctly
03163   if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
03164 
03165   GEOMImpl_IBlockTrsf aTI (aFunction);
03166   aTI.SetOriginal(aLastFunction);
03167   aTI.SetFace1U(theDirFace1);
03168   aTI.SetFace2U(theDirFace2);
03169   aTI.SetNbIterU(theNbTimes);
03170 
03171   //Compute the transformation
03172   try {
03173 #if OCC_VERSION_LARGE > 0x06010000
03174     OCC_CATCH_SIGNALS;
03175 #endif
03176     if (!GetSolver()->ComputeFunction(aFunction)) {
03177       SetErrorCode("Block driver failed to make multi-transformation");
03178       return NULL;
03179     }
03180   }
03181   catch (Standard_Failure) {
03182     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
03183     SetErrorCode(aFail->GetMessageString());
03184     return NULL;
03185   }
03186 
03187   //Make a Python command
03188   GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation1D("
03189     << theObject << ", " << theDirFace1 << ", " << theDirFace2 << ", " << theNbTimes << ")";
03190 
03191   SetErrorCode(OK);
03192   return aCopy;
03193 }
03194 
03195 //=============================================================================
03199 //=============================================================================
03200 Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation2D
03201                                              (Handle(GEOM_Object)    theObject,
03202                                               const Standard_Integer theDirFace1U,
03203                                               const Standard_Integer theDirFace2U,
03204                                               const Standard_Integer theNbTimesU,
03205                                               const Standard_Integer theDirFace1V,
03206                                               const Standard_Integer theDirFace2V,
03207                                               const Standard_Integer theNbTimesV)
03208 {
03209   SetErrorCode(KO);
03210 
03211   if (theObject.IsNull()) return NULL;
03212 
03213   Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
03214   if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be moved
03215 
03216   //Add a new Copy object
03217   Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
03218 
03219   //Add a translate function
03220   Handle(GEOM_Function) aFunction =
03221     aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_2D);
03222 
03223   //Check if the function is set correctly
03224   if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
03225 
03226   GEOMImpl_IBlockTrsf aTI (aFunction);
03227   aTI.SetOriginal(aLastFunction);
03228   aTI.SetFace1U(theDirFace1U);
03229   aTI.SetFace2U(theDirFace2U);
03230   aTI.SetNbIterU(theNbTimesU);
03231   aTI.SetFace1V(theDirFace1V);
03232   aTI.SetFace2V(theDirFace2V);
03233   aTI.SetNbIterV(theNbTimesV);
03234 
03235   //Compute the transformation
03236   try {
03237 #if OCC_VERSION_LARGE > 0x06010000
03238     OCC_CATCH_SIGNALS;
03239 #endif
03240     if (!GetSolver()->ComputeFunction(aFunction)) {
03241       SetErrorCode("Block driver failed to make multi-transformation");
03242       return NULL;
03243     }
03244   }
03245   catch (Standard_Failure) {
03246     Handle(Standard_Failure) aFail = Standard_Failure::Caught();
03247     SetErrorCode(aFail->GetMessageString());
03248     return NULL;
03249   }
03250 
03251   //Make a Python command
03252   GEOM::TPythonDump(aFunction) << aCopy << " = geompy.MakeMultiTransformation2D("
03253     << theObject << ", " << theDirFace1U << ", " << theDirFace2U << ", " << theNbTimesU
03254       << ", " << theDirFace1V << ", " << theDirFace2V << ", " << theNbTimesV << ")";
03255 
03256   SetErrorCode(OK);
03257   return aCopy;
03258 }
03259 
03260 //=============================================================================
03264 //=============================================================================
03265 Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::Propagate
03266                                                  (Handle(GEOM_Object) theShape)
03267 {
03268   SetErrorCode(KO);
03269 
03270   if (theShape.IsNull()) return NULL;
03271 
03272   TopoDS_Shape aShape = theShape->GetValue();
03273   if (aShape.IsNull()) return NULL;
03274 
03275   TopTools_IndexedMapOfShape anIndices;
03276   TopExp::MapShapes(aShape, anIndices);
03277 
03278   TopTools_IndexedDataMapOfShapeListOfShape MEW;
03279   GEOMImpl_Block6Explorer::MapShapesAndAncestors
03280     (aShape, TopAbs_EDGE, TopAbs_WIRE, MEW);
03281   Standard_Integer ie, nbEdges = MEW.Extent();
03282 
03283   // Result
03284   Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
03285 
03286   TopTools_MapOfShape mapAcceptedEdges;
03287   TCollection_AsciiString aListRes, anEntry;
03288 
03289   // Sort shapes in current chain (Mantis issue 21053)
03290   TopTools_DataMapOfShapeListOfShape aMapChains;
03291   TopTools_ListOfShape aFirstInChains;
03292 
03293   for (ie = 1; ie <= nbEdges; ie++) {
03294     TopoDS_Shape curE = MEW.FindKey(ie);
03295 
03296     if (mapAcceptedEdges.Contains(curE)) continue;
03297 
03298     // Build the chain
03299     TopTools_ListOfShape currentChain;
03300     TopTools_ListOfShape listPrevEdges;
03301 
03302     currentChain.Append(curE);
03303     listPrevEdges.Append(curE);
03304     mapAcceptedEdges.Add(curE);
03305 
03306     // Collect all edges pass by pass
03307     while (listPrevEdges.Extent() > 0) {
03308       // List of edges, added to chain on this cycle pass
03309       TopTools_ListOfShape listCurEdges;
03310 
03311       // Find the next portion of edges
03312       TopTools_ListIteratorOfListOfShape itE (listPrevEdges);
03313       for (; itE.More(); itE.Next()) {
03314         TopoDS_Shape anE = itE.Value();
03315 
03316         // Iterate on faces, having edge <anE>
03317         TopTools_ListIteratorOfListOfShape itW (MEW.FindFromKey(anE));
03318         for (; itW.More(); itW.Next()) {
03319           TopoDS_Shape aW = itW.Value();
03320           TopoDS_Shape anOppE;
03321 
03322           BRepTools_WireExplorer aWE (TopoDS::Wire(aW));
03323           Standard_Integer nb = 1, found = 0;
03324           TopTools_Array1OfShape anEdges (1,4);
03325           for (; aWE.More(); aWE.Next(), nb++) {
03326             if (nb > 4) {
03327               found = 0;
03328               break;
03329             }
03330             anEdges(nb) = aWE.Current();
03331             if (anEdges(nb).IsSame(anE)) found = nb;
03332           }
03333 
03334           if (nb == 5 && found > 0) {
03335             // Quadrangle face found, get an opposite edge
03336             Standard_Integer opp = found + 2;
03337             if (opp > 4) opp -= 4;
03338             anOppE = anEdges(opp);
03339 
03340             if (!mapAcceptedEdges.Contains(anOppE)) {
03341               // Add found edge to the chain
03342               currentChain.Append(anOppE);
03343               listCurEdges.Append(anOppE);
03344               mapAcceptedEdges.Add(anOppE);
03345             }
03346           } // if (nb == 5 && found > 0)
03347         } // for (; itF.More(); itF.Next())
03348       } // for (; itE.More(); itE.Next())
03349 
03350       listPrevEdges = listCurEdges;
03351     } // while (listPrevEdges.Extent() > 0)
03352 
03353     // Sort shapes in current chain (Mantis issue 21053)
03354     GEOMImpl_IShapesOperations::SortShapes(currentChain, Standard_False);
03355     aFirstInChains.Append(currentChain.First());
03356     aMapChains.Bind(currentChain.First(), currentChain);
03357   }
03358 
03359   // Sort chains (Mantis issue 21053)
03360   GEOMImpl_IShapesOperations::SortShapes(aFirstInChains, Standard_False);
03361 
03362   // Store sorted chains in the document
03363   TopTools_ListIteratorOfListOfShape aChainsIt (aFirstInChains);
03364   for (; aChainsIt.More(); aChainsIt.Next()) {
03365     TopoDS_Shape aFirstInChain = aChainsIt.Value();
03366     const TopTools_ListOfShape& currentChain = aMapChains.Find(aFirstInChain);
03367 
03368     // Store the chain in the document
03369     Handle(TColStd_HArray1OfInteger) anArray =
03370       new TColStd_HArray1OfInteger (1, currentChain.Extent());
03371 
03372     // Fill array of sub-shape indices
03373     TopTools_ListIteratorOfListOfShape itSub (currentChain);
03374     for (int index = 1; itSub.More(); itSub.Next(), ++index) {
03375       int id = anIndices.FindIndex(itSub.Value());
03376       anArray->SetValue(index, id);
03377     }
03378 
03379     // Add a new group object
03380     Handle(GEOM_Object) aChain = GetEngine()->AddSubShape(theShape, anArray);
03381 
03382     // Set a GROUP type
03383     aChain->SetType(GEOM_GROUP);
03384 
03385     // Set a sub-shape type
03386     TDF_Label aFreeLabel = aChain->GetFreeLabel();
03387     TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)TopAbs_EDGE);
03388 
03389     // Add the chain to the result
03390     aSeq->Append(aChain);
03391 
03392     //Make a Python command
03393     TDF_Tool::Entry(aChain->GetEntry(), anEntry);
03394     aListRes += anEntry + ", ";
03395   }
03396 
03397   if (aSeq->IsEmpty()) {
03398     SetErrorCode("There are no quadrangle faces in the shape");
03399     return aSeq;
03400   }
03401 
03402   aListRes.Trunc(aListRes.Length() - 2);
03403 
03404   // The Propagation doesn't change object so no new function is required.
03405   Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
03406 
03407   // Make a Python command
03408   GEOM::TPythonDump(aFunction, /*append=*/true)
03409     << "[" << aListRes.ToCString() << "] = geompy.Propagate(" << theShape << ")";
03410 
03411   SetErrorCode(OK);
03412   return aSeq;
03413 }