using namespace std; #include "GEOMImpl_IBlocksOperations.hxx" #include "GEOMImpl_Types.hxx" #include "GEOMImpl_BlockDriver.hxx" #include "GEOMImpl_IBlocks.hxx" #include "GEOMImpl_IBlockTrsf.hxx" #include "GEOMImpl_CopyDriver.hxx" #include "GEOMImpl_Block6Explorer.hxx" #include "GEOM_Function.hxx" #include "utilities.h" #include "OpUtil.hxx" #include "Utils_ExceptHandlers.hxx" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC //============================================================================= /*! * constructor: */ //============================================================================= GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations (GEOM_Engine* theEngine, int theDocID) : GEOM_IOperations(theEngine, theDocID) { MESSAGE("GEOMImpl_IBlocksOperations::GEOMImpl_IBlocksOperations"); } //============================================================================= /*! * destructor */ //============================================================================= GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations() { MESSAGE("GEOMImpl_IBlocksOperations::~GEOMImpl_IBlocksOperations"); } //============================================================================= /*! * MakeQuad */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2, Handle(GEOM_Object) theEdge3, Handle(GEOM_Object) theEdge4) { SetErrorCode(KO); if (theEdge1.IsNull() || theEdge2.IsNull() || theEdge3.IsNull() || theEdge4.IsNull()) return NULL; //Add a new Face object Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE); //Add a new Face function Handle(GEOM_Function) aFunction = aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_EDGES); //Check if the function is set correctly if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL; GEOMImpl_IBlocks aPI (aFunction); Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction(); Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction(); Handle(GEOM_Function) aRef3 = theEdge3->GetLastFunction(); Handle(GEOM_Function) aRef4 = theEdge4->GetLastFunction(); if (aRef1.IsNull() || aRef2.IsNull() || aRef3.IsNull() || aRef4.IsNull()) return NULL; Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient; aShapesSeq->Append(aRef1); aShapesSeq->Append(aRef2); aShapesSeq->Append(aRef3); aShapesSeq->Append(aRef4); aPI.SetShapes(aShapesSeq); //Compute the Face value try { if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Block driver failed to compute a face"); return NULL; } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //Make a Python command TCollection_AsciiString anEntry, aDescr; TDF_Tool::Entry(aFace->GetEntry(), anEntry); aDescr += anEntry + " = IBlocksOperations.MakeQuad("; TDF_Tool::Entry(theEdge1->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(theEdge2->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(theEdge3->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(theEdge4->GetEntry(), anEntry); aDescr += anEntry + ")"; aFunction->SetDescription(aDescr); SetErrorCode(OK); return aFace; } //============================================================================= /*! * MakeQuad2Edges */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad2Edges (Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2) { SetErrorCode(KO); if (theEdge1.IsNull() || theEdge2.IsNull()) return NULL; //Add a new Face object Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE); //Add a new Face function Handle(GEOM_Function) aFunction = aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_TWO_EDGES); //Check if the function is set correctly if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL; GEOMImpl_IBlocks aPI (aFunction); Handle(GEOM_Function) aRef1 = theEdge1->GetLastFunction(); Handle(GEOM_Function) aRef2 = theEdge2->GetLastFunction(); if (aRef1.IsNull() || aRef2.IsNull()) return NULL; Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient; aShapesSeq->Append(aRef1); aShapesSeq->Append(aRef2); aPI.SetShapes(aShapesSeq); //Compute the Face value try { if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Block driver failed to compute a face"); return NULL; } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //Make a Python command TCollection_AsciiString anEntry, aDescr; TDF_Tool::Entry(aFace->GetEntry(), anEntry); aDescr += anEntry + " = IBlocksOperations.MakeQuad2Edges("; TDF_Tool::Entry(theEdge1->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(theEdge2->GetEntry(), anEntry); aDescr += anEntry + ")"; aFunction->SetDescription(aDescr); SetErrorCode(OK); return aFace; } //============================================================================= /*! * MakeQuad4Vertices */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeQuad4Vertices (Handle(GEOM_Object) thePnt1, Handle(GEOM_Object) thePnt2, Handle(GEOM_Object) thePnt3, Handle(GEOM_Object) thePnt4) { SetErrorCode(KO); if (thePnt1.IsNull() || thePnt2.IsNull() || thePnt3.IsNull() || thePnt4.IsNull()) return NULL; //Add a new Face object Handle(GEOM_Object) aFace = GetEngine()->AddObject(GetDocID(), GEOM_FACE); //Add a new Face function Handle(GEOM_Function) aFunction = aFace->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_FACE_FOUR_PNT); //Check if the function is set correctly if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL; GEOMImpl_IBlocks aPI (aFunction); Handle(GEOM_Function) aRef1 = thePnt1->GetLastFunction(); Handle(GEOM_Function) aRef2 = thePnt2->GetLastFunction(); Handle(GEOM_Function) aRef3 = thePnt3->GetLastFunction(); Handle(GEOM_Function) aRef4 = thePnt4->GetLastFunction(); if (aRef1.IsNull() || aRef2.IsNull() || aRef3.IsNull() || aRef4.IsNull()) return NULL; Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient; aShapesSeq->Append(aRef1); aShapesSeq->Append(aRef2); aShapesSeq->Append(aRef3); aShapesSeq->Append(aRef4); aPI.SetShapes(aShapesSeq); //Compute the Face value try { if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Block driver failed to compute a face"); return NULL; } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //Make a Python command TCollection_AsciiString anEntry, aDescr; TDF_Tool::Entry(aFace->GetEntry(), anEntry); aDescr += anEntry + " = IBlocksOperations.MakeQuad4Vertices("; TDF_Tool::Entry(thePnt1->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(thePnt2->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(thePnt3->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(thePnt4->GetEntry(), anEntry); aDescr += anEntry + ")"; aFunction->SetDescription(aDescr); SetErrorCode(OK); return aFace; } //============================================================================= /*! * MakeHexa */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2, Handle(GEOM_Object) theFace3, Handle(GEOM_Object) theFace4, Handle(GEOM_Object) theFace5, Handle(GEOM_Object) theFace6) { SetErrorCode(KO); if (theFace1.IsNull() || theFace2.IsNull() || theFace3.IsNull() || theFace4.IsNull() || theFace5.IsNull() || theFace6.IsNull()) return NULL; //Add a new Solid object Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK); //Add a new Block function Handle(GEOM_Function) aFunction = aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_SIX_FACES); //Check if the function is set correctly if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL; GEOMImpl_IBlocks aPI (aFunction); Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction(); Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction(); Handle(GEOM_Function) aRef3 = theFace3->GetLastFunction(); Handle(GEOM_Function) aRef4 = theFace4->GetLastFunction(); Handle(GEOM_Function) aRef5 = theFace5->GetLastFunction(); Handle(GEOM_Function) aRef6 = theFace6->GetLastFunction(); if (aRef1.IsNull() || aRef2.IsNull() || aRef3.IsNull() || aRef4.IsNull() || aRef5.IsNull() || aRef6.IsNull()) return NULL; Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient; aShapesSeq->Append(aRef1); aShapesSeq->Append(aRef2); aShapesSeq->Append(aRef3); aShapesSeq->Append(aRef4); aShapesSeq->Append(aRef5); aShapesSeq->Append(aRef6); aPI.SetShapes(aShapesSeq); //Compute the Block value try { if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Block driver failed to compute a block"); return NULL; } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //Make a Python command TCollection_AsciiString anEntry, aDescr; TDF_Tool::Entry(aBlock->GetEntry(), anEntry); aDescr += anEntry + " = IBlocksOperations.MakeHexa("; TDF_Tool::Entry(theFace1->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(theFace2->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(theFace3->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(theFace4->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(theFace5->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(theFace6->GetEntry(), anEntry); aDescr += anEntry + ")"; aFunction->SetDescription(aDescr); SetErrorCode(OK); return aBlock; } //============================================================================= /*! * MakeHexa2Faces */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeHexa2Faces (Handle(GEOM_Object) theFace1, Handle(GEOM_Object) theFace2) { SetErrorCode(KO); if (theFace1.IsNull() || theFace2.IsNull()) return NULL; //Add a new Solid object Handle(GEOM_Object) aBlock = GetEngine()->AddObject(GetDocID(), GEOM_BLOCK); //Add a new Block function Handle(GEOM_Function) aFunction = aBlock->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_TWO_FACES); //Check if the function is set correctly if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL; GEOMImpl_IBlocks aPI (aFunction); Handle(GEOM_Function) aRef1 = theFace1->GetLastFunction(); Handle(GEOM_Function) aRef2 = theFace2->GetLastFunction(); if (aRef1.IsNull() || aRef2.IsNull()) return NULL; Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient; aShapesSeq->Append(aRef1); aShapesSeq->Append(aRef2); aPI.SetShapes(aShapesSeq); //Compute the Block value try { if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Block driver failed to compute a block"); return NULL; } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //Make a Python command TCollection_AsciiString anEntry, aDescr; TDF_Tool::Entry(aBlock->GetEntry(), anEntry); aDescr += anEntry + " = IBlocksOperations.MakeHexa2Faces("; TDF_Tool::Entry(theFace1->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(theFace2->GetEntry(), anEntry); aDescr += anEntry + ")"; aFunction->SetDescription(aDescr); SetErrorCode(OK); return aBlock; } //============================================================================= /*! * MakeBlockCompound */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeBlockCompound (Handle(GEOM_Object) theCompound) { SetErrorCode(KO); if (theCompound.IsNull()) return NULL; //Add a new object Handle(GEOM_Object) aBlockComp = GetEngine()->AddObject(GetDocID(), GEOM_COMPOUND); //Add a new BlocksComp function Handle(GEOM_Function) aFunction = aBlockComp->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_COMPOUND_GLUE); //Check if the function is set correctly if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL; GEOMImpl_IBlocks aPI (aFunction); Handle(GEOM_Function) aRef1 = theCompound->GetLastFunction(); if (aRef1.IsNull()) return NULL; Handle(TColStd_HSequenceOfTransient) aShapesSeq = new TColStd_HSequenceOfTransient; aShapesSeq->Append(aRef1); aPI.SetShapes(aShapesSeq); //Compute the Blocks Compound value try { if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Block driver failed to compute a blocks compound"); return NULL; } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //Make a Python command TCollection_AsciiString anEntry, aDescr; TDF_Tool::Entry(aBlockComp->GetEntry(), anEntry); aDescr += anEntry + " = IBlocksOperations.MakeBlockCompound("; TDF_Tool::Entry(theCompound->GetEntry(), anEntry); aDescr += anEntry + ")"; aFunction->SetDescription(aDescr); SetErrorCode(OK); return aBlockComp; } //============================================================================= /*! * GetEdge */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetPoint (Handle(GEOM_Object) theShape, const Standard_Real theX, const Standard_Real theY, const Standard_Real theZ, const Standard_Real theEpsilon) { SetErrorCode(KO); //New Point object Handle(GEOM_Object) aResult; // Arguments if (theShape.IsNull()) return NULL; TopoDS_Shape aBlockOrComp = theShape->GetValue(); if (aBlockOrComp.IsNull()) { SetErrorCode("Block or compound is null"); return NULL; } if (aBlockOrComp.ShapeType() != TopAbs_SOLID && aBlockOrComp.ShapeType() != TopAbs_COMPOUND && aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) { SetErrorCode("Shape is neither a block, nor a compound of blocks"); return NULL; } //Compute the Vertex value gp_Pnt P (theX, theY, theZ); Standard_Real eps = Max(theEpsilon, Precision::Confusion()); TopoDS_Shape V; Standard_Integer isFound = 0; TopTools_MapOfShape mapShape; TopExp_Explorer exp (aBlockOrComp, TopAbs_VERTEX); for (; exp.More(); exp.Next()) { if (mapShape.Add(exp.Current())) { TopoDS_Vertex aVi = TopoDS::Vertex(exp.Current()); gp_Pnt aPi = BRep_Tool::Pnt(aVi); if (aPi.Distance(P) < eps) { V = aVi; isFound++; } } } if (isFound == 0) { SetErrorCode("Vertex has not been found"); return NULL; } else if (isFound > 1) { SetErrorCode("Multiple vertices found by the given coordinates and epsilon"); return NULL; } else { TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aBlockOrComp, anIndices); Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, anIndices.FindIndex(V)); aResult = GetEngine()->AddSubShape(theShape, anArray); } //The GetPoint() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); //Make a Python command TCollection_AsciiString anEntry, aDescr; TDF_Tool::Entry(aResult->GetEntry(), anEntry); aDescr += anEntry + " = IBlocksOperations.GetPoint("; TDF_Tool::Entry(theShape->GetEntry(), anEntry); aDescr += anEntry + ", "; aDescr += TCollection_AsciiString(theX) + ", "; aDescr += TCollection_AsciiString(theY) + ", "; aDescr += TCollection_AsciiString(theZ) + ", "; aDescr += TCollection_AsciiString(theEpsilon) + ")"; TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n"; aNewDescr += aDescr; aFunction->SetDescription(aNewDescr); SetErrorCode(OK); return aResult; } //============================================================================= /*! * GetEdge */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdge (Handle(GEOM_Object) theShape, Handle(GEOM_Object) thePoint1, Handle(GEOM_Object) thePoint2) { SetErrorCode(KO); //New Edge object Handle(GEOM_Object) aResult; // Arguments if (theShape.IsNull() || thePoint1.IsNull() || thePoint2.IsNull()) return NULL; TopoDS_Shape aBlockOrComp = theShape->GetValue(); if (aBlockOrComp.IsNull()) { SetErrorCode("Block or compound is null"); return NULL; } if (aBlockOrComp.ShapeType() != TopAbs_SOLID && aBlockOrComp.ShapeType() != TopAbs_COMPOUND && aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) { SetErrorCode("Shape is neither a block, nor a compound of blocks"); return NULL; } TopoDS_Shape anArg1 = thePoint1->GetValue(); TopoDS_Shape anArg2 = thePoint2->GetValue(); if (anArg1.IsNull() || anArg2.IsNull()) { SetErrorCode("Null shape is given as argument"); return NULL; } if (anArg1.ShapeType() != TopAbs_VERTEX || anArg2.ShapeType() != TopAbs_VERTEX) { SetErrorCode("Element for edge identification is not a vertex"); return NULL; } //Compute the Edge value try { TopTools_IndexedDataMapOfShapeListOfShape MVE; GEOMImpl_Block6Explorer::MapShapesAndAncestors (aBlockOrComp, TopAbs_VERTEX, TopAbs_EDGE, MVE); TopoDS_Shape V1,V2; Standard_Integer ish, ext = MVE.Extent(); if (MVE.Contains(anArg1)) { V1 = anArg1; } else { for (ish = 1; ish <= ext; ish++) { TopoDS_Shape aShi = MVE.FindKey(ish); if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) { V1 = aShi; break; } } } if (MVE.Contains(anArg2)) { V2 = anArg2; } else { for (ish = 1; ish <= ext; ish++) { TopoDS_Shape aShi = MVE.FindKey(ish); if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) { V2 = aShi; break; } } } if (V1.IsNull() || V2.IsNull()) { SetErrorCode("The given vertex does not belong to the shape"); return NULL; } TopoDS_Shape anEdge; Standard_Integer isFound = GEOMImpl_Block6Explorer::FindEdge(anEdge, V1, V2, MVE, Standard_True); if (isFound == 0) { SetErrorCode("The given vertices do not belong to one edge of the given shape"); return NULL; } else if (isFound > 1) { SetErrorCode("Multiple edges found by the given vertices of the shape"); return NULL; } else { TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aBlockOrComp, anIndices); Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, anIndices.FindIndex(anEdge)); aResult = GetEngine()->AddSubShape(theShape, anArray); } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //The GetEdge() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); //Make a Python command TCollection_AsciiString anEntry, aDescr; TDF_Tool::Entry(aResult->GetEntry(), anEntry); aDescr += anEntry + " = IBlocksOperations.GetEdge("; TDF_Tool::Entry(theShape->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(thePoint1->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(thePoint2->GetEntry(), anEntry); aDescr += anEntry + ")"; TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n"; aNewDescr += aDescr; aFunction->SetDescription(aNewDescr); SetErrorCode(OK); return aResult; } //============================================================================= /*! * GetEdgeNearPoint */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetEdgeNearPoint (Handle(GEOM_Object) theShape, Handle(GEOM_Object) thePoint) { SetErrorCode(KO); //New object Handle(GEOM_Object) aResult; // Arguments if (theShape.IsNull() || thePoint.IsNull()) return NULL; TopoDS_Shape aBlockOrComp = theShape->GetValue(); if (aBlockOrComp.IsNull()) { SetErrorCode("Block or compound is null"); return NULL; } if (aBlockOrComp.ShapeType() != TopAbs_SOLID && aBlockOrComp.ShapeType() != TopAbs_COMPOUND && aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) { SetErrorCode("Shape is neither a block, nor a compound of blocks"); return NULL; } TopoDS_Shape anArg = thePoint->GetValue(); if (anArg.IsNull()) { SetErrorCode("Null shape is given as argument"); return NULL; } if (anArg.ShapeType() != TopAbs_VERTEX) { SetErrorCode("Element for edge identification is not a vertex"); return NULL; } //Compute the Edge value try { TopoDS_Shape aShape; TopoDS_Vertex aVert = TopoDS::Vertex(anArg); // 1. Explode blocks on edges TopTools_MapOfShape mapShape; Standard_Integer nbEdges = 0; TopExp_Explorer exp (aBlockOrComp, TopAbs_EDGE); for (; exp.More(); exp.Next()) { if (mapShape.Add(exp.Current())) { nbEdges++; } } mapShape.Clear(); Standard_Integer ind = 1; TopTools_Array1OfShape anEdges (1, nbEdges); TColStd_Array1OfReal aDistances (1, nbEdges); for (exp.Init(aBlockOrComp, TopAbs_EDGE); exp.More(); exp.Next()) { if (mapShape.Add(exp.Current())) { TopoDS_Shape anEdge = exp.Current(); anEdges(ind) = anEdge; // 2. Classify the point relatively each edge BRepExtrema_DistShapeShape aDistTool (aVert, anEdges(ind)); if (!aDistTool.IsDone()) { SetErrorCode("Can not find a distance from the given point to one of edges"); return NULL; } aDistances(ind) = aDistTool.Value(); ind++; } } // 3. Define edge, having minimum distance to the point Standard_Real nearest = RealLast(), nbFound = 0; Standard_Real prec = Precision::Confusion(); for (ind = 1; ind <= nbEdges; ind++) { if (Abs(aDistances(ind) - nearest) < prec) { nbFound++; } else if (aDistances(ind) < nearest) { nearest = aDistances(ind); aShape = anEdges(ind); nbFound = 1; } else { } } if (nbFound > 1) { SetErrorCode("Multiple edges near the given point are found"); return NULL; } else if (nbFound == 0) { SetErrorCode("There are no edges near the given point"); return NULL; } else { TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aBlockOrComp, anIndices); Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, anIndices.FindIndex(aShape)); aResult = GetEngine()->AddSubShape(theShape, anArray); } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //The GetEdgeNearPoint() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); //Make a Python command TCollection_AsciiString anEntry, aDescr; TDF_Tool::Entry(aResult->GetEntry(), anEntry); aDescr += anEntry + " = IBlocksOperations.GetEdgeNearPoint("; TDF_Tool::Entry(theShape->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(thePoint->GetEntry(), anEntry); aDescr += anEntry + ")"; TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n"; aNewDescr += aDescr; aFunction->SetDescription(aNewDescr); SetErrorCode(OK); return aResult; } //============================================================================= /*! * GetFaceByPoints */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByPoints (Handle(GEOM_Object) theShape, Handle(GEOM_Object) thePoint1, Handle(GEOM_Object) thePoint2, Handle(GEOM_Object) thePoint3, Handle(GEOM_Object) thePoint4) { SetErrorCode(KO); //New object Handle(GEOM_Object) aResult; // Arguments if (theShape.IsNull() || thePoint1.IsNull() || thePoint2.IsNull() || thePoint3.IsNull() || thePoint4.IsNull()) return NULL; TopoDS_Shape aBlockOrComp = theShape->GetValue(); if (aBlockOrComp.IsNull()) { SetErrorCode("Block or compound is null"); return NULL; } if (aBlockOrComp.ShapeType() != TopAbs_SOLID && aBlockOrComp.ShapeType() != TopAbs_COMPOUND && aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) { SetErrorCode("Shape is neither a block, nor a compound of blocks"); return NULL; } TopoDS_Shape anArg1 = thePoint1->GetValue(); TopoDS_Shape anArg2 = thePoint2->GetValue(); TopoDS_Shape anArg3 = thePoint3->GetValue(); TopoDS_Shape anArg4 = thePoint4->GetValue(); if (anArg1.IsNull() || anArg2.IsNull() || anArg3.IsNull() || anArg4.IsNull()) { SetErrorCode("Null shape is given as argument"); return NULL; } if (anArg1.ShapeType() != TopAbs_VERTEX || anArg2.ShapeType() != TopAbs_VERTEX || anArg3.ShapeType() != TopAbs_VERTEX || anArg4.ShapeType() != TopAbs_VERTEX) { SetErrorCode("Element for face identification is not a vertex"); return NULL; } //Compute the Face value try { TopoDS_Shape aShape; TopTools_IndexedDataMapOfShapeListOfShape MVF; GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_VERTEX, TopAbs_FACE, MVF); TopoDS_Shape V1,V2,V3,V4; Standard_Integer ish, ext = MVF.Extent(); if (MVF.Contains(anArg1)) { V1 = anArg1; } else { for (ish = 1; ish <= ext; ish++) { TopoDS_Shape aShi = MVF.FindKey(ish); if (BRepTools::Compare(TopoDS::Vertex(anArg1), TopoDS::Vertex(aShi))) { V1 = aShi; break; } } } if (MVF.Contains(anArg2)) { V2 = anArg2; } else { for (ish = 1; ish <= ext; ish++) { TopoDS_Shape aShi = MVF.FindKey(ish); if (BRepTools::Compare(TopoDS::Vertex(anArg2), TopoDS::Vertex(aShi))) { V2 = aShi; break; } } } if (MVF.Contains(anArg3)) { V3 = anArg3; } else { for (ish = 1; ish <= ext; ish++) { TopoDS_Shape aShi = MVF.FindKey(ish); if (BRepTools::Compare(TopoDS::Vertex(anArg3), TopoDS::Vertex(aShi))) { V3 = aShi; break; } } } if (MVF.Contains(anArg4)) { V4 = anArg4; } else { for (ish = 1; ish <= ext; ish++) { TopoDS_Shape aShi = MVF.FindKey(ish); if (BRepTools::Compare(TopoDS::Vertex(anArg4), TopoDS::Vertex(aShi))) { V4 = aShi; break; } } } if (V1.IsNull() || V2.IsNull() || V3.IsNull() || V4.IsNull()) { SetErrorCode("The given vertex does not belong to the shape"); return NULL; } Standard_Integer isFound = GEOMImpl_Block6Explorer::FindFace(aShape, V1, V2, V3, V4, MVF, Standard_True); if (isFound == 0) { SetErrorCode("The given vertices do not belong to one face of the given shape"); return NULL; } else if (isFound > 1) { SetErrorCode("The given vertices belong to several faces of the given shape"); return NULL; } else { TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aBlockOrComp, anIndices); Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, anIndices.FindIndex(aShape)); aResult = GetEngine()->AddSubShape(theShape, anArray); } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //The GetFaceByPoints() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); //Make a Python command TCollection_AsciiString anEntry, aDescr; TDF_Tool::Entry(aResult->GetEntry(), anEntry); aDescr += anEntry + " = IBlocksOperations.GetFaceByPoints("; TDF_Tool::Entry(theShape->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(thePoint1->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(thePoint2->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(thePoint3->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(thePoint4->GetEntry(), anEntry); aDescr += anEntry + ")"; TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n"; aNewDescr += aDescr; aFunction->SetDescription(aNewDescr); SetErrorCode(OK); return aResult; } //============================================================================= /*! * GetFaceByEdges */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByEdges (Handle(GEOM_Object) theShape, Handle(GEOM_Object) theEdge1, Handle(GEOM_Object) theEdge2) { SetErrorCode(KO); //New object Handle(GEOM_Object) aResult; // Arguments if (theShape.IsNull() || theEdge1.IsNull() || theEdge2.IsNull()) return NULL; TopoDS_Shape aBlockOrComp = theShape->GetValue(); if (aBlockOrComp.IsNull()) { SetErrorCode("Block or compound is null"); return NULL; } if (aBlockOrComp.ShapeType() != TopAbs_SOLID && aBlockOrComp.ShapeType() != TopAbs_COMPOUND && aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) { SetErrorCode("Shape is neither a block, nor a compound of blocks"); return NULL; } TopoDS_Shape anArg1 = theEdge1->GetValue(); TopoDS_Shape anArg2 = theEdge2->GetValue(); if (anArg1.IsNull() || anArg2.IsNull()) { SetErrorCode("Null shape is given as argument"); return NULL; } if (anArg1.ShapeType() != TopAbs_EDGE || anArg2.ShapeType() != TopAbs_EDGE) { SetErrorCode("Element for face identification is not an edge"); return NULL; } //Compute the Face value try { TopoDS_Shape aShape; TopTools_IndexedDataMapOfShapeListOfShape MEF; GEOMImpl_Block6Explorer::MapShapesAndAncestors(aBlockOrComp, TopAbs_EDGE, TopAbs_FACE, MEF); TopoDS_Shape E1,E2; Standard_Integer ish, ext = MEF.Extent(); if (MEF.Contains(anArg1)) { E1 = anArg1; } else { for (ish = 1; ish <= ext; ish++) { TopoDS_Shape aShi = MEF.FindKey(ish); if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg1, aShi)) { E1 = aShi; } } } if (MEF.Contains(anArg2)) { E2 = anArg2; } else { for (ish = 1; ish <= ext; ish++) { TopoDS_Shape aShi = MEF.FindKey(ish); if (GEOMImpl_Block6Explorer::IsSimilarEdges(anArg2, aShi)) { E2 = aShi; } } } if (E1.IsNull() || E2.IsNull()) { SetErrorCode("The given edge does not belong to the shape"); return NULL; } const TopTools_ListOfShape& aFacesOfE1 = MEF.FindFromKey(E1); const TopTools_ListOfShape& aFacesOfE2 = MEF.FindFromKey(E2); Standard_Integer isFound = 0; TopTools_ListIteratorOfListOfShape anIterF1 (aFacesOfE1); for (; anIterF1.More(); anIterF1.Next()) { TopTools_ListIteratorOfListOfShape anIterF2 (aFacesOfE2); for (; anIterF2.More(); anIterF2.Next()) { if (anIterF1.Value().IsSame(anIterF2.Value())) { isFound++; // Store the face, defined by two edges aShape = anIterF1.Value(); } } } if (isFound == 0) { SetErrorCode("The given edges do not belong to one face of the given shape"); return NULL; } else if (isFound > 1) { SetErrorCode("The given edges belong to several faces of the given shape"); return NULL; } else { TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aBlockOrComp, anIndices); Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, anIndices.FindIndex(aShape)); aResult = GetEngine()->AddSubShape(theShape, anArray); } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //The GetFaceByEdges() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); //Make a Python command TCollection_AsciiString anEntry, aDescr; TDF_Tool::Entry(aResult->GetEntry(), anEntry); aDescr += anEntry + " = IBlocksOperations.GetFaceByEdges("; TDF_Tool::Entry(theShape->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(theEdge1->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(theEdge2->GetEntry(), anEntry); aDescr += anEntry + ")"; TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n"; aNewDescr += aDescr; aFunction->SetDescription(aNewDescr); SetErrorCode(OK); return aResult; } //============================================================================= /*! * GetOppositeFace */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetOppositeFace (Handle(GEOM_Object) theShape, Handle(GEOM_Object) theFace) { SetErrorCode(KO); //New object Handle(GEOM_Object) aResult; // Arguments if (theShape.IsNull() || theFace.IsNull()) return NULL; TopoDS_Shape aBlockOrComp = theShape->GetValue(); if (aBlockOrComp.IsNull()) { SetErrorCode("Block is null"); return NULL; } if (aBlockOrComp.ShapeType() != TopAbs_SOLID) { SetErrorCode("Shape is not a block"); return NULL; } TopoDS_Shape anArg = theFace->GetValue(); if (anArg.IsNull()) { SetErrorCode("Null shape is given as argument"); return NULL; } if (anArg.ShapeType() != TopAbs_FACE) { SetErrorCode("Element for face identification is not a face"); return NULL; } //Compute the Face value try { TopoDS_Shape aShape; GEOMImpl_Block6Explorer aBlockTool; aBlockTool.InitByBlockAndFace(aBlockOrComp, anArg); aShape = aBlockTool.GetFace(2); TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aBlockOrComp, anIndices); Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, anIndices.FindIndex(aShape)); aResult = GetEngine()->AddSubShape(theShape, anArray); } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //The GetOppositeFace() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); //Make a Python command TCollection_AsciiString anEntry, aDescr; TDF_Tool::Entry(aResult->GetEntry(), anEntry); aDescr += anEntry + " = IBlocksOperations.GetOppositeFace("; TDF_Tool::Entry(theShape->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(theFace->GetEntry(), anEntry); aDescr += anEntry + ")"; TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n"; aNewDescr += aDescr; aFunction->SetDescription(aNewDescr); SetErrorCode(OK); return aResult; } //============================================================================= /*! * GetFaceNearPoint */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceNearPoint (Handle(GEOM_Object) theShape, Handle(GEOM_Object) thePoint) { SetErrorCode(KO); //New object Handle(GEOM_Object) aResult; // Arguments if (theShape.IsNull() || thePoint.IsNull()) return NULL; TopoDS_Shape aBlockOrComp = theShape->GetValue(); if (aBlockOrComp.IsNull()) { SetErrorCode("Block or compound is null"); return NULL; } if (aBlockOrComp.ShapeType() != TopAbs_SOLID && aBlockOrComp.ShapeType() != TopAbs_COMPOUND && aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) { SetErrorCode("Shape is neither a block, nor a compound of blocks"); return NULL; } TopoDS_Shape anArg = thePoint->GetValue(); if (anArg.IsNull()) { SetErrorCode("Null shape is given as argument"); return NULL; } if (anArg.ShapeType() != TopAbs_VERTEX) { SetErrorCode("Element for face identification is not a vertex"); return NULL; } //Compute the Face value try { TopoDS_Shape aShape; TopoDS_Vertex aVert = TopoDS::Vertex(anArg); gp_Pnt aPnt = BRep_Tool::Pnt(aVert); // 1. Explode blocks on faces TopTools_MapOfShape mapShape; Standard_Integer nbFaces = 0; TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE); for (; exp.More(); exp.Next()) { if (mapShape.Add(exp.Current())) { nbFaces++; } } mapShape.Clear(); Standard_Integer ind = 1; TopTools_Array1OfShape aFaces (1, nbFaces); TColStd_Array1OfInteger aDistances (1, nbFaces); for (exp.Init(aBlockOrComp, TopAbs_FACE); exp.More(); exp.Next()) { if (mapShape.Add(exp.Current())) { TopoDS_Shape aFace = exp.Current(); aFaces(ind) = aFace; // 2. Classify the point relatively each face BRepClass_FaceClassifier FC (TopoDS::Face(aFace), aPnt, Precision::Confusion()); if (FC.State() == TopAbs_IN) { aDistances(ind) = -1; } else if (FC.State() == TopAbs_ON) { aDistances(ind) = 0; } else { // OUT aDistances(ind) = 1; } ind++; } } // 3. Define face, containing the point or having minimum distance to it Standard_Integer nearest = 2, nbFound = 0; for (ind = 1; ind <= nbFaces; ind++) { if (aDistances(ind) < nearest) { nearest = aDistances(ind); aShape = aFaces(ind); nbFound = 1; } else if (aDistances(ind) == nearest) { nbFound++; } else { } } if (nbFound > 1) { if (nearest == 0) { // The point is on boundary of some faces and there are // no faces, having the point inside SetErrorCode("Multiple faces near the given point are found"); return NULL; } else if (nearest == 1) { // The point is outside some faces and there are // no faces, having the point inside or on boundary. // We will get a nearest face Standard_Real minDist = RealLast(); for (ind = 1; ind <= nbFaces; ind++) { if (aDistances(ind) == 1) { BRepExtrema_DistShapeShape aDistTool (aVert, aFaces(ind)); if (!aDistTool.IsDone()) { SetErrorCode("Can not find a distance from the given point to one of faces"); return NULL; } Standard_Real aDist = aDistTool.Value(); if (aDist < minDist) { minDist = aDist; aShape = aFaces(ind); } } } } else { // nearest == -1 // The point is inside some faces. // We will get a face with nearest center Standard_Real minDist = RealLast(); for (ind = 1; ind <= nbFaces; ind++) { if (aDistances(ind) == -1) { GProp_GProps aSystem; BRepGProp::SurfaceProperties(aFaces(ind), aSystem); gp_Pnt aCenterMass = aSystem.CentreOfMass(); Standard_Real aDist = aCenterMass.Distance(aPnt); if (aDist < minDist) { minDist = aDist; aShape = aFaces(ind); } } } } } if (nbFound == 0) { SetErrorCode("There are no faces near the given point"); return NULL; } else { TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aBlockOrComp, anIndices); Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, anIndices.FindIndex(aShape)); aResult = GetEngine()->AddSubShape(theShape, anArray); } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //The GetFaceNearPoint() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); //Make a Python command TCollection_AsciiString anEntry, aDescr; TDF_Tool::Entry(aResult->GetEntry(), anEntry); aDescr += anEntry + " = IBlocksOperations.GetFaceNearPoint("; TDF_Tool::Entry(theShape->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(thePoint->GetEntry(), anEntry); aDescr += anEntry + ")"; TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n"; aNewDescr += aDescr; aFunction->SetDescription(aNewDescr); SetErrorCode(OK); return aResult; } //============================================================================= /*! * GetFaceByNormale */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetFaceByNormale (Handle(GEOM_Object) theShape, Handle(GEOM_Object) theVector) { SetErrorCode(KO); //New object Handle(GEOM_Object) aResult; // Arguments if (theShape.IsNull() || theVector.IsNull()) return NULL; TopoDS_Shape aBlockOrComp = theShape->GetValue(); if (aBlockOrComp.IsNull()) { SetErrorCode("Block or compound is null"); return NULL; } if (aBlockOrComp.ShapeType() != TopAbs_SOLID && aBlockOrComp.ShapeType() != TopAbs_COMPOUND && aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) { SetErrorCode("Shape is neither a block, nor a compound of blocks"); return NULL; } TopoDS_Shape anArg = theVector->GetValue(); if (anArg.IsNull()) { SetErrorCode("Null shape is given as argument"); return NULL; } if (anArg.ShapeType() != TopAbs_EDGE) { SetErrorCode("Element for normale identification is not an edge"); return NULL; } //Compute the Face value try { TopoDS_Shape aShape; TopoDS_Edge anEdge = TopoDS::Edge(anArg); TopoDS_Vertex V1, V2; TopExp::Vertices(anEdge, V1, V2, Standard_True); gp_Pnt P1 = BRep_Tool::Pnt(V1); gp_Pnt P2 = BRep_Tool::Pnt(V2); gp_Vec aVec (P1, P2); if (aVec.Magnitude() < Precision::Confusion()) { SetErrorCode("Vector with null magnitude is given"); return NULL; } Standard_Real minAngle = RealLast(); TopTools_MapOfShape mapShape; TopExp_Explorer exp (aBlockOrComp, TopAbs_FACE); for (; exp.More(); exp.Next()) { if (mapShape.Add(exp.Current())) { TopoDS_Face aFace = TopoDS::Face(exp.Current()); BRepAdaptor_Surface SF (aFace); Standard_Real u, v, x; // find a point on the surface to get normal direction in u = SF.FirstUParameter(); x = SF.LastUParameter(); if (Precision::IsInfinite(u)) { u = (Precision::IsInfinite(x)) ? 0. : x; } else if (!Precision::IsInfinite(x)) { u = (u+x) / 2.; } v = SF.FirstVParameter(); x = SF.LastVParameter(); if (Precision::IsInfinite(v)) { v = (Precision::IsInfinite(x)) ? 0. : x; } else if (!Precision::IsInfinite(x)) { v = (v+x) / 2.; } // compute the normal direction gp_Vec Vec1,Vec2; SF.D1(u,v,P1,Vec1,Vec2); gp_Vec V = Vec1.Crossed(Vec2); x = V.Magnitude(); if (V.Magnitude() < Precision::Confusion()) { SetErrorCode("Normal vector of a face has null magnitude"); return NULL; } // consider the face orientation if (aFace.Orientation() == TopAbs_REVERSED || aFace.Orientation() == TopAbs_INTERNAL) { V = - V; } // compute the angle and compare with the minimal one Standard_Real anAngle = aVec.Angle(V); if (anAngle < minAngle) { minAngle = anAngle; aShape = aFace; } } } if (aShape.IsNull()) { SetErrorCode("Failed to find a face by the given normale"); return NULL; } else { TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aBlockOrComp, anIndices); Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, anIndices.FindIndex(aShape)); aResult = GetEngine()->AddSubShape(theShape, anArray); } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //The GetFaceByNormale() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = theShape->GetLastFunction(); //Make a Python command TCollection_AsciiString anEntry, aDescr; TDF_Tool::Entry(aResult->GetEntry(), anEntry); aDescr += anEntry + " = IBlocksOperations.GetFaceByNormale("; TDF_Tool::Entry(theShape->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(theVector->GetEntry(), anEntry); aDescr += anEntry + ")"; TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n"; aNewDescr += aDescr; aFunction->SetDescription(aNewDescr); SetErrorCode(OK); return aResult; } //============================================================================= /*! * IsCompoundOfBlocks */ //============================================================================= Standard_Boolean GEOMImpl_IBlocksOperations::IsCompoundOfBlocks (Handle(GEOM_Object) theCompound, const Standard_Integer theMinNbFaces, const Standard_Integer theMaxNbFaces, Standard_Integer& theNbBlocks) { SetErrorCode(KO); Standard_Boolean isCompOfBlocks = Standard_False; theNbBlocks = 0; if (theCompound.IsNull()) return isCompOfBlocks; TopoDS_Shape aBlockOrComp = theCompound->GetValue(); //Check isCompOfBlocks = Standard_True; try { TopTools_MapOfShape mapShape; TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID); for (; exp.More(); exp.Next()) { if (mapShape.Add(exp.Current())) { TopoDS_Shape aSolid = exp.Current(); TopTools_MapOfShape mapFaces; TopExp_Explorer expF (aSolid, TopAbs_FACE); Standard_Integer nbFaces = 0; for (; expF.More(); expF.Next()) { if (mapFaces.Add(expF.Current())) { nbFaces++; if (nbFaces > theMaxNbFaces) { isCompOfBlocks = Standard_False; break; } } } if (nbFaces < theMinNbFaces || theMaxNbFaces < nbFaces) { isCompOfBlocks = Standard_False; } else { theNbBlocks++; } } } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return isCompOfBlocks; } SetErrorCode(OK); return isCompOfBlocks; } //============================================================================= /*! * Set of functions, used by CheckCompoundOfBlocks() method */ //============================================================================= void AddBlocksFrom (const TopoDS_Shape& theShape, TopTools_ListOfShape& BLO, TopTools_ListOfShape& NOT) { TopAbs_ShapeEnum aType = theShape.ShapeType(); switch (aType) { case TopAbs_COMPOUND: case TopAbs_COMPSOLID: { TopoDS_Iterator It (theShape); for (; It.More(); It.Next()) { AddBlocksFrom(It.Value(), BLO, NOT); } } break; case TopAbs_SOLID: { TopTools_MapOfShape mapFaces; TopExp_Explorer expF (theShape, TopAbs_FACE); Standard_Integer nbFaces = 0; Standard_Integer nbEdges = 0; for (; expF.More(); expF.Next()) { if (mapFaces.Add(expF.Current())) { nbFaces++; if (nbFaces > 6) break; // Check number of edges in the face TopoDS_Shape aF = expF.Current(); TopExp_Explorer expE (aF, TopAbs_EDGE); nbEdges = 0; for (; expE.More(); expE.Next()) { nbEdges++; if (nbEdges > 4) break; } if (nbEdges != 4) break; } } if (nbFaces == 6 && nbEdges == 4) { BLO.Append(theShape); } else { NOT.Append(theShape); } } break; default: NOT.Append(theShape); } } #define REL_NOT_CONNECTED 0 #define REL_OK 1 #define REL_NOT_GLUED 2 #define REL_COLLISION_VV 3 #define REL_COLLISION_FF 4 #define REL_COLLISION_EE 5 #define REL_UNKNOWN 6 Standard_Integer BlocksRelation (const TopoDS_Shape& theBlock1, const TopoDS_Shape& theBlock2) { // Compare bounding boxes before calling BRepExtrema_DistShapeShape Standard_Real Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1; Standard_Real Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2; Bnd_Box B1, B2; BRepBndLib::Add(theBlock1, B1); BRepBndLib::Add(theBlock2, B2); // BRepBndLib::AddClose(theBlock1, B1); // BRepBndLib::AddClose(theBlock2, B2); B1.Get(Xmin1, Ymin1, Zmin1, Xmax1, Ymax1, Zmax1); B2.Get(Xmin2, Ymin2, Zmin2, Xmax2, Ymax2, Zmax2); if (Xmax2 < Xmin1 || Xmax1 < Xmin2 || Ymax2 < Ymin1 || Ymax1 < Ymin2 || Zmax2 < Zmin1 || Zmax1 < Zmin2) { // Standard_Real prec = Precision::Confusion(); // if (prec < Xmin1 - Xmax2 || prec < Xmin2 - Xmax1 || // prec < Ymin1 - Ymax2 || prec < Ymin2 - Ymax1 || // prec < Zmin1 - Zmax2 || prec < Zmin2 - Zmax1) { return REL_NOT_CONNECTED; } // to be done BRepExtrema_DistShapeShape dst (theBlock1, theBlock2); if (!dst.IsDone()) { return REL_UNKNOWN; } if (dst.Value() > Precision::Confusion()) { return REL_NOT_CONNECTED; } if (dst.InnerSolution()) { return REL_COLLISION_VV; } Standard_Integer nbSol = dst.NbSolution(); Standard_Integer relation = REL_OK; Standard_Integer nbVerts = 0; Standard_Integer nbEdges = 0; Standard_Integer sol = 1; for (; sol <= nbSol; sol++) { BRepExtrema_SupportType supp1 = dst.SupportTypeShape1(sol); BRepExtrema_SupportType supp2 = dst.SupportTypeShape2(sol); if (supp1 == BRepExtrema_IsVertex && supp2 == BRepExtrema_IsVertex) { nbVerts++; } else if (supp1 == BRepExtrema_IsInFace || supp2 == BRepExtrema_IsInFace) { return REL_COLLISION_FF; } else if (supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsOnEdge) { nbEdges++; } else if ((supp1 == BRepExtrema_IsOnEdge && supp2 == BRepExtrema_IsVertex) || (supp2 == BRepExtrema_IsOnEdge && supp1 == BRepExtrema_IsVertex)) { relation = REL_COLLISION_EE; } else { } } if (relation != REL_OK) { return relation; } TColStd_Array1OfInteger vertSol (1, nbVerts); TopTools_Array1OfShape V1 (1, nbVerts); TopTools_Array1OfShape V2 (1, nbVerts); Standard_Integer ivs = 0; for (sol = 1; sol <= nbSol; sol++) { if (dst.SupportTypeShape1(sol) == BRepExtrema_IsVertex && dst.SupportTypeShape2(sol) == BRepExtrema_IsVertex) { TopoDS_Vertex Vcur = TopoDS::Vertex(dst.SupportOnShape1(sol)); // Check, that this vertex is far enough from other solution vertices. Standard_Integer ii = 1; for (; ii <= ivs; ii++) { if (BRepTools::Compare(TopoDS::Vertex(V1(ii)), Vcur)) { continue; } } ivs++; vertSol(ivs) = sol; V1(ivs) = Vcur; V2(ivs) = dst.SupportOnShape2(sol); } } // As we deal only with quadrangles, // 2, 3 or 4 vertex solutions can be found. if (ivs <= 1) { if (nbEdges > 0) { return REL_COLLISION_FF; } return REL_NOT_CONNECTED; } if (ivs > 4) { return REL_UNKNOWN; } // Check sharing of coincident entities. if (ivs == 2 || ivs == 3) { // Map vertices and edges of the blocks TopTools_IndexedDataMapOfShapeListOfShape MVE1, MVE2; GEOMImpl_Block6Explorer::MapShapesAndAncestors (theBlock1, TopAbs_VERTEX, TopAbs_EDGE, MVE1); GEOMImpl_Block6Explorer::MapShapesAndAncestors (theBlock2, TopAbs_VERTEX, TopAbs_EDGE, MVE2); if (ivs == 2) { // Find common edge TopoDS_Shape anEdge1, anEdge2; GEOMImpl_Block6Explorer::FindEdge(anEdge1, V1(1), V1(2), MVE1); if (anEdge1.IsNull()) return REL_UNKNOWN; GEOMImpl_Block6Explorer::FindEdge(anEdge2, V2(1), V2(2), MVE2); if (anEdge2.IsNull()) return REL_UNKNOWN; if (!anEdge1.IsSame(anEdge2)) return REL_NOT_GLUED; } else { // ivs == 3 // Find common edges Standard_Integer e1_v1 = 1; Standard_Integer e1_v2 = 2; Standard_Integer e2_v1 = 3; Standard_Integer e2_v2 = 1; TopoDS_Shape anEdge11, anEdge12; GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1); if (anEdge11.IsNull()) { e1_v2 = 3; e2_v1 = 2; GEOMImpl_Block6Explorer::FindEdge(anEdge11, V1(e1_v1), V1(e1_v2), MVE1); if (anEdge11.IsNull()) return REL_UNKNOWN; } GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1); if (anEdge12.IsNull()) { e2_v2 = 5 - e2_v1; GEOMImpl_Block6Explorer::FindEdge(anEdge12, V1(e2_v1), V1(e2_v2), MVE1); if (anEdge12.IsNull()) return REL_UNKNOWN; } TopoDS_Shape anEdge21, anEdge22; GEOMImpl_Block6Explorer::FindEdge(anEdge21, V2(e1_v1), V2(e1_v2), MVE2); if (anEdge21.IsNull()) return REL_UNKNOWN; GEOMImpl_Block6Explorer::FindEdge(anEdge22, V2(e2_v1), V2(e2_v2), MVE2); if (anEdge22.IsNull()) return REL_UNKNOWN; // Check of edges coincidence (with some precision) have to be done here // if (!anEdge11.IsEqual(anEdge21)) return REL_UNKNOWN; // if (!anEdge12.IsEqual(anEdge22)) return REL_UNKNOWN; // Check of edges sharing if (!anEdge11.IsSame(anEdge21)) return REL_NOT_GLUED; if (!anEdge12.IsSame(anEdge22)) return REL_NOT_GLUED; } } if (ivs == 4) { // Map vertices and faces of the blocks TopTools_IndexedDataMapOfShapeListOfShape MVF1, MVF2; GEOMImpl_Block6Explorer::MapShapesAndAncestors (theBlock1, TopAbs_VERTEX, TopAbs_FACE, MVF1); GEOMImpl_Block6Explorer::MapShapesAndAncestors (theBlock2, TopAbs_VERTEX, TopAbs_FACE, MVF2); TopoDS_Shape aFace1, aFace2; GEOMImpl_Block6Explorer::FindFace(aFace1, V1(1), V1(2), V1(3), V1(4), MVF1); if (aFace1.IsNull()) return REL_UNKNOWN; GEOMImpl_Block6Explorer::FindFace(aFace2, V2(1), V2(2), V2(3), V2(4), MVF2); if (aFace2.IsNull()) return REL_UNKNOWN; // Check of faces coincidence (with some precision) have to be done here // if (!aFace1.IsEqual(aFace2)) return REL_UNKNOWN; // Check of faces sharing if (!aFace1.IsSame(aFace2)) return REL_NOT_GLUED; } return REL_OK; } void FindConnected (const Standard_Integer theBlockIndex, const TColStd_Array2OfInteger& theRelations, TColStd_MapOfInteger& theProcessedMap, TColStd_MapOfInteger& theConnectedMap) { theConnectedMap.Add(theBlockIndex); theProcessedMap.Add(theBlockIndex); Standard_Integer nbBlocks = theRelations.ColLength(); Standard_Integer col = 1; for (; col <= nbBlocks; col++) { if (theRelations(theBlockIndex, col) == REL_OK || theRelations(theBlockIndex, col) == REL_NOT_GLUED) { if (!theProcessedMap.Contains(col)) { FindConnected(col, theRelations, theProcessedMap, theConnectedMap); } } } } Standard_Boolean HasAnyConnection (const Standard_Integer theBlockIndex, const TColStd_MapOfInteger& theWith, const TColStd_Array2OfInteger& theRelations, TColStd_MapOfInteger& theProcessedMap) { theProcessedMap.Add(theBlockIndex); Standard_Integer nbBlocks = theRelations.ColLength(); Standard_Integer col = 1; for (; col <= nbBlocks; col++) { if (theRelations(theBlockIndex, col) != REL_NOT_CONNECTED) { if (!theProcessedMap.Contains(col)) { if (theWith.Contains(col)) return Standard_True; if (HasAnyConnection(col, theWith, theRelations, theProcessedMap)) return Standard_True; } } } return Standard_False; } //============================================================================= /*! * CheckCompoundOfBlocks */ //============================================================================= Standard_Boolean GEOMImpl_IBlocksOperations::CheckCompoundOfBlocks (Handle(GEOM_Object) theCompound, list& 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. Report non-blocks TopTools_ListOfShape NOT; // Not blocks TopTools_ListOfShape BLO; // All blocks from the given compound AddBlocksFrom(aBlockOrComp, BLO, NOT); if (NOT.Extent() > 0) { isCompOfBlocks = Standard_False; BCError anErr; anErr.error = NOT_BLOCK; TopTools_ListIteratorOfListOfShape NOTit (NOT); for (; NOTit.More(); NOTit.Next()) { anErr.incriminated.push_back(anIndices.FindIndex(NOTit.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; } // Convert list of blocks into array for easy and fast access Standard_Integer ibl = 1; TopTools_Array1OfShape aBlocks (1, nbBlocks); TopTools_ListIteratorOfListOfShape BLOit (BLO); for (; BLOit.More(); BLOit.Next(), ibl++) { aBlocks.SetValue(ibl, BLOit.Value()); } // 2. Find relations between all blocks, // report connection errors (NOT_GLUED and INVALID_CONNECTION) TColStd_Array2OfInteger aRelations (1, nbBlocks, 1, nbBlocks); aRelations.Init(REL_NOT_CONNECTED); Standard_Integer row = 1; for (row = 1; row <= nbBlocks; row++) { TopoDS_Shape aBlock = aBlocks.Value(row); Standard_Integer col = row + 1; for (; col <= nbBlocks; col++) { Standard_Integer aRel = BlocksRelation(aBlock, aBlocks.Value(col)); if (aRel != REL_NOT_CONNECTED) { aRelations.SetValue(row, col, aRel); aRelations.SetValue(col, row, aRel); if (aRel == REL_NOT_GLUED) { // report connection error isCompOfBlocks = Standard_False; BCError anErr; anErr.error = NOT_GLUED; anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row))); anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col))); theErrors.push_back(anErr); } else if (aRel == REL_COLLISION_VV || aRel == REL_COLLISION_FF || aRel == REL_COLLISION_EE || aRel == REL_UNKNOWN) { // report connection error isCompOfBlocks = Standard_False; BCError anErr; anErr.error = INVALID_CONNECTION; anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(row))); anErr.incriminated.push_back(anIndices.FindIndex(aBlocks.Value(col))); theErrors.push_back(anErr); } else { } } } } // 3. Find largest set of connected (good connection or not glued) blocks TColStd_MapOfInteger aProcessedMap; TColStd_MapOfInteger aLargestSet; TColStd_MapOfInteger aCurrentSet; for (ibl = 1; ibl <= nbBlocks; ibl++) { if (!aProcessedMap.Contains(ibl)) { FindConnected(ibl, aRelations, aProcessedMap, aCurrentSet); if (aCurrentSet.Extent() > aLargestSet.Extent()) { aLargestSet = aCurrentSet; } } } // 4. Report all blocks, isolated from 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(aBlocks.Value(ibl))); } } } if (hasIsolated) { isCompOfBlocks = Standard_False; theErrors.push_back(anErr); } SetErrorCode(OK); return isCompOfBlocks; } //============================================================================= /*! * PrintBCErrors */ //============================================================================= TCollection_AsciiString GEOMImpl_IBlocksOperations::PrintBCErrors (Handle(GEOM_Object) theCompound, const list& theErrors) { TCollection_AsciiString aDescr; list::const_iterator errIt = theErrors.begin(); int i = 0; for (; errIt != theErrors.end(); i++, errIt++) { BCError errStruct = *errIt; switch (errStruct.error) { case NOT_BLOCK: aDescr += "\nNot a Blocks: "; break; case INVALID_CONNECTION: aDescr += "\nInvalid connection between two blocks: "; break; case NOT_CONNECTED: aDescr += "\nBlocks, not connected with main body: "; break; case NOT_GLUED: aDescr += "\nNot glued blocks: "; break; default: break; } list sshList = errStruct.incriminated; list::iterator sshIt = sshList.begin(); int jj = 0; for (; sshIt != sshList.end(); jj++, sshIt++) { if (jj > 0) aDescr += ", "; aDescr += TCollection_AsciiString(*sshIt); } } return aDescr; } //============================================================================= /*! * ExplodeCompoundOfBlocks */ //============================================================================= Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::ExplodeCompoundOfBlocks (Handle(GEOM_Object) theCompound, const Standard_Integer theMinNbFaces, const Standard_Integer theMaxNbFaces) { SetErrorCode(KO); if (theCompound.IsNull()) return NULL; TopoDS_Shape aBlockOrComp = theCompound->GetValue(); if (aBlockOrComp.IsNull()) return NULL; Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient; Handle(GEOM_Object) anObj; Handle(GEOM_Function) aFunction; TopTools_MapOfShape mapShape; TCollection_AsciiString anAsciiList = "[", anEntry; // Map shapes TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aBlockOrComp, anIndices); Handle(TColStd_HArray1OfInteger) anArray; // Explode try { TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID); for (; exp.More(); exp.Next()) { if (mapShape.Add(exp.Current())) { TopoDS_Shape aSolid = exp.Current(); TopTools_MapOfShape mapFaces; TopExp_Explorer expF (aSolid, TopAbs_FACE); Standard_Integer nbFaces = 0; for (; expF.More(); expF.Next()) { if (mapFaces.Add(expF.Current())) { nbFaces++; } } if (theMinNbFaces <= nbFaces && nbFaces <= theMaxNbFaces) { anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, anIndices.FindIndex(aSolid)); anObj = GetEngine()->AddSubShape(theCompound, anArray); aBlocks->Append(anObj); //Make a Python command TDF_Tool::Entry(anObj->GetEntry(), anEntry); anAsciiList += anEntry; anAsciiList += ","; } } } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return aBlocks; } if (aBlocks->IsEmpty()) { SetErrorCode("There are no specified blocks in the given shape"); return aBlocks; } anAsciiList.Trunc(anAsciiList.Length() - 1); anAsciiList += "]"; //The explode doesn't change object so no new function is required. aFunction = theCompound->GetLastFunction(); //Make a Python command TCollection_AsciiString aDescr (anAsciiList); aDescr += " = IBlocksOperations.ExplodeCompoundOfBlocks("; TDF_Tool::Entry(theCompound->GetEntry(), anEntry); aDescr += anEntry + ", "; aDescr += TCollection_AsciiString(theMinNbFaces) + ", "; aDescr += TCollection_AsciiString(theMaxNbFaces) + ")"; TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n"; aNewDescr += aDescr; aFunction->SetDescription(aNewDescr); SetErrorCode(OK); return aBlocks; } //============================================================================= /*! * GetBlockNearPoint */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockNearPoint (Handle(GEOM_Object) theCompound, Handle(GEOM_Object) thePoint) { SetErrorCode(KO); //New object Handle(GEOM_Object) aResult; // Arguments if (theCompound.IsNull() || thePoint.IsNull()) return NULL; TopoDS_Shape aBlockOrComp = theCompound->GetValue(); if (aBlockOrComp.IsNull()) { SetErrorCode("Compound is null"); return NULL; } if (aBlockOrComp.ShapeType() != TopAbs_COMPOUND && aBlockOrComp.ShapeType() != TopAbs_COMPSOLID) { SetErrorCode("Shape is neither a block, nor a compound of blocks"); return NULL; } TopoDS_Shape anArg = thePoint->GetValue(); if (anArg.IsNull()) { SetErrorCode("Null shape is given as argument"); return NULL; } if (anArg.ShapeType() != TopAbs_VERTEX) { SetErrorCode("Element for block identification is not a vertex"); return NULL; } //Compute the Block value try { TopoDS_Shape aShape; TopoDS_Vertex aVert = TopoDS::Vertex(anArg); gp_Pnt aPnt = BRep_Tool::Pnt(aVert); // 1. Explode compound on blocks TopTools_MapOfShape mapShape; Standard_Integer nbSolids = 0; TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID); for (; exp.More(); exp.Next()) { if (mapShape.Add(exp.Current())) { nbSolids++; } } mapShape.Clear(); Standard_Integer ind = 1; TopTools_Array1OfShape aSolids (1, nbSolids); TColStd_Array1OfInteger aDistances (1, nbSolids); for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next()) { if (mapShape.Add(exp.Current())) { TopoDS_Shape aSolid = exp.Current(); aSolids(ind) = aSolid; // 2. Classify the point relatively each block BRepClass3d_SolidClassifier SC (aSolid, aPnt, Precision::Confusion()); if (SC.State() == TopAbs_IN) { aDistances(ind) = -1; } else if (SC.State() == TopAbs_ON) { aDistances(ind) = 0; } else { // OUT aDistances(ind) = 1; } ind++; } } // 3. Define block, containing the point or having minimum distance to it Standard_Integer nearest = 2, nbFound = 0; for (ind = 1; ind <= nbSolids; ind++) { if (aDistances(ind) < nearest) { nearest = aDistances(ind); aShape = aSolids(ind); nbFound = 1; } else if (aDistances(ind) == nearest) { nbFound++; } else { } } if (nbFound > 1) { if (nearest == 0) { // The point is on boundary of some blocks and there are // no blocks, having the point inside their volume SetErrorCode("Multiple blocks near the given point are found"); return NULL; } else if (nearest == 1) { // The point is outside some blocks and there are // no blocks, having the point inside or on boundary. // We will get a nearest block Standard_Real minDist = RealLast(); for (ind = 1; ind <= nbSolids; ind++) { if (aDistances(ind) == 1) { BRepExtrema_DistShapeShape aDistTool (aVert, aSolids(ind)); if (!aDistTool.IsDone()) { SetErrorCode("Can not find a distance from the given point to one of blocks"); return NULL; } Standard_Real aDist = aDistTool.Value(); if (aDist < minDist) { minDist = aDist; aShape = aSolids(ind); } } } } else { // nearest == -1 // The point is inside some blocks. // We will get a block with nearest center Standard_Real minDist = RealLast(); for (ind = 1; ind <= nbSolids; ind++) { if (aDistances(ind) == -1) { GProp_GProps aSystem; BRepGProp::VolumeProperties(aSolids(ind), aSystem); gp_Pnt aCenterMass = aSystem.CentreOfMass(); Standard_Real aDist = aCenterMass.Distance(aPnt); if (aDist < minDist) { minDist = aDist; aShape = aSolids(ind); } } } } } if (nbFound == 0) { SetErrorCode("There are no blocks near the given point"); return NULL; } else { TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aBlockOrComp, anIndices); Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, anIndices.FindIndex(aShape)); aResult = GetEngine()->AddSubShape(theCompound, anArray); } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //The GetBlockNearPoint() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = theCompound->GetLastFunction(); //Make a Python command TCollection_AsciiString anEntry, aDescr; TDF_Tool::Entry(aResult->GetEntry(), anEntry); aDescr += anEntry + " = IBlocksOperations.GetBlockNearPoint("; TDF_Tool::Entry(theCompound->GetEntry(), anEntry); aDescr += anEntry + ", "; TDF_Tool::Entry(thePoint->GetEntry(), anEntry); aDescr += anEntry + ")"; TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n"; aNewDescr += aDescr; aFunction->SetDescription(aNewDescr); SetErrorCode(OK); return aResult; } //============================================================================= /*! * GetBlockByParts */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IBlocksOperations::GetBlockByParts (Handle(GEOM_Object) theCompound, const Handle(TColStd_HSequenceOfTransient)& theParts) { SetErrorCode(KO); Handle(GEOM_Object) aResult; if (theCompound.IsNull() || theParts.IsNull()) return NULL; TopoDS_Shape aBlockOrComp = theCompound->GetValue(); if (aBlockOrComp.IsNull()) return NULL; //Get the parts Standard_Integer argi, aLen = theParts->Length(); TopTools_Array1OfShape anArgs (1, aLen); TCollection_AsciiString anEntry, aPartsDescr; for (argi = 1; argi <= aLen; argi++) { Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi)); Handle(GEOM_Function) aRef = anObj->GetLastFunction(); if (aRef.IsNull()) return NULL; TopoDS_Shape anArg = aRef->GetValue(); if (anArg.IsNull()) { SetErrorCode("Null shape is given as argument"); return NULL; } anArgs(argi) = anArg; // For Python command TDF_Tool::Entry(anObj->GetEntry(), anEntry); if (argi > 1) aPartsDescr += ", "; aPartsDescr += anEntry; } //Compute the Block value try { // 1. Explode compound on solids TopTools_MapOfShape mapShape; Standard_Integer nbSolids = 0; TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID); for (; exp.More(); exp.Next()) { if (mapShape.Add(exp.Current())) { nbSolids++; } } mapShape.Clear(); Standard_Integer ind = 1; TopTools_Array1OfShape aSolids (1, nbSolids); TColStd_Array1OfInteger aNbParts (1, nbSolids); for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) { if (mapShape.Add(exp.Current())) { TopoDS_Shape aSolid = exp.Current(); aSolids(ind) = aSolid; aNbParts(ind) = 0; // 2. Define quantity of parts, contained in each solid TopTools_IndexedMapOfShape aSubShapes; TopExp::MapShapes(aSolid, aSubShapes); for (argi = 1; argi <= aLen; argi++) { if (aSubShapes.Contains(anArgs(argi))) { aNbParts(ind)++; } } } } // 3. Define solid, containing maximum quantity of parts Standard_Integer maxNb = 0, nbFound = 0; TopoDS_Shape aShape; for (ind = 1; ind <= nbSolids; ind++) { if (aNbParts(ind) > maxNb) { maxNb = aNbParts(ind); aShape = aSolids(ind); nbFound = 1; } else if (aNbParts(ind) == maxNb) { nbFound++; } else { } } if (nbFound > 1) { SetErrorCode("Multiple blocks, containing maximum quantity of the given parts, are found"); return NULL; } else if (nbFound == 0) { SetErrorCode("There are no blocks, containing the given parts"); return NULL; } else { TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aBlockOrComp, anIndices); Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, anIndices.FindIndex(aShape)); aResult = GetEngine()->AddSubShape(theCompound, anArray); } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //The GetBlockByParts() doesn't change object so no new function is required. Handle(GEOM_Function) aFunction = theCompound->GetLastFunction(); //Make a Python command TDF_Tool::Entry(aResult->GetEntry(), anEntry); TCollection_AsciiString aDescr (anEntry); aDescr += " = IBlocksOperations.GetBlockByParts("; TDF_Tool::Entry(theCompound->GetEntry(), anEntry); aDescr += anEntry + ", ["; aDescr += aPartsDescr + "])"; TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n"; aNewDescr += aDescr; aFunction->SetDescription(aNewDescr); SetErrorCode(OK); return aResult; } //============================================================================= /*! * GetBlocksByParts */ //============================================================================= Handle(TColStd_HSequenceOfTransient) GEOMImpl_IBlocksOperations::GetBlocksByParts (Handle(GEOM_Object) theCompound, const Handle(TColStd_HSequenceOfTransient)& theParts) { SetErrorCode(KO); if (theCompound.IsNull() || theParts.IsNull()) return NULL; TopoDS_Shape aBlockOrComp = theCompound->GetValue(); if (aBlockOrComp.IsNull()) return NULL; Handle(TColStd_HSequenceOfTransient) aBlocks = new TColStd_HSequenceOfTransient; Handle(GEOM_Object) anObj; Handle(GEOM_Function) aFunction; //Get the parts Standard_Integer argi, aLen = theParts->Length(); TopTools_Array1OfShape anArgs (1, aLen); TCollection_AsciiString anEntry, aPartsDescr, anAsciiList = "["; for (argi = 1; argi <= aLen; argi++) { Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(theParts->Value(argi)); Handle(GEOM_Function) aRef = anObj->GetLastFunction(); if (aRef.IsNull()) return NULL; TopoDS_Shape anArg = aRef->GetValue(); if (anArg.IsNull()) { SetErrorCode("Null shape is given as argument"); return NULL; } anArgs(argi) = anArg; // For Python command TDF_Tool::Entry(anObj->GetEntry(), anEntry); if (argi > 1) aPartsDescr += ", "; aPartsDescr += anEntry; } //Get the Blocks try { TopTools_MapOfShape mapShape; Standard_Integer nbSolids = 0; TopExp_Explorer exp (aBlockOrComp, TopAbs_SOLID); for (; exp.More(); exp.Next()) { if (mapShape.Add(exp.Current())) { nbSolids++; } } mapShape.Clear(); Standard_Integer ind = 1; TopTools_Array1OfShape aSolids (1, nbSolids); TColStd_Array1OfInteger aNbParts (1, nbSolids); for (exp.Init(aBlockOrComp, TopAbs_SOLID); exp.More(); exp.Next(), ind++) { if (mapShape.Add(exp.Current())) { TopoDS_Shape aSolid = exp.Current(); aSolids(ind) = aSolid; aNbParts(ind) = 0; // 2. Define quantity of parts, contained in each solid TopTools_IndexedMapOfShape aSubShapes; TopExp::MapShapes(aSolid, aSubShapes); for (argi = 1; argi <= aLen; argi++) { if (aSubShapes.Contains(anArgs(argi))) { aNbParts(ind)++; } } } } // 3. Define solid, containing maximum quantity of parts Standard_Integer maxNb = 0, nbFound = 0; for (ind = 1; ind <= nbSolids; ind++) { if (aNbParts(ind) > maxNb) { maxNb = aNbParts(ind); nbFound = 1; } else if (aNbParts(ind) == maxNb) { nbFound++; } else { } } if (nbFound == 0) { SetErrorCode("There are no blocks, containing the given parts"); return NULL; } // Map shapes TopTools_IndexedMapOfShape anIndices; TopExp::MapShapes(aBlockOrComp, anIndices); Handle(TColStd_HArray1OfInteger) anArray; for (ind = 1; ind <= nbSolids; ind++) { if (aNbParts(ind) == maxNb) { anArray = new TColStd_HArray1OfInteger(1,1); anArray->SetValue(1, anIndices.FindIndex(aSolids(ind))); anObj = GetEngine()->AddSubShape(theCompound, anArray); aBlocks->Append(anObj); //Make a Python command TDF_Tool::Entry(anObj->GetEntry(), anEntry); anAsciiList += anEntry; anAsciiList += ","; } } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } anAsciiList.Trunc(anAsciiList.Length() - 1); anAsciiList += "]"; //The GetBlocksByParts() doesn't change object so no new function is required. aFunction = theCompound->GetLastFunction(); //Make a Python command TCollection_AsciiString aDescr (anAsciiList); aDescr += " = IBlocksOperations.GetBlocksByParts("; TDF_Tool::Entry(theCompound->GetEntry(), anEntry); aDescr += anEntry + ", ["; aDescr += aPartsDescr + "])"; TCollection_AsciiString aNewDescr = aFunction->GetDescription() + "\n"; aNewDescr += aDescr; aFunction->SetDescription(aNewDescr); SetErrorCode(OK); return aBlocks; } //============================================================================= /*! * MakeMultiTransformation1D */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation1D (Handle(GEOM_Object) theObject, const Standard_Integer theDirFace1, const Standard_Integer theDirFace2, const Standard_Integer theNbTimes) { 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 moved //Add a new Copy object Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY); //Add a translate function Handle(GEOM_Function) aFunction = aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_1D); //Check if the function is set correctly if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL; GEOMImpl_IBlockTrsf aTI (aFunction); aTI.SetOriginal(aLastFunction); aTI.SetFace1U(theDirFace1); aTI.SetFace2U(theDirFace2); aTI.SetNbIterU(theNbTimes); //Compute the transformation try { if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Block driver failed to make multi-transformation"); return NULL; } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //Make a Python command TCollection_AsciiString anEntry, aDescr; TDF_Tool::Entry(aCopy->GetEntry(), anEntry); aDescr += anEntry + " = IBlocksOperations.MakeMultiTransformation1D("; TDF_Tool::Entry(theObject->GetEntry(), anEntry); aDescr += anEntry + ", "; aDescr += TCollection_AsciiString(theDirFace1) + ", "; aDescr += TCollection_AsciiString(theDirFace2) + ", "; aDescr += TCollection_AsciiString(theNbTimes) + ") "; aFunction->SetDescription(aDescr); SetErrorCode(OK); return aCopy; } //============================================================================= /*! * MakeMultiTransformation2D */ //============================================================================= Handle(GEOM_Object) GEOMImpl_IBlocksOperations::MakeMultiTransformation2D (Handle(GEOM_Object) theObject, const Standard_Integer theDirFace1U, const Standard_Integer theDirFace2U, const Standard_Integer theNbTimesU, const Standard_Integer theDirFace1V, const Standard_Integer theDirFace2V, const Standard_Integer theNbTimesV) { 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 moved //Add a new Copy object Handle(GEOM_Object) aCopy = GetEngine()->AddObject(GetDocID(), GEOM_COPY); //Add a translate function Handle(GEOM_Function) aFunction = aCopy->AddFunction(GEOMImpl_BlockDriver::GetID(), BLOCK_MULTI_TRANSFORM_2D); //Check if the function is set correctly if (aFunction->GetDriverGUID() != GEOMImpl_BlockDriver::GetID()) return NULL; GEOMImpl_IBlockTrsf aTI (aFunction); aTI.SetOriginal(aLastFunction); aTI.SetFace1U(theDirFace1U); aTI.SetFace2U(theDirFace2U); aTI.SetNbIterU(theNbTimesU); aTI.SetFace1V(theDirFace1V); aTI.SetFace2V(theDirFace2V); aTI.SetNbIterV(theNbTimesV); //Compute the transformation try { if (!GetSolver()->ComputeFunction(aFunction)) { SetErrorCode("Block driver failed to make multi-transformation"); return NULL; } } catch (Standard_Failure) { Handle(Standard_Failure) aFail = Standard_Failure::Caught(); SetErrorCode(aFail->GetMessageString()); return NULL; } //Make a Python command TCollection_AsciiString anEntry, aDescr; TDF_Tool::Entry(aCopy->GetEntry(), anEntry); aDescr += anEntry + " = IBlocksOperations.MakeMultiTransformation2D("; TDF_Tool::Entry(theObject->GetEntry(), anEntry); aDescr += anEntry + ", "; aDescr += TCollection_AsciiString(theDirFace1U) + ", "; aDescr += TCollection_AsciiString(theDirFace2U) + ", "; aDescr += TCollection_AsciiString(theNbTimesU) + ", "; aDescr += TCollection_AsciiString(theDirFace1V) + ", "; aDescr += TCollection_AsciiString(theDirFace2V) + ", "; aDescr += TCollection_AsciiString(theNbTimesV) + ") "; aFunction->SetDescription(aDescr); SetErrorCode(OK); return aCopy; }