+//=============================================================================
+/*!
+ * CheckCompoundOfBlocks
+ */
+//=============================================================================
+Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks
+ (Handle(GEOM_Object) theCompound,
+ list<BCError>& theErrors)
+{
+ SetErrorCode(KO);
+
+ if (theCompound.IsNull()) return Standard_False;
+ TopoDS_Shape aBlockOrComp = theCompound->GetValue();
+
+ Standard_Boolean isCompOfBlocks = Standard_True;
+
+ // Map sub-shapes and their indices
+ TopTools_IndexedMapOfShape anIndices;
+ TopExp::MapShapes(aBlockOrComp, anIndices);
+
+ // 1. Separate blocks from non-blocks
+ TopTools_ListOfShape NOT; // Not blocks
+ TopTools_ListOfShape EXT; // Hexahedral solids, having degenerated and/or seam edges
+ TopTools_ListOfShape BLO; // All blocks from the given compound
+ AddBlocksFrom(aBlockOrComp, BLO, NOT, EXT);
+
+ // Report non-blocks
+ if (NOT.Extent() > 0) {
+ isCompOfBlocks = Standard_False;
+ BCError anErr;
+ anErr.error = NOT_BLOCK;
+ TopTools_ListIteratorOfListOfShape it (NOT);
+ for (; it.More(); it.Next()) {
+ anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
+ }
+ theErrors.push_back(anErr);
+ }
+
+ // Report solids, having degenerated and/or seam edges
+ if (EXT.Extent() > 0) {
+ isCompOfBlocks = Standard_False;
+ BCError anErr;
+ anErr.error = EXTRA_EDGE;
+ TopTools_ListIteratorOfListOfShape it (EXT);
+ for (; it.More(); it.Next()) {
+ anErr.incriminated.push_back(anIndices.FindIndex(it.Value()));
+ }
+ theErrors.push_back(anErr);
+ }
+
+ Standard_Integer nbBlocks = BLO.Extent();
+ if (nbBlocks == 0) {
+ isCompOfBlocks = Standard_False;
+ SetErrorCode(OK);
+ return isCompOfBlocks;
+ }
+ if (nbBlocks == 1) {
+ SetErrorCode(OK);
+ return isCompOfBlocks;
+ }
+
+ // Prepare data for 2. and 3.
+ TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks);
+ aRelations.Init(REL_NOT_CONNECTED);
+
+ TopTools_IndexedMapOfShape mapBlocks;
+
+ BRep_Builder BB;
+ TopoDS_Compound aComp;
+ BB.MakeCompound(aComp);
+
+ TopTools_ListIteratorOfListOfShape BLOit (BLO);
+ for (; BLOit.More(); BLOit.Next()) {
+ mapBlocks.Add(BLOit.Value());
+ BB.Add(aComp, BLOit.Value());
+ }
+
+ // 2. Find glued blocks (having shared faces)
+ TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
+ GEOMImpl_Block6Explorer::MapShapesAndAncestors
+ (aComp, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
+
+ Standard_Integer prevInd = 0, curInd = 0;
+ Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
+ for (; ind <= nbFaces; ind++) {
+ const TopTools_ListOfShape& aGluedBlocks = mapFaceBlocks.FindFromIndex(ind);
+ if (aGluedBlocks.Extent() > 1) { // Shared face found
+ TopTools_ListIteratorOfListOfShape aGluedBlocksIt (aGluedBlocks);
+ TopoDS_Shape prevBlock, curBlock;
+ for (; aGluedBlocksIt.More(); aGluedBlocksIt.Next()) {
+ curBlock = aGluedBlocksIt.Value();
+ if (!prevBlock.IsNull()) {
+ prevInd = mapBlocks.FindIndex(prevBlock);
+ curInd = mapBlocks.FindIndex(curBlock);
+ aRelations.SetValue(prevInd, curInd, REL_OK);
+ aRelations.SetValue(curInd, prevInd, REL_OK);
+ }
+ prevBlock = curBlock;
+ }
+ }
+ }
+
+ // 3. Find not glued blocks
+ GEOMAlgo_GlueAnalyser aGD;
+
+ aGD.SetShape(aComp);
+ aGD.SetTolerance(Precision::Confusion());
+ aGD.SetCheckGeometry(Standard_True);
+ aGD.Perform();
+
+ Standard_Integer iErr, iWrn;
+ iErr = aGD.ErrorStatus();
+ if (iErr) {
+ SetErrorCode("Error in GEOMAlgo_GlueAnalyser");
+ return isCompOfBlocks;
+ }
+ iWrn = aGD.WarningStatus();
+ if (iWrn) {
+ MESSAGE("Warning in GEOMAlgo_GlueAnalyser");
+ }
+
+ // Report not glued blocks
+ if (aGD.HasSolidsToGlue()) {
+ isCompOfBlocks = Standard_False;
+ Standard_Integer aSx1Ind, aSx2Ind;
+
+ const GEOMAlgo_ListOfCoupleOfShapes& aLCS = aGD.SolidsToGlue();
+ GEOMAlgo_ListIteratorOfListOfCoupleOfShapes aItCS (aLCS);
+ for (; aItCS.More(); aItCS.Next()) {
+ const GEOMAlgo_CoupleOfShapes& aCS = aItCS.Value();
+ const TopoDS_Shape& aSx1 = aCS.Shape1();
+ const TopoDS_Shape& aSx2 = aCS.Shape2();
+
+ aSx1Ind = mapBlocks.FindIndex(aSx1);
+ aSx2Ind = mapBlocks.FindIndex(aSx2);
+ aRelations.SetValue(aSx1Ind, aSx2Ind, NOT_GLUED);
+ aRelations.SetValue(aSx2Ind, aSx1Ind, NOT_GLUED);
+
+ BCError anErr;
+ anErr.error = NOT_GLUED;
+ anErr.incriminated.push_back(anIndices.FindIndex(aSx1));
+ anErr.incriminated.push_back(anIndices.FindIndex(aSx2));
+ theErrors.push_back(anErr);
+ }
+ }
+
+ // 4. Find largest set of connected (good connection or not glued) blocks
+ Standard_Integer ibl = 1;
+ TColStd_MapOfInteger aProcessedMap;
+ TColStd_MapOfInteger aLargestSet;
+ TColStd_MapOfInteger aCurrentSet;
+ for (ibl = 1; ibl <= nbBlocks; ibl++) {
+ if (!aProcessedMap.Contains(ibl)) {
+ aCurrentSet.Clear();
+ FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet);
+ if (aCurrentSet.Extent() > aLargestSet.Extent()) {
+ aLargestSet = aCurrentSet;
+ }
+ }
+ }
+
+ // 5. Report all blocks, isolated from <aLargestSet>
+ BCError anErr;
+ anErr.error = NOT_CONNECTED;
+ Standard_Boolean hasIsolated = Standard_False;
+ for (ibl = 1; ibl <= nbBlocks; ibl++) {
+ if (!aLargestSet.Contains(ibl)) {
+ aProcessedMap.Clear();
+ if (!HasAnyConnection(ibl, aLargestSet, aRelations, aProcessedMap)) {
+ // report connection absence
+ hasIsolated = Standard_True;
+ anErr.incriminated.push_back(anIndices.FindIndex(mapBlocks.FindKey(ibl)));
+ }
+ }
+ }
+ if (hasIsolated) {
+ isCompOfBlocks = Standard_False;
+ theErrors.push_back(anErr);
+ }
+
+ SetErrorCode(OK);
+ return isCompOfBlocks;
+}
+
+//=============================================================================
+/*!
+ * RemoveExtraEdges
+ */
+//=============================================================================
+Handle(GEOM_Object) GEOMImpl_IBlocksOperations::RemoveExtraEdges
+ (Handle(GEOM_Object) theObject)
+{
+ SetErrorCode(KO);
+
+ if (theObject.IsNull()) return NULL;
+
+ Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
+ if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
+
+ //Add a new Copy object
+ Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
+
+ //Add a function
+ Handle(GEOM_Function) aFunction =
+ aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_REMOVE_EXTRA);
+
+ //Check if the function is set correctly
+ if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
+
+ GEOMImpl_IBlockTrsf aTI (aFunction);
+ aTI.SetOriginal(aLastFunction);
+
+ //Compute the fixed shape
+ try {
+#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
+ OCC_CATCH_SIGNALS;
+#endif
+ if (!GetSolver()->ComputeFunction(aFunction)) {
+ SetErrorCode("Block driver failed to remove extra edges of the given shape");
+ return NULL;
+ }
+ }
+ catch (Standard_Failure) {
+ Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+ SetErrorCode(aFail->GetMessageString());
+ return NULL;
+ }
+
+ //Make a Python command
+ GEOM::TPythonDump(aFunction) << aCopy
+ << " = geompy.RemoveExtraEdges(" << theObject << ")";
+
+ SetErrorCode(OK);
+ return aCopy;
+}
+
+//=============================================================================
+/*!
+ * CheckAndImprove
+ */
+//=============================================================================
+Handle(GEOM_Object) GEOMImpl_IBlocksOperations::CheckAndImprove
+ (Handle(GEOM_Object) theObject)
+{
+ SetErrorCode(KO);
+
+ if (theObject.IsNull()) return NULL;
+
+ Handle(GEOM_Function) aLastFunction = theObject->GetLastFunction();
+ if (aLastFunction.IsNull()) return NULL; //There is no function which creates an object to be fixed
+
+ //Add a new Copy object
+ Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY);
+
+ //Add a function
+ Handle(GEOM_Function) aFunction =
+ aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_IMPROVE);
+
+ //Check if the function is set correctly
+ if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL;
+
+ GEOMImpl_IBlockTrsf aTI (aFunction);
+ aTI.SetOriginal(aLastFunction);
+
+ //Compute the fixed shape
+ try {
+#if (OCC_VERSION_MAJOR << 16 | OCC_VERSION_MINOR << 8 | OCC_VERSION_MAINTENANCE) > 0x060100
+ OCC_CATCH_SIGNALS;
+#endif
+ if (!GetSolver()->ComputeFunction(aFunction)) {
+ SetErrorCode("Block driver failed to improve the given blocks compound");
+ return NULL;
+ }
+ }
+ catch (Standard_Failure) {
+ Handle(Standard_Failure) aFail = Standard_Failure::Caught();
+ SetErrorCode(aFail->GetMessageString());
+ return NULL;
+ }
+
+ //Make a Python command
+ GEOM::TPythonDump(aFunction) << aCopy
+ << " = geompy.CheckAndImprove(" << theObject << ")";
+
+ SetErrorCode(OK);
+ return aCopy;
+}
+