+//=============================================================================
+/*!
+ * GetFreeFacesIDs
+ */
+//=============================================================================
+Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetFreeFacesIDs
+ (Handle(GEOM_Object) theShape)
+{
+ SetErrorCode(KO);
+
+ if (theShape.IsNull()) return NULL;
+ TopoDS_Shape aShape = theShape->GetValue();
+ if (aShape.IsNull()) return NULL;
+
+ Handle(TColStd_HSequenceOfInteger) aSeq = new TColStd_HSequenceOfInteger;
+
+ TopTools_IndexedDataMapOfShapeListOfShape mapFaceBlocks;
+ GEOMImpl_Block6Explorer::MapShapesAndAncestors
+ (aShape, TopAbs_FACE, TopAbs_SOLID, mapFaceBlocks);
+
+ Standard_Integer ind = 1, nbFaces = mapFaceBlocks.Extent();
+
+ if (nbFaces == 0) {
+ SetErrorCode("The given shape has no faces");
+ return aSeq;
+ }
+
+ TopTools_IndexedMapOfShape anIndices;
+ TopExp::MapShapes(aShape, anIndices);
+
+ Standard_Integer id;
+ for (; ind <= nbFaces; ind++) {
+ if (mapFaceBlocks.FindFromIndex(ind).Extent() != 2) {
+ id = anIndices.FindIndex(mapFaceBlocks.FindKey(ind));
+ aSeq->Append(id);
+ }
+ }
+
+ //The explode doesn't change object so no new function is required.
+ Handle(GEOM_Function) aFunction = theShape->GetLastFunction();
+
+ //Make a Python command
+ GEOM::TPythonDump(aFunction, /*append=*/true)
+ << "listFreeFacesIDs = geompy.GetFreeFacesIDs(" << theShape << ")";
+
+ SetErrorCode(OK);
+ return aSeq;
+}
+
+//=======================================================================
+//function : GetSharedShapes
+//purpose :
+//=======================================================================
+Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
+ (Handle(GEOM_Object) theShape1,
+ Handle(GEOM_Object) theShape2,
+ const Standard_Integer theShapeType)
+{
+ SetErrorCode(KO);
+
+ if (theShape1.IsNull() || theShape2.IsNull()) return NULL;
+
+ TopoDS_Shape aShape1 = theShape1->GetValue();
+ TopoDS_Shape aShape2 = theShape2->GetValue();
+
+ if (aShape1.IsNull() || aShape2.IsNull()) return NULL;
+
+ TopTools_IndexedMapOfShape anIndices;
+ TopExp::MapShapes(aShape1, anIndices);
+ Handle(TColStd_HArray1OfInteger) anArray;
+
+ TopTools_IndexedMapOfShape mapShape1;
+ TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapShape1);
+
+ Handle(GEOM_Object) anObj;
+ Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
+ TCollection_AsciiString anAsciiList, anEntry;
+
+ TopTools_MapOfShape mapShape2;
+ TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
+ for (; exp.More(); exp.Next()) {
+ TopoDS_Shape aSS = exp.Current();
+ if (mapShape2.Add(aSS) && mapShape1.Contains(aSS)) {
+ anArray = new TColStd_HArray1OfInteger(1,1);
+ anArray->SetValue(1, anIndices.FindIndex(aSS));
+ anObj = GetEngine()->AddSubShape(theShape1, anArray);
+ aSeq->Append(anObj);
+
+ // for python command
+ TDF_Tool::Entry(anObj->GetEntry(), anEntry);
+ anAsciiList += anEntry;
+ anAsciiList += ",";
+ }
+ }
+
+ if (aSeq->IsEmpty()) {
+ SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
+ return aSeq;
+ }
+
+ //Make a Python command
+ anAsciiList.Trunc(anAsciiList.Length() - 1);
+
+ Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
+
+ GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
+ << "] = geompy.GetSharedShapes(" << theShape1 << ", "
+ << theShape2 << ", " << TopAbs_ShapeEnum(theShapeType) << ")";
+
+ SetErrorCode(OK);
+ return aSeq;
+}
+
+//=============================================================================
+/*!
+ *
+ */
+//=============================================================================
+static GEOM::TPythonDump& operator<< (GEOM::TPythonDump& theDump,
+ const GEOMAlgo_State theState)
+{
+ switch (theState) {
+ case GEOMAlgo_ST_IN:
+ theDump << "geompy.GEOM.ST_IN";
+ break;
+ case GEOMAlgo_ST_OUT:
+ theDump << "geompy.GEOM.ST_OUT";
+ break;
+ case GEOMAlgo_ST_ON:
+ theDump << "geompy.GEOM.ST_ON";
+ break;
+ case GEOMAlgo_ST_ONIN:
+ theDump << "geompy.GEOM.ST_ONIN";
+ break;
+ case GEOMAlgo_ST_ONOUT:
+ theDump << "geompy.GEOM.ST_ONOUT";
+ break;
+ default:
+ theDump << "geompy.GEOM.ST_UNKNOWN";
+ break;
+ }
+ return theDump;
+}
+
+//=======================================================================
+//function : checkTypeShapesOn
+/*!
+ * \brief Checks if theShapeType parameter of GetShapesOnXXX() is OK
+ * \param theShapeType - the shape type to check
+ * \retval bool - result of the check
+ */
+//=======================================================================
+bool GEOMImpl_IShapesOperations::checkTypeShapesOn(const Standard_Integer theShapeType)
+{
+ if (theShapeType != TopAbs_VERTEX &&
+ theShapeType != TopAbs_EDGE &&
+ theShapeType != TopAbs_FACE &&
+ theShapeType != TopAbs_SOLID) {
+ SetErrorCode("Only solids, vertices, edges or faces can be found by this method");
+ return false;
+ }
+ return true;
+}
+
+//=======================================================================
+//function : makePlane
+ /*!
+ * \brief Creates Geom_Plane
+ * \param theAx1 - shape object defining plane parameters
+ * \retval Handle(Geom_Surface) - resulting surface
+ */
+//=======================================================================
+Handle(Geom_Surface) GEOMImpl_IShapesOperations::makePlane(const TopoDS_Shape& anAx1)
+{
+ if (anAx1.ShapeType() != TopAbs_EDGE) return NULL;
+ TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
+ TopoDS_Vertex V1, V2;
+ TopExp::Vertices(anEdge, V1, V2, Standard_True);
+ if (V1.IsNull() || V2.IsNull()) {
+ SetErrorCode("Bad edge given for the plane normal vector");
+ return NULL;
+ }
+ gp_Pnt aLoc = BRep_Tool::Pnt(V1);
+ gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
+ if (aVec.Magnitude() < Precision::Confusion()) {
+ SetErrorCode("Vector with null magnitude given");
+ return NULL;
+ }
+ return new Geom_Plane(aLoc, aVec);
+}
+
+//=======================================================================
+//function : makeCylinder
+ /*!
+ * \brief Creates Geom_CylindricalSurface
+ * \param theAx1 - edge defining cylinder axis
+ * \param theRadius - cylinder radius
+ * \retval Handle(Geom_Surface) - resulting surface
+ */
+//=======================================================================
+Handle(Geom_Surface) GEOMImpl_IShapesOperations::makeCylinder(const TopoDS_Shape& anAxis,
+ const Standard_Real theRadius)
+{
+ //Axis of the cylinder
+ if (anAxis.ShapeType() != TopAbs_EDGE) {
+ SetErrorCode("Not an edge given for the axis");
+ return NULL;
+ }
+ TopoDS_Edge anEdge = TopoDS::Edge(anAxis);
+ TopoDS_Vertex V1, V2;
+ TopExp::Vertices(anEdge, V1, V2, Standard_True);
+ if (V1.IsNull() || V2.IsNull()) {
+ SetErrorCode("Bad edge given for the axis");
+ return NULL;
+ }
+ gp_Pnt aLoc = BRep_Tool::Pnt(V1);
+ gp_Vec aVec (aLoc, BRep_Tool::Pnt(V2));
+ if (aVec.Magnitude() < Precision::Confusion()) {
+ SetErrorCode("Vector with null magnitude given");
+ return NULL;
+ }
+
+ gp_Ax3 anAx3 (aLoc, aVec);
+ return new Geom_CylindricalSurface(anAx3, theRadius);
+}
+
+//=======================================================================
+//function : getShapesOnBoxIDs
+ /*!
+ * \brief Find IDs of subshapes complying with given status about surface
+ * \param theBox - the box to check state of subshapes against
+ * \param theShape - the shape to explore
+ * \param theShapeType - type of subshape of theShape
+ * \param theState - required state
+ * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
+ */
+//=======================================================================
+Handle(TColStd_HSequenceOfInteger)
+ GEOMImpl_IShapesOperations::getShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
+ const Handle(GEOM_Object)& theShape,
+ const Standard_Integer theShapeType,
+ GEOMAlgo_State theState)
+{
+ Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
+
+ TopoDS_Shape aBox = theBox->GetValue();
+ TopoDS_Shape aShape = theShape->GetValue();
+
+ // Check presence of triangulation, build if need
+ if (!CheckTriangulation(aShape)) {
+ SetErrorCode("Cannot build triangulation on the shape");
+ return aSeqOfIDs;
+ }
+
+ // Call algo
+ GEOMAlgo_FinderShapeOn2 aFinder;
+ Standard_Real aTol = 0.0001; // default value
+
+ Handle(GEOMAlgo_ClsfBox) aClsfBox = new GEOMAlgo_ClsfBox;
+ aClsfBox->SetBox(aBox);
+
+ aFinder.SetShape(aShape);
+ aFinder.SetTolerance(aTol);
+ aFinder.SetClsf(aClsfBox);
+ aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
+ aFinder.SetState(theState);
+ aFinder.Perform();
+
+ // Interprete results
+ Standard_Integer iErr = aFinder.ErrorStatus();
+ // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
+ if (iErr) {
+ MESSAGE(" iErr : " << iErr);
+ TCollection_AsciiString aMsg (" iErr : ");
+ aMsg += TCollection_AsciiString(iErr);
+ SetErrorCode(aMsg);
+ return aSeqOfIDs;
+ }
+ Standard_Integer iWrn = aFinder.WarningStatus();
+ // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
+ if (iWrn) {
+ MESSAGE(" *** iWrn : " << iWrn);
+ }
+
+ const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
+
+ if (listSS.Extent() < 1) {
+ //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
+ SetErrorCode(NOT_FOUND_ANY); // NPAL18017
+ return aSeqOfIDs;
+ }
+
+ // Fill sequence of object IDs
+ aSeqOfIDs = new TColStd_HSequenceOfInteger;
+
+ TopTools_IndexedMapOfShape anIndices;
+ TopExp::MapShapes(aShape, anIndices);
+
+ TopTools_ListIteratorOfListOfShape itSub (listSS);
+ for (int index = 1; itSub.More(); itSub.Next(), ++index) {
+ int id = anIndices.FindIndex(itSub.Value());
+ aSeqOfIDs->Append(id);
+ }
+
+ return aSeqOfIDs;
+}
+
+//=======================================================================
+//function : GetShapesOnBoxIDs
+/*!
+ * \brief Find subshapes complying with given status about surface
+ * \param theBox - the box to check state of subshapes against
+ * \param theShape - the shape to explore
+ * \param theShapeType - type of subshape of theShape
+ * \param theState - required state
+ * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
+ */
+//=======================================================================
+Handle(TColStd_HSequenceOfInteger)
+ GEOMImpl_IShapesOperations::GetShapesOnBoxIDs(const Handle(GEOM_Object)& theBox,
+ const Handle(GEOM_Object)& theShape,
+ const Standard_Integer theShapeType,
+ GEOMAlgo_State theState)
+{
+ // Find subshapes ids
+ Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
+ getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
+ if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
+ return NULL;
+
+ // The GetShapesOnBox() doesn't change object so no new function is required.
+ Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theBox)->GetLastFunction();
+
+ // Make a Python command
+ GEOM::TPythonDump(aFunction)
+ << "listShapesOnBoxIDs = geompy.GetShapesOnBoxIDs("
+ << theBox << ", "
+ << theShape << ", "
+ << TopAbs_ShapeEnum(theShapeType) << ", "
+ << theState << ")";
+
+ SetErrorCode(OK);
+ return aSeqOfIDs;
+}
+
+//=======================================================================
+//function : GetShapesOnBox
+/*!
+ * \brief Find subshapes complying with given status about surface
+ * \param theBox - the box to check state of subshapes against
+ * \param theShape - the shape to explore
+ * \param theShapeType - type of subshape of theShape
+ * \param theState - required state
+ * \retval Handle(TColStd_HSequenceOfTransient) - found subshapes
+ */
+//=======================================================================
+Handle(TColStd_HSequenceOfTransient)
+ GEOMImpl_IShapesOperations::GetShapesOnBox(const Handle(GEOM_Object)& theBox,
+ const Handle(GEOM_Object)& theShape,
+ const Standard_Integer theShapeType,
+ GEOMAlgo_State theState)
+{
+ // Find subshapes ids
+ Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
+ getShapesOnBoxIDs (theBox, theShape, theShapeType, theState);
+ if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
+ return NULL;
+
+ // Find objects by indices
+ TCollection_AsciiString anAsciiList;
+ Handle(TColStd_HSequenceOfTransient) aSeq;
+ aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
+ if ( aSeq.IsNull() || aSeq->IsEmpty() )
+ return NULL;
+
+ // Make a Python command
+
+ Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
+ Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
+
+ GEOM::TPythonDump(aFunction)
+ << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnBox("
+ << theBox << ", "
+ << theShape << ", "
+ << TopAbs_ShapeEnum(theShapeType) << ", "
+ << theState << ")";
+
+ SetErrorCode(OK);
+ return aSeq;
+}
+
+//=======================================================================
+//function : getShapesOnShapeIDs
+/*!
+ * \brief Find IDs of subshapes complying with given status about surface
+ * \param theCheckShape - the shape to check state of subshapes against
+ * \param theShape - the shape to explore
+ * \param theShapeType - type of subshape of theShape
+ * \param theState - required state
+ * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
+ */
+//=======================================================================
+Handle(TColStd_HSequenceOfInteger)
+ GEOMImpl_IShapesOperations::getShapesOnShapeIDs
+ (const Handle(GEOM_Object)& theCheckShape,
+ const Handle(GEOM_Object)& theShape,
+ const Standard_Integer theShapeType,
+ GEOMAlgo_State theState)
+{
+ Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
+
+ TopoDS_Shape aCheckShape = theCheckShape->GetValue();
+ TopoDS_Shape aShape = theShape->GetValue();
+ TopTools_ListOfShape res;
+
+ // Check presence of triangulation, build if need
+ if (!CheckTriangulation(aShape)) {
+ SetErrorCode("Cannot build triangulation on the shape");
+ return aSeqOfIDs;
+ }
+
+ // Call algo
+ GEOMAlgo_FinderShapeOn2 aFinder;
+ Standard_Real aTol = 0.0001; // default value
+
+ Handle(GEOMAlgo_ClsfSolid) aClsfSolid = new GEOMAlgo_ClsfSolid;
+ aClsfSolid->SetShape(aCheckShape);
+
+ aFinder.SetShape(aShape);
+ aFinder.SetTolerance(aTol);
+ aFinder.SetClsf(aClsfSolid);
+ aFinder.SetShapeType( (TopAbs_ShapeEnum)theShapeType );
+ aFinder.SetState(theState);
+ aFinder.Perform();
+
+ // Interprete results
+ Standard_Integer iErr = aFinder.ErrorStatus();
+ // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
+ if (iErr) {
+ MESSAGE(" iErr : " << iErr);
+ TCollection_AsciiString aMsg (" iErr : ");
+ aMsg += TCollection_AsciiString(iErr);
+ SetErrorCode(aMsg);
+ return aSeqOfIDs;
+ }
+ Standard_Integer iWrn = aFinder.WarningStatus();
+ // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
+ if (iWrn) {
+ MESSAGE(" *** iWrn : " << iWrn);
+ }
+
+ const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
+
+ if (listSS.Extent() < 1) {
+ //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
+ SetErrorCode(NOT_FOUND_ANY); // NPAL18017
+ }
+
+ // Fill sequence of object IDs
+ aSeqOfIDs = new TColStd_HSequenceOfInteger;
+
+ TopTools_IndexedMapOfShape anIndices;
+ TopExp::MapShapes(aShape, anIndices);
+
+ TopTools_ListIteratorOfListOfShape itSub (listSS);
+ for (int index = 1; itSub.More(); itSub.Next(), ++index) {
+ int id = anIndices.FindIndex(itSub.Value());
+ aSeqOfIDs->Append(id);
+ }
+
+ return aSeqOfIDs;
+}
+
+//=======================================================================
+//function : GetShapesOnShapeIDs
+/*!
+ * \brief Find subshapes complying with given status about surface
+ * \param theCheckShape - the shape to check state of subshapes against
+ * \param theShape - the shape to explore
+ * \param theShapeType - type of subshape of theShape
+ * \param theState - required state
+ * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
+ */
+//=======================================================================
+Handle(TColStd_HSequenceOfInteger)
+ GEOMImpl_IShapesOperations::GetShapesOnShapeIDs
+ (const Handle(GEOM_Object)& theCheckShape,
+ const Handle(GEOM_Object)& theShape,
+ const Standard_Integer theShapeType,
+ GEOMAlgo_State theState)
+{
+ Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
+ getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
+
+ if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
+ return NULL;
+
+ // The GetShapesOnShape() doesn't change object so no new function is required.
+ Handle(GEOM_Function) aFunction =
+ GEOM::GetCreatedLast(theShape,theCheckShape)->GetLastFunction();
+
+ // Make a Python command
+ GEOM::TPythonDump(aFunction)
+ << "listShapesOnBoxIDs = geompy.GetShapesOnShapeIDs("
+ << theCheckShape << ", "
+ << theShape << ", "
+ << TopAbs_ShapeEnum(theShapeType) << ", "
+ << theState << ")";
+
+ SetErrorCode(OK);
+ return aSeqOfIDs;
+}
+
+//=======================================================================
+//function : GetShapesOnShape
+/*!
+ * \brief Find subshapes complying with given status about surface
+ * \param theCheckShape - the shape to check state of subshapes against
+ * \param theShape - the shape to explore
+ * \param theShapeType - type of subshape of theShape
+ * \param theState - required state
+ * \retval Handle(TColStd_HSequenceOfTransient) - found subshapes
+ */
+//=======================================================================
+Handle(TColStd_HSequenceOfTransient)
+ GEOMImpl_IShapesOperations::GetShapesOnShape
+ (const Handle(GEOM_Object)& theCheckShape,
+ const Handle(GEOM_Object)& theShape,
+ const Standard_Integer theShapeType,
+ GEOMAlgo_State theState)
+{
+ Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
+ getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
+ if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
+ return NULL;
+
+ // Find objects by indices
+ TCollection_AsciiString anAsciiList;
+ Handle(TColStd_HSequenceOfTransient) aSeq;
+ aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
+
+ if ( aSeq.IsNull() || aSeq->IsEmpty() )
+ return NULL;
+
+ // Make a Python command
+
+ Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
+ Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
+
+ GEOM::TPythonDump(aFunction)
+ << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnShape("
+ << theCheckShape << ", "
+ << theShape << ", "
+ << TopAbs_ShapeEnum(theShapeType) << ", "
+ << theState << ")";
+
+ SetErrorCode(OK);
+ return aSeq;
+}
+
+//=======================================================================
+//function : GetShapesOnShapeAsCompound
+//=======================================================================
+Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnShapeAsCompound
+ (const Handle(GEOM_Object)& theCheckShape,
+ const Handle(GEOM_Object)& theShape,
+ const Standard_Integer theShapeType,
+ GEOMAlgo_State theState)
+{
+ Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
+ getShapesOnShapeIDs (theCheckShape, theShape, theShapeType, theState);
+
+ if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
+ return NULL;
+
+ // Find objects by indices
+ TCollection_AsciiString anAsciiList;
+ Handle(TColStd_HSequenceOfTransient) aSeq;
+ aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
+
+ if ( aSeq.IsNull() || aSeq->IsEmpty() )
+ return NULL;
+
+ TopoDS_Compound aCompound;
+ BRep_Builder B;
+ B.MakeCompound(aCompound);
+ int i = 1;
+ for(; i<=aSeq->Length(); i++) {
+ Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast(aSeq->Value(i));
+ TopoDS_Shape aShape_i = anObj->GetValue();
+ B.Add(aCompound,aShape_i);
+ }
+
+ //Add a new result object
+ Handle(GEOM_Object) aRes = GetEngine()->AddObject(GetDocID(), GEOM_SHAPES_ON_SHAPE);
+ Handle(GEOM_Function) aFunction =
+ aRes->AddFunction(GEOMImpl_ShapeDriver::GetID(), SHAPES_ON_SHAPE);
+ aFunction->SetValue(aCompound);
+
+ GEOM::TPythonDump(aFunction)
+ << aRes << " = geompy.GetShapesOnShapeAsCompound("
+ << theCheckShape << ", "
+ << theShape << ", "
+ << TopAbs_ShapeEnum(theShapeType) << ", "
+ << theState << ")";
+
+ SetErrorCode(OK);
+
+ return aRes;
+}
+
+//=======================================================================
+//function : getShapesOnSurfaceIDs
+ /*!
+ * \brief Find IDs of subshapes complying with given status about surface
+ * \param theSurface - the surface to check state of subshapes against
+ * \param theShape - the shape to explore
+ * \param theShapeType - type of subshape of theShape
+ * \param theState - required state
+ * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
+ */
+//=======================================================================
+Handle(TColStd_HSequenceOfInteger)
+ GEOMImpl_IShapesOperations::getShapesOnSurfaceIDs(const Handle(Geom_Surface)& theSurface,
+ const TopoDS_Shape& theShape,
+ TopAbs_ShapeEnum theShapeType,
+ GEOMAlgo_State theState)
+{
+ Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
+
+ // Check presence of triangulation, build if need
+ if (!CheckTriangulation(theShape)) {
+ SetErrorCode("Cannot build triangulation on the shape");
+ return aSeqOfIDs;
+ }
+
+ // Call algo
+ GEOMAlgo_FinderShapeOn1 aFinder;
+ Standard_Real aTol = 0.0001; // default value
+
+ aFinder.SetShape(theShape);
+ aFinder.SetTolerance(aTol);
+ aFinder.SetSurface(theSurface);
+ aFinder.SetShapeType(theShapeType);
+ aFinder.SetState(theState);
+
+ // Sets the minimal number of inner points for the faces that do not have own
+ // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
+ // Default value=3
+ aFinder.SetNbPntsMin(3);
+ // Sets the maximal number of inner points for edges or faces.
+ // It is usefull for the cases when this number is very big (e.g =2000) to improve
+ // the performance. If this value =0, all inner points will be taken into account.
+ // Default value=0
+ aFinder.SetNbPntsMax(100);
+
+ aFinder.Perform();
+
+ // Interprete results
+ Standard_Integer iErr = aFinder.ErrorStatus();
+ // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
+ if (iErr) {
+ MESSAGE(" iErr : " << iErr);
+ TCollection_AsciiString aMsg (" iErr : ");
+ aMsg += TCollection_AsciiString(iErr);
+ SetErrorCode(aMsg);
+ return aSeqOfIDs;
+ }
+ Standard_Integer iWrn = aFinder.WarningStatus();
+ // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
+ if (iWrn) {
+ MESSAGE(" *** iWrn : " << iWrn);
+ }
+
+ const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
+
+ if (listSS.Extent() < 1) {
+ //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
+ SetErrorCode(NOT_FOUND_ANY); // NPAL18017
+ return aSeqOfIDs;
+ }
+
+ // Fill sequence of object IDs
+ aSeqOfIDs = new TColStd_HSequenceOfInteger;
+
+ TopTools_IndexedMapOfShape anIndices;
+ TopExp::MapShapes(theShape, anIndices);
+
+ TopTools_ListIteratorOfListOfShape itSub (listSS);
+ for (int index = 1; itSub.More(); itSub.Next(), ++index) {
+ int id = anIndices.FindIndex(itSub.Value());
+ aSeqOfIDs->Append(id);
+ }
+
+ return aSeqOfIDs;
+}
+
+//=======================================================================
+//function : getObjectsShapesOn
+/*!
+ * \brief Find shape objects and their entries by their ids
+ * \param theShapeIDs - incoming shape ids
+ * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
+ * \retval Handle(TColStd_HSequenceOfTransient) - found shape objects
+ */
+//=======================================================================
+Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::
+ getObjectsShapesOn(const Handle(GEOM_Object)& theShape,
+ const Handle(TColStd_HSequenceOfInteger)& theShapeIDs,
+ TCollection_AsciiString & theShapeEntries)
+{
+ Handle(TColStd_HSequenceOfTransient) aSeq;
+
+ if ( !theShapeIDs.IsNull() && theShapeIDs->Length() > 0 )
+ {
+ aSeq = new TColStd_HSequenceOfTransient;
+ Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
+ TCollection_AsciiString anEntry;
+ for ( int i = 1; i <= theShapeIDs->Length(); ++i )
+ {
+ anArray->SetValue(1, theShapeIDs->Value( i ));
+ Handle(GEOM_Object) anObj = GetEngine()->AddSubShape(theShape, anArray);
+ aSeq->Append( anObj );
+
+ TDF_Tool::Entry(anObj->GetEntry(), anEntry);
+ if ( i != 1 ) theShapeEntries += ",";
+ theShapeEntries += anEntry;
+ }
+ }
+ return aSeq;
+}
+
+//=======================================================================
+//function : getShapesOnSurface
+/*!
+ * \brief Find subshapes complying with given status about surface
+ * \param theSurface - the surface to check state of subshapes against
+ * \param theShape - the shape to explore
+ * \param theShapeType - type of subshape of theShape
+ * \param theState - required state
+ * \param theShapeEntries - outgoing entries like "entry1, entry2, ..."
+ * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
+ */
+//=======================================================================
+Handle(TColStd_HSequenceOfTransient)
+ GEOMImpl_IShapesOperations::getShapesOnSurface(const Handle(Geom_Surface)& theSurface,
+ const Handle(GEOM_Object)& theShape,
+ TopAbs_ShapeEnum theShapeType,
+ GEOMAlgo_State theState,
+ TCollection_AsciiString & theShapeEntries)
+{
+ // Find subshapes ids
+ Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
+ getShapesOnSurfaceIDs (theSurface, theShape->GetValue(), theShapeType, theState);
+ if ( aSeqOfIDs.IsNull() || aSeqOfIDs->Length() == 0 )
+ return NULL;
+
+ return getObjectsShapesOn( theShape, aSeqOfIDs, theShapeEntries );
+}
+
+//=============================================================================
+/*!
+ * GetShapesOnPlane
+ */
+//=============================================================================
+Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlane
+ (const Handle(GEOM_Object)& theShape,
+ const Standard_Integer theShapeType,
+ const Handle(GEOM_Object)& theAx1,
+ const GEOMAlgo_State theState)
+{
+ SetErrorCode(KO);
+
+ if (theShape.IsNull() || theAx1.IsNull()) return NULL;
+
+ TopoDS_Shape aShape = theShape->GetValue();
+ TopoDS_Shape anAx1 = theAx1->GetValue();
+
+ if (aShape.IsNull() || anAx1.IsNull()) return NULL;
+
+ TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
+ if ( !checkTypeShapesOn( theShapeType ))
+ return NULL;
+
+ // Create plane
+ Handle(Geom_Surface) aPlane = makePlane( anAx1 );
+ if ( aPlane.IsNull() )
+ return NULL;
+
+ // Find objects
+ TCollection_AsciiString anAsciiList;
+ Handle(TColStd_HSequenceOfTransient) aSeq;
+ aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
+ if ( aSeq.IsNull() || aSeq->Length() == 0 )
+ return NULL;
+
+ // Make a Python command
+
+ Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
+ Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
+
+ GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
+ << "] = geompy.GetShapesOnPlane(" << theShape << ", "
+ << aShapeType << ", " << theAx1 << ", " << theState << ")";
+
+ SetErrorCode(OK);
+ return aSeq;
+}
+
+//=============================================================================
+/*!
+ * GetShapesOnPlaneWithLocation
+ */
+//=============================================================================
+Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocation
+ (const Handle(GEOM_Object)& theShape,
+ const Standard_Integer theShapeType,
+ const Handle(GEOM_Object)& theAx1,
+ const Handle(GEOM_Object)& thePnt,
+ const GEOMAlgo_State theState)
+{
+ SetErrorCode(KO);
+
+ if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
+
+ TopoDS_Shape aShape = theShape->GetValue();
+ TopoDS_Shape anAx1 = theAx1->GetValue();
+ TopoDS_Shape anPnt = thePnt->GetValue();
+
+ if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
+
+ TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
+ if ( !checkTypeShapesOn( theShapeType ))
+ return NULL;
+
+ // Create plane
+ if ( anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX ) return NULL;
+ TopoDS_Vertex V1, V2, V3;
+ TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
+ TopExp::Vertices(anEdge, V1, V2, Standard_True);
+
+ if (V1.IsNull() || V2.IsNull()) {
+ SetErrorCode("Bad edge given for the plane normal vector");
+ return NULL;
+ }
+ V3 = TopoDS::Vertex(anPnt);
+
+ if(V3.IsNull()) {
+ SetErrorCode("Bad vertex given for the plane location");
+ return NULL;
+ }
+ gp_Pnt aLoc = BRep_Tool::Pnt(V3);
+ gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
+
+ if (aVec.Magnitude() < Precision::Confusion()) {
+ SetErrorCode("Vector with null magnitude given");
+ return NULL;
+ }
+ Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
+
+ if ( aPlane.IsNull() )
+ return NULL;
+
+ // Find objects
+ TCollection_AsciiString anAsciiList;
+ Handle(TColStd_HSequenceOfTransient) aSeq;
+ aSeq = getShapesOnSurface( aPlane, theShape, aShapeType, theState, anAsciiList );
+ if ( aSeq.IsNull() || aSeq->Length() == 0 )
+ return NULL;
+
+ // Make a Python command
+
+ Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
+ Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
+
+ GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
+ << "] = geompy.GetShapesOnPlaneWithLocation(" << theShape << ", "
+ << aShapeType << ", " << theAx1 << ", "<< thePnt <<", " << theState << ")";
+
+ SetErrorCode(OK);
+ return aSeq;
+}
+
+//=============================================================================
+/*!
+ * GetShapesOnCylinder
+ */
+//=============================================================================
+Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnCylinder
+ (const Handle(GEOM_Object)& theShape,
+ const Standard_Integer theShapeType,
+ const Handle(GEOM_Object)& theAxis,
+ const Standard_Real theRadius,
+ const GEOMAlgo_State theState)
+{
+ SetErrorCode(KO);
+
+ if (theShape.IsNull() || theAxis.IsNull()) return NULL;
+
+ TopoDS_Shape aShape = theShape->GetValue();
+ TopoDS_Shape anAxis = theAxis->GetValue();
+
+ if (aShape.IsNull() || anAxis.IsNull()) return NULL;
+
+ TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
+ if ( !checkTypeShapesOn( aShapeType ))
+ return NULL;
+
+ // Create a cylinder surface
+ Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
+ if ( aCylinder.IsNull() )
+ return NULL;
+
+ // Find objects
+ TCollection_AsciiString anAsciiList;
+ Handle(TColStd_HSequenceOfTransient) aSeq;
+ aSeq = getShapesOnSurface( aCylinder, theShape, aShapeType, theState, anAsciiList );
+ if ( aSeq.IsNull() || aSeq->Length() == 0 )
+ return NULL;
+
+ // Make a Python command
+
+ Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
+ Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
+
+ GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
+ << "] = geompy.GetShapesOnCylinder(" << theShape << ", " << aShapeType
+ << ", " << theAxis << ", " << theRadius << ", " << theState << ")";
+
+ SetErrorCode(OK);
+ return aSeq;
+}
+
+//=============================================================================
+/*!
+ * GetShapesOnSphere
+ */
+//=============================================================================
+Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetShapesOnSphere
+ (const Handle(GEOM_Object)& theShape,
+ const Standard_Integer theShapeType,
+ const Handle(GEOM_Object)& theCenter,
+ const Standard_Real theRadius,
+ const GEOMAlgo_State theState)
+{
+ SetErrorCode(KO);
+
+ if (theShape.IsNull() || theCenter.IsNull()) return NULL;
+
+ TopoDS_Shape aShape = theShape->GetValue();
+ TopoDS_Shape aCenter = theCenter->GetValue();
+
+ if (aShape.IsNull() || aCenter.IsNull()) return NULL;
+
+ TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
+ if ( !checkTypeShapesOn( aShapeType ))
+ return NULL;
+
+ // Center of the sphere
+ if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
+ gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
+
+ gp_Ax3 anAx3 (aLoc, gp::DZ());
+ Handle(Geom_SphericalSurface) aSphere =
+ new Geom_SphericalSurface(anAx3, theRadius);
+
+ // Find objects
+ TCollection_AsciiString anAsciiList;
+ Handle(TColStd_HSequenceOfTransient) aSeq;
+ aSeq = getShapesOnSurface( aSphere, theShape, aShapeType, theState, anAsciiList );
+ if ( aSeq.IsNull() || aSeq->Length() == 0 )
+ return NULL;
+
+ // Make a Python command
+
+ Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
+ Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
+
+ GEOM::TPythonDump(aFunction) << "[" << anAsciiList.ToCString()
+ << "] = geompy.GetShapesOnSphere(" << theShape << ", " << aShapeType
+ << ", " << theCenter << ", " << theRadius << ", " << theState << ")";
+
+ SetErrorCode(OK);
+ return aSeq;
+}
+
+//=============================================================================
+/*!
+ * GetShapesOnPlaneIDs
+ */
+//=============================================================================
+Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneIDs
+ (const Handle(GEOM_Object)& theShape,
+ const Standard_Integer theShapeType,
+ const Handle(GEOM_Object)& theAx1,
+ const GEOMAlgo_State theState)
+{
+ SetErrorCode(KO);
+
+ if (theShape.IsNull() || theAx1.IsNull()) return NULL;
+
+ TopoDS_Shape aShape = theShape->GetValue();
+ TopoDS_Shape anAx1 = theAx1->GetValue();
+
+ if (aShape.IsNull() || anAx1.IsNull()) return NULL;
+
+ TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
+ if ( !checkTypeShapesOn( aShapeType ))
+ return NULL;
+
+ // Create plane
+ Handle(Geom_Surface) aPlane = makePlane( anAx1 );
+ if ( aPlane.IsNull() )
+ return NULL;
+
+ // Find object IDs
+ Handle(TColStd_HSequenceOfInteger) aSeq;
+ aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
+
+ // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
+ Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
+
+ // Make a Python command
+ GEOM::TPythonDump(aFunction, /*append=*/true)
+ << "listShapesOnPlane = geompy.GetShapesOnPlaneIDs"
+ << "(" << theShape << "," << aShapeType << "," << theAx1 << "," << theState << ")";
+
+ SetErrorCode(OK);
+ return aSeq;
+}
+
+//=============================================================================
+/*!
+ * GetShapesOnPlaneWithLocationIDs
+ */
+//=============================================================================
+Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnPlaneWithLocationIDs
+ (const Handle(GEOM_Object)& theShape,
+ const Standard_Integer theShapeType,
+ const Handle(GEOM_Object)& theAx1,
+ const Handle(GEOM_Object)& thePnt,
+ const GEOMAlgo_State theState)
+{
+ SetErrorCode(KO);
+
+ if (theShape.IsNull() || theAx1.IsNull() || thePnt.IsNull()) return NULL;
+
+ TopoDS_Shape aShape = theShape->GetValue();
+ TopoDS_Shape anAx1 = theAx1->GetValue();
+ TopoDS_Shape anPnt = thePnt->GetValue();
+
+ if (aShape.IsNull() || anAx1.IsNull() || anPnt.IsNull()) return NULL;
+
+ TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
+ if ( !checkTypeShapesOn( aShapeType ))
+ return NULL;
+
+ // Create plane
+ if (anAx1.ShapeType() != TopAbs_EDGE || anPnt.ShapeType() != TopAbs_VERTEX) return NULL;
+ TopoDS_Edge anEdge = TopoDS::Edge(anAx1);
+ TopoDS_Vertex V1, V2, V3;
+ TopExp::Vertices(anEdge, V1, V2, Standard_True);
+ if (V1.IsNull() || V2.IsNull()) {
+ SetErrorCode("Bad edge given for the plane normal vector");
+ return NULL;
+ }
+ V3 = TopoDS::Vertex(anPnt);
+ if(V3.IsNull()) {
+ SetErrorCode("Bad vertex given for the plane location");
+ return NULL;
+ }
+ gp_Pnt aLoc = BRep_Tool::Pnt(V3);
+ gp_Vec aVec(BRep_Tool::Pnt(V1),BRep_Tool::Pnt(V2));
+ if (aVec.Magnitude() < Precision::Confusion()) {
+ SetErrorCode("Vector with null magnitude given");
+ return NULL;
+ }
+
+ Handle(Geom_Surface) aPlane = new Geom_Plane(aLoc, aVec);
+ if ( aPlane.IsNull() )
+ return NULL;
+
+ // Find object IDs
+ Handle(TColStd_HSequenceOfInteger) aSeq;
+ aSeq = getShapesOnSurfaceIDs( aPlane, aShape, aShapeType, theState );
+
+ // The GetShapesOnPlaneIDs() doesn't change object so no new function is required.
+ Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAx1)->GetLastFunction();
+
+ // Make a Python command
+ GEOM::TPythonDump(aFunction, /*append=*/true)
+ << "listShapesOnPlane = geompy.GetShapesOnPlaneWithLocationIDs"
+ << "(" << theShape << ", " << aShapeType << ", " << theAx1 << ", "<< thePnt << ", " << theState << ")";
+
+ SetErrorCode(OK);
+ return aSeq;
+}
+
+//=============================================================================
+/*!
+ * GetShapesOnCylinderIDs
+ */
+//=============================================================================
+Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnCylinderIDs
+ (const Handle(GEOM_Object)& theShape,
+ const Standard_Integer theShapeType,
+ const Handle(GEOM_Object)& theAxis,
+ const Standard_Real theRadius,
+ const GEOMAlgo_State theState)
+{
+ SetErrorCode(KO);
+
+ if (theShape.IsNull() || theAxis.IsNull()) return NULL;
+
+ TopoDS_Shape aShape = theShape->GetValue();
+ TopoDS_Shape anAxis = theAxis->GetValue();
+
+ if (aShape.IsNull() || anAxis.IsNull()) return NULL;
+
+ TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
+ if ( !checkTypeShapesOn( aShapeType ))
+ return NULL;
+
+ // Create a cylinder surface
+ Handle(Geom_Surface) aCylinder = makeCylinder( anAxis, theRadius );
+ if ( aCylinder.IsNull() )
+ return NULL;
+
+ // Find object IDs
+ Handle(TColStd_HSequenceOfInteger) aSeq;
+ aSeq = getShapesOnSurfaceIDs( aCylinder, aShape, aShapeType, theState );
+
+ // The GetShapesOnCylinder() doesn't change object so no new function is required.
+ Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theAxis)->GetLastFunction();
+
+ // Make a Python command
+ GEOM::TPythonDump(aFunction, /*append=*/true)
+ << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
+ << "(" << theShape << ", " << aShapeType << ", " << theAxis << ", "
+ << theRadius << ", " << theState << ")";
+
+ SetErrorCode(OK);
+ return aSeq;
+}
+
+//=============================================================================
+/*!
+ * GetShapesOnSphereIDs
+ */
+//=============================================================================
+Handle(TColStd_HSequenceOfInteger) GEOMImpl_IShapesOperations::GetShapesOnSphereIDs
+ (const Handle(GEOM_Object)& theShape,
+ const Standard_Integer theShapeType,
+ const Handle(GEOM_Object)& theCenter,
+ const Standard_Real theRadius,
+ const GEOMAlgo_State theState)
+{
+ SetErrorCode(KO);
+
+ if (theShape.IsNull() || theCenter.IsNull()) return NULL;
+
+ TopoDS_Shape aShape = theShape->GetValue();
+ TopoDS_Shape aCenter = theCenter->GetValue();
+
+ if (aShape.IsNull() || aCenter.IsNull()) return NULL;
+
+ TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
+ if ( !checkTypeShapesOn( aShapeType ))
+ return NULL;
+
+ // Center of the sphere
+ if (aCenter.ShapeType() != TopAbs_VERTEX) return NULL;
+ gp_Pnt aLoc = BRep_Tool::Pnt(TopoDS::Vertex(aCenter));
+
+ gp_Ax3 anAx3 (aLoc, gp::DZ());
+ Handle(Geom_SphericalSurface) aSphere =
+ new Geom_SphericalSurface(anAx3, theRadius);
+
+ // Find object IDs
+ Handle(TColStd_HSequenceOfInteger) aSeq;
+ aSeq = getShapesOnSurfaceIDs( aSphere, aShape, aShapeType, theState );
+
+ // The GetShapesOnSphere() doesn't change object so no new function is required.
+ Handle(GEOM_Function) aFunction = GEOM::GetCreatedLast(theShape,theCenter)->GetLastFunction();
+
+ // Make a Python command
+ GEOM::TPythonDump(aFunction, /*append=*/true)
+ << "listShapesOnCylinder = geompy.GetShapesOnCylinderIDs"
+ << "(" << theShape << ", " << aShapeType << ", " << theCenter << ", "
+ << theRadius << ", " << theState << ")";
+
+ SetErrorCode(OK);
+ return aSeq;
+}
+
+//=======================================================================
+//function : getShapesOnQuadrangleIDs
+ /*!
+ * \brief Find IDs of subshapes complying with given status about quadrangle
+ * \param theShape - the shape to explore
+ * \param theShapeType - type of subshape of theShape
+ * \param theTopLeftPoint - top left quadrangle corner
+ * \param theTopRigthPoint - top right quadrangle corner
+ * \param theBottomLeftPoint - bottom left quadrangle corner
+ * \param theBottomRigthPoint - bottom right quadrangle corner
+ * \param theState - required state
+ * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
+ */
+//=======================================================================
+Handle(TColStd_HSequenceOfInteger)
+ GEOMImpl_IShapesOperations::getShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
+ const Standard_Integer theShapeType,
+ const Handle(GEOM_Object)& theTopLeftPoint,
+ const Handle(GEOM_Object)& theTopRigthPoint,
+ const Handle(GEOM_Object)& theBottomLeftPoint,
+ const Handle(GEOM_Object)& theBottomRigthPoint,
+ const GEOMAlgo_State theState)
+{
+ SetErrorCode(KO);
+
+ if ( theShape.IsNull() ||
+ theTopLeftPoint.IsNull() ||
+ theTopRigthPoint.IsNull() ||
+ theBottomLeftPoint.IsNull() ||
+ theBottomRigthPoint.IsNull() )
+ return NULL;
+
+ TopoDS_Shape aShape = theShape->GetValue();
+ TopoDS_Shape aTL = theTopLeftPoint->GetValue();
+ TopoDS_Shape aTR = theTopRigthPoint->GetValue();
+ TopoDS_Shape aBL = theBottomLeftPoint->GetValue();
+ TopoDS_Shape aBR = theBottomRigthPoint->GetValue();
+
+ if (aShape.IsNull() ||
+ aTL.IsNull() ||
+ aTR.IsNull() ||
+ aBL.IsNull() ||
+ aBR.IsNull() ||
+ aTL.ShapeType() != TopAbs_VERTEX ||
+ aTR.ShapeType() != TopAbs_VERTEX ||
+ aBL.ShapeType() != TopAbs_VERTEX ||
+ aBR.ShapeType() != TopAbs_VERTEX )
+ return NULL;
+
+ TopAbs_ShapeEnum aShapeType = TopAbs_ShapeEnum(theShapeType);
+ if ( !checkTypeShapesOn( aShapeType ))
+ return NULL;
+
+ Handle(TColStd_HSequenceOfInteger) aSeqOfIDs;
+
+ // Check presence of triangulation, build if need
+ if (!CheckTriangulation(aShape)) {
+ SetErrorCode("Cannot build triangulation on the shape");
+ return aSeqOfIDs;
+ }
+
+ // Call algo
+ gp_Pnt aPntTL = BRep_Tool::Pnt(TopoDS::Vertex(aTL));
+ gp_Pnt aPntTR = BRep_Tool::Pnt(TopoDS::Vertex(aTR));
+ gp_Pnt aPntBL = BRep_Tool::Pnt(TopoDS::Vertex(aBL));
+ gp_Pnt aPntBR = BRep_Tool::Pnt(TopoDS::Vertex(aBR));
+
+ GEOMAlgo_FinderShapeOnQuad aFinder( aPntTL, aPntTR, aPntBL, aPntBR );
+ Standard_Real aTol = 0.0001; // default value
+
+ aFinder.SetShape(aShape);
+ aFinder.SetTolerance(aTol);
+ //aFinder.SetSurface(theSurface);
+ aFinder.SetShapeType(aShapeType);
+ aFinder.SetState(theState);
+
+ // Sets the minimal number of inner points for the faces that do not have own
+ // inner points at all (for e.g. rectangular planar faces have just 2 triangles).
+ // Default value=3
+ aFinder.SetNbPntsMin(3);
+ // Sets the maximal number of inner points for edges or faces.
+ // It is usefull for the cases when this number is very big (e.g =2000) to improve
+ // the performance. If this value =0, all inner points will be taken into account.
+ // Default value=0
+ aFinder.SetNbPntsMax(100);
+
+ aFinder.Perform();
+
+ // Interprete results
+ Standard_Integer iErr = aFinder.ErrorStatus();
+ // the detailed description of error codes is in GEOMAlgo_FinderShapeOn1.cxx
+ if (iErr) {
+ MESSAGE(" iErr : " << iErr);
+ TCollection_AsciiString aMsg (" iErr : ");
+ aMsg += TCollection_AsciiString(iErr);
+ SetErrorCode(aMsg);
+ return aSeqOfIDs;
+ }
+ Standard_Integer iWrn = aFinder.WarningStatus();
+ // the detailed description of warning codes is in GEOMAlgo_FinderShapeOn1.cxx
+ if (iWrn) {
+ MESSAGE(" *** iWrn : " << iWrn);
+ }
+
+ const TopTools_ListOfShape& listSS = aFinder.Shapes(); // the result
+
+ if (listSS.Extent() < 1) {
+ //SetErrorCode("Not a single sub-shape of the requested type found on the given surface");
+ SetErrorCode(NOT_FOUND_ANY); // NPAL18017
+ return aSeqOfIDs;
+ }
+
+ // Fill sequence of object IDs
+ aSeqOfIDs = new TColStd_HSequenceOfInteger;
+
+ TopTools_IndexedMapOfShape anIndices;
+ TopExp::MapShapes(aShape, anIndices);
+
+ TopTools_ListIteratorOfListOfShape itSub (listSS);
+ for (int index = 1; itSub.More(); itSub.Next(), ++index) {
+ int id = anIndices.FindIndex(itSub.Value());
+ aSeqOfIDs->Append(id);
+ }
+ return aSeqOfIDs;
+}
+
+//=======================================================================
+//function : GetShapesOnQuadrangle
+ /*!
+ * \brief Find subshapes complying with given status about quadrangle
+ * \param theShape - the shape to explore
+ * \param theShapeType - type of subshape of theShape
+ * \param theTopLeftPoint - top left quadrangle corner
+ * \param theTopRigthPoint - top right quadrangle corner
+ * \param theBottomLeftPoint - bottom left quadrangle corner
+ * \param theBottomRigthPoint - bottom right quadrangle corner
+ * \param theState - required state
+ * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
+ */
+//=======================================================================
+Handle(TColStd_HSequenceOfTransient)
+ GEOMImpl_IShapesOperations::GetShapesOnQuadrangle (const Handle(GEOM_Object)& theShape,
+ const Standard_Integer theShapeType,
+ const Handle(GEOM_Object)& theTopLeftPoint,
+ const Handle(GEOM_Object)& theTopRigthPoint,
+ const Handle(GEOM_Object)& theBottomLeftPoint,
+ const Handle(GEOM_Object)& theBottomRigthPoint,
+ const GEOMAlgo_State theState)
+{
+ // Find indices
+ Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
+ getShapesOnQuadrangleIDs( theShape,
+ theShapeType,
+ theTopLeftPoint,
+ theTopRigthPoint,
+ theBottomLeftPoint,
+ theBottomRigthPoint,
+ theState);
+ if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
+ return NULL;
+
+ // Find objects by indices
+ TCollection_AsciiString anAsciiList;
+ Handle(TColStd_HSequenceOfTransient) aSeq;
+ aSeq = getObjectsShapesOn( theShape, aSeqOfIDs, anAsciiList );
+ if ( aSeq.IsNull() || aSeq->IsEmpty() )
+ return NULL;
+
+ // Make a Python command
+
+ Handle(GEOM_Object) anObj = Handle(GEOM_Object)::DownCast( aSeq->Value( 1 ));
+ Handle(GEOM_Function) aFunction = anObj->GetLastFunction();
+
+ GEOM::TPythonDump(aFunction)
+ << "[" << anAsciiList.ToCString() << "] = geompy.GetShapesOnQuadrangle("
+ << theShape << ", "
+ << TopAbs_ShapeEnum(theShapeType) << ", "
+ << theTopLeftPoint << ", "
+ << theTopRigthPoint << ", "
+ << theBottomLeftPoint << ", "
+ << theBottomRigthPoint << ", "
+ << theState << ")";
+
+ SetErrorCode(OK);
+ return aSeq;
+}
+
+//=======================================================================
+//function : GetShapesOnQuadrangleIDs
+ /*!
+ * \brief Find IDs of subshapes complying with given status about quadrangle
+ * \param theShape - the shape to explore
+ * \param theShapeType - type of subshape of theShape
+ * \param theTopLeftPoint - top left quadrangle corner
+ * \param theTopRigthPoint - top right quadrangle corner
+ * \param theBottomLeftPoint - bottom left quadrangle corner
+ * \param theBottomRigthPoint - bottom right quadrangle corner
+ * \param theState - required state
+ * \retval Handle(TColStd_HSequenceOfInteger) - IDs of found subshapes
+ */
+//=======================================================================
+Handle(TColStd_HSequenceOfInteger)
+ GEOMImpl_IShapesOperations::GetShapesOnQuadrangleIDs (const Handle(GEOM_Object)& theShape,
+ const Standard_Integer theShapeType,
+ const Handle(GEOM_Object)& theTopLeftPoint,
+ const Handle(GEOM_Object)& theTopRigthPoint,
+ const Handle(GEOM_Object)& theBottomLeftPoint,
+ const Handle(GEOM_Object)& theBottomRigthPoint,
+ const GEOMAlgo_State theState)
+{
+ // Find indices
+ Handle(TColStd_HSequenceOfInteger) aSeqOfIDs =
+ getShapesOnQuadrangleIDs( theShape,
+ theShapeType,
+ theTopLeftPoint,
+ theTopRigthPoint,
+ theBottomLeftPoint,
+ theBottomRigthPoint,
+ theState);
+ if ( aSeqOfIDs.IsNull() || aSeqOfIDs->IsEmpty() )
+ return NULL;
+
+ // Make a Python command
+
+ // The GetShapesOnCylinder() doesn't change object so no new function is required.
+ Handle(GEOM_Object) lastObj = GEOM::GetCreatedLast(theShape,theTopLeftPoint);
+ lastObj = GEOM::GetCreatedLast(lastObj,theTopRigthPoint);
+ lastObj = GEOM::GetCreatedLast(lastObj,theBottomRigthPoint);
+ lastObj = GEOM::GetCreatedLast(lastObj,theBottomLeftPoint);
+ Handle(GEOM_Function) aFunction = lastObj->GetLastFunction();
+
+ GEOM::TPythonDump(aFunction, /*append=*/true)
+ << "listShapesOnQuadrangle = geompy.GetShapesOnQuadrangleIDs("
+ << theShape << ", "
+ << TopAbs_ShapeEnum(theShapeType) << ", "
+ << theTopLeftPoint << ", "
+ << theTopRigthPoint << ", "
+ << theBottomLeftPoint << ", "
+ << theBottomRigthPoint << ", "
+ << theState << ")";
+
+ SetErrorCode(OK);
+ return aSeqOfIDs;
+}
+
+//=============================================================================
+/*!
+ * GetInPlaceOfShape
+ */
+//=============================================================================
+static bool GetInPlaceOfShape (const Handle(GEOM_Function)& theWhereFunction,
+ const TopTools_IndexedMapOfShape& theWhereIndices,
+ const TopoDS_Shape& theWhat,
+ TColStd_ListOfInteger& theModifiedList)
+{
+ if (theWhereFunction.IsNull() || theWhat.IsNull()) return false;
+
+ if (theWhereIndices.Contains(theWhat)) {
+ // entity was not changed by the operation
+ Standard_Integer aWhatIndex = theWhereIndices.FindIndex(theWhat);
+ theModifiedList.Append(aWhatIndex);
+ return true;
+ }
+
+ // try to find in history
+ TDF_Label aHistoryLabel = theWhereFunction->GetHistoryEntry(Standard_False);
+
+ // search in history for all argument shapes
+ Standard_Boolean isFound = Standard_False;
+ Standard_Boolean isGood = Standard_False;
+
+ TDF_LabelSequence aLabelSeq;
+ theWhereFunction->GetDependency(aLabelSeq);
+ Standard_Integer nbArg = aLabelSeq.Length();
+
+ for (Standard_Integer iarg = 1; iarg <= nbArg && !isFound; iarg++) {
+
+ TDF_Label anArgumentRefLabel = aLabelSeq.Value(iarg);
+
+ Handle(GEOM_Object) anArgumentObject = GEOM_Object::GetReferencedObject(anArgumentRefLabel);
+ TopoDS_Shape anArgumentShape = anArgumentObject->GetValue();
+
+ TopTools_IndexedMapOfShape anArgumentIndices;
+ TopExp::MapShapes(anArgumentShape, anArgumentIndices);
+
+ if (anArgumentIndices.Contains(theWhat)) {
+ isFound = Standard_True;
+ Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(theWhat);
+
+ // Find corresponding label in history
+ TDF_Label anArgumentHistoryLabel =
+ theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False);
+ if (anArgumentHistoryLabel.IsNull()) {
+ // Lost History of operation argument. Possibly, all its entities was removed.
+ isGood = Standard_True;
+ }
+ else {
+ TDF_Label aWhatHistoryLabel = anArgumentHistoryLabel.FindChild(aWhatIndex, Standard_False);
+
+ if (aWhatHistoryLabel.IsNull()) {
+ // Removed entity ? Compound ? Compsolid ? Shell ? Wire
+ isGood = Standard_False;
+ } else {
+ Handle(TDataStd_IntegerArray) anIntegerArray;
+ if (!aWhatHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) {
+ //Error: Empty modifications history for the sought shape.
+ isGood = Standard_False;
+ }
+ else {
+ isGood = Standard_True;
+ Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length();
+ for (imod = 1; imod <= aModifLen; imod++) {
+ theModifiedList.Append(anIntegerArray->Array()->Value(imod));
+ }
+ }
+ }
+ }
+ }
+ }
+
+ isFound = isGood;
+
+ if (!isFound) {
+ // try compound/compsolid/shell/wire element by element
+ bool isFoundAny = false;
+ TopTools_MapOfShape mapShape;
+
+ if (theWhat.ShapeType() == TopAbs_COMPOUND ||
+ theWhat.ShapeType() == TopAbs_COMPSOLID) {
+ // recursive processing of compound/compsolid
+ TopoDS_Iterator anIt (theWhat, Standard_True, Standard_True);
+ for (; anIt.More(); anIt.Next()) {
+ if (mapShape.Add(anIt.Value())) {
+ TopoDS_Shape curWhat = anIt.Value();
+ isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
+ if (isFoundAny) isFound = Standard_True;
+ }
+ }
+ }
+ else if (theWhat.ShapeType() == TopAbs_SHELL) {
+ // try to replace a shell by its faces images
+ TopExp_Explorer anExp (theWhat, TopAbs_FACE);
+ for (; anExp.More(); anExp.Next()) {
+ if (mapShape.Add(anExp.Current())) {
+ TopoDS_Shape curWhat = anExp.Current();
+ isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
+ if (isFoundAny) isFound = Standard_True;
+ }
+ }
+ }
+ else if (theWhat.ShapeType() == TopAbs_WIRE) {
+ // try to replace a wire by its edges images
+ TopExp_Explorer anExp (theWhat, TopAbs_EDGE);
+ for (; anExp.More(); anExp.Next()) {
+ if (mapShape.Add(anExp.Current())) {
+ TopoDS_Shape curWhat = anExp.Current();
+ isFoundAny = GetInPlaceOfShape(theWhereFunction, theWhereIndices, curWhat, theModifiedList);
+ if (isFoundAny) isFound = Standard_True;
+ }
+ }
+ }
+ else {
+ // Removed entity
+ }
+ }
+
+ return isFound;
+}
+
+//=============================================================================
+/*!
+ * GetShapeProperties
+ */
+//=============================================================================
+void GEOMImpl_IShapesOperations::GetShapeProperties( const TopoDS_Shape aShape, Standard_Real tab[],
+ gp_Pnt & aVertex )
+{
+ GProp_GProps theProps;
+ gp_Pnt aCenterMass;
+ //TopoDS_Shape aPntShape;
+ Standard_Real aShapeSize;
+
+ if (aShape.ShapeType() == TopAbs_EDGE) BRepGProp::LinearProperties(aShape, theProps);
+ else if (aShape.ShapeType() == TopAbs_FACE) BRepGProp::SurfaceProperties(aShape, theProps);
+ else BRepGProp::VolumeProperties(aShape, theProps);
+
+ aCenterMass = theProps.CentreOfMass();
+ aShapeSize = theProps.Mass();
+
+// aPntShape = BRepBuilderAPI_MakeVertex(aCenterMass).Shape();
+// aVertex = BRep_Tool::Pnt( TopoDS::Vertex( aPntShape ) );
+ aVertex = aCenterMass;
+ tab[0] = aVertex.X();
+ tab[1] = aVertex.Y();
+ tab[2] = aVertex.Z();
+ tab[3] = aShapeSize;
+ return;
+}
+
+namespace {
+
+ //================================================================================
+ /*!
+ * \brief Return normal to face at extrema point
+ */
+ //================================================================================
+
+ gp_Vec GetNormal(const TopoDS_Face& face, const BRepExtrema_DistShapeShape& extrema)
+ {
+ gp_Vec defaultNorm(1,0,0); // to have same normals on different faces
+ try {
+ // get UV at extrema point
+ Standard_Real u,v, f,l;
+ switch ( extrema.SupportTypeShape2(1) ) {
+ case BRepExtrema_IsInFace: {
+ extrema.ParOnFaceS2(1, u, v );
+ break;
+ }
+ case BRepExtrema_IsOnEdge: {
+ TopoDS_Edge edge = TopoDS::Edge( extrema.SupportOnShape2(1));
+ Handle(Geom2d_Curve) pcurve = BRep_Tool::CurveOnSurface( edge, face, f,l );
+ extrema.ParOnEdgeS2( 1, u );
+ gp_Pnt2d uv = pcurve->Value( u );
+ u = uv.Coord(1);
+ v = uv.Coord(2);
+ break;
+ }
+ case BRepExtrema_IsVertex: return defaultNorm;
+ }
+ // get derivatives
+ BRepAdaptor_Surface surface( face, false );
+ gp_Vec du, dv; gp_Pnt p;
+ surface.D1( u, v, p, du, dv );
+
+ return du ^ dv;
+
+ } catch (Standard_Failure ) {
+ }
+ return defaultNorm;
+ }
+}
+
+//=============================================================================
+/*!
+ case GetInPlace:
+ default:
+ */
+//=============================================================================
+Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace (Handle(GEOM_Object) theShapeWhere,
+ Handle(GEOM_Object) theShapeWhat)
+{
+ SetErrorCode(KO);
+
+ if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
+
+ TopoDS_Shape aWhere = theShapeWhere->GetValue();
+ TopoDS_Shape aWhat = theShapeWhat->GetValue();
+ TopoDS_Shape aPntShape;
+ TopoDS_Vertex aVertex;
+
+ if (aWhere.IsNull() || aWhat.IsNull()) {
+ SetErrorCode("Error: aWhere and aWhat TopoDS_Shape are Null.");
+ return NULL;
+ }
+
+ Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
+ if (aWhereFunction.IsNull()) {
+ SetErrorCode("Error: aWhereFunction is Null.");
+ return NULL;
+ }
+
+ TopTools_IndexedMapOfShape aWhereIndices;
+ TopExp::MapShapes(aWhere, aWhereIndices);
+
+ TColStd_ListOfInteger aModifiedList;
+ Standard_Integer aWhereIndex;
+ Handle(TColStd_HArray1OfInteger) aModifiedArray;
+ Handle(GEOM_Object) aResult;
+
+ bool isFound = false;
+ Standard_Integer iType = TopAbs_SOLID;
+ Standard_Integer compType = TopAbs_SOLID;
+ Standard_Real aWhat_Mass = 0., aWhere_Mass = 0.;
+ Standard_Real tab_aWhat[4], tab_aWhere[4];
+ Standard_Real dl_l = 1e-3;
+ Standard_Real min_l, Tol_1D, Tol_2D, Tol_3D, Tol_Mass;
+ Standard_Real aXmin, aYmin, aZmin, aXmax, aYmax, aZmax;
+ Bnd_Box BoundingBox;
+ gp_Pnt aPnt, aPnt_aWhat, tab_Pnt[2];
+ GProp_GProps aProps;
+
+ // Find the iType of the aWhat shape
+ if ( aWhat.ShapeType() == TopAbs_EDGE || aWhat.ShapeType() == TopAbs_WIRE ) iType = TopAbs_EDGE;
+ else if ( aWhat.ShapeType() == TopAbs_FACE || aWhat.ShapeType() == TopAbs_SHELL ) iType = TopAbs_FACE;
+ else if ( aWhat.ShapeType() == TopAbs_SOLID || aWhat.ShapeType() == TopAbs_COMPSOLID ) iType = TopAbs_SOLID;
+ else if ( aWhat.ShapeType() == TopAbs_COMPOUND ) {
+ // Only the iType of the first shape in the compound is taken into account
+ TopoDS_Iterator It (aWhat, Standard_False, Standard_False);
+ if ( !It.More() ) {
+ SetErrorCode("Error: theShapeWhat is an empty COMPOUND.");
+ return NULL;
+ }
+ compType = It.Value().ShapeType();
+ if ( compType == TopAbs_EDGE || compType == TopAbs_WIRE ) iType = TopAbs_EDGE;
+ else if ( compType == TopAbs_FACE || compType == TopAbs_SHELL) iType = TopAbs_FACE;
+ else if ( compType == TopAbs_SOLID || compType == TopAbs_COMPSOLID) iType = TopAbs_SOLID;
+ }
+ else {
+ SetErrorCode("Error: An attempt to extract a shape of not supported type.");
+ return NULL;
+ }
+
+ TopExp_Explorer Exp_aWhat( aWhat, TopAbs_ShapeEnum( iType ) );
+ TopExp_Explorer Exp_aWhere( aWhere, TopAbs_ShapeEnum( iType ) );
+ TopExp_Explorer Exp_Edge( aWhere, TopAbs_EDGE );
+
+ // Find the shortest edge in theShapeWhere shape
+ BRepBndLib::Add(aWhere, BoundingBox);
+ BoundingBox.Get(aXmin, aYmin, aZmin, aXmax, aYmax, aZmax);
+ min_l = fabs(aXmax - aXmin);
+ if( min_l < fabs(aYmax - aYmin) ) min_l = fabs(aYmax - aYmin);
+ if( min_l < fabs(aZmax - aZmin) ) min_l = fabs(aZmax - aZmin);
+ min_l /= dl_l;
+ for ( Standard_Integer nbEdge = 0; Exp_Edge.More(); Exp_Edge.Next(), nbEdge++ ) {
+ TopExp_Explorer Exp_Vertex( Exp_Edge.Current(), TopAbs_VERTEX);
+ for ( Standard_Integer nbVertex = 0; Exp_Vertex.More(); Exp_Vertex.Next(), nbVertex++ ) {
+ aPnt = BRep_Tool::Pnt( TopoDS::Vertex( Exp_Vertex.Current() ) );
+ tab_Pnt[nbVertex] = aPnt;
+ }
+ if ( ! tab_Pnt[0].IsEqual(tab_Pnt[1], dl_l) ) {
+ BRepGProp::LinearProperties(Exp_Edge.Current(), aProps);
+ if ( aProps.Mass() < min_l ) min_l = aProps.Mass();
+ }
+ }
+
+ // Compute tolerances
+ Tol_1D = dl_l * min_l;
+ Tol_2D = dl_l * ( min_l * min_l) * ( 2. + dl_l);
+ Tol_3D = dl_l * ( min_l * min_l * min_l ) * ( 3. + (3 * dl_l) + (dl_l * dl_l) );
+
+ if (Tol_1D < Precision::Confusion()) Tol_1D = Precision::Confusion();
+ if (Tol_2D < Precision::Confusion()) Tol_2D = Precision::Confusion();
+ if (Tol_3D < Precision::Confusion()) Tol_3D = Precision::Confusion();
+
+ Tol_Mass = Tol_3D;
+ if ( iType == TopAbs_EDGE ) Tol_Mass = Tol_1D;
+ else if ( iType == TopAbs_FACE ) Tol_Mass = Tol_2D;
+
+ // Compute the ShapeWhat Mass
+ for ( ; Exp_aWhat.More(); Exp_aWhat.Next() ) {
+ if ( iType == TopAbs_EDGE ) BRepGProp::LinearProperties(Exp_aWhat.Current(), aProps);
+ else if ( iType == TopAbs_FACE ) BRepGProp::SurfaceProperties(Exp_aWhat.Current(), aProps);
+ else BRepGProp::VolumeProperties(Exp_aWhat.Current(), aProps);
+ aWhat_Mass += aProps.Mass();
+ }
+
+ // Searching for the sub-shapes inside the ShapeWhere shape
+ TopTools_MapOfShape map_aWhere;
+ for ( Exp_aWhere.ReInit(); Exp_aWhere.More(); Exp_aWhere.Next() ) {
+ if (!map_aWhere.Add(Exp_aWhere.Current()))
+ continue; // skip repeated shape to avoid mass addition
+ GetShapeProperties( Exp_aWhere.Current(), tab_aWhere, aPnt );
+ for ( Exp_aWhat.ReInit(); Exp_aWhat.More(); Exp_aWhat.Next() ) {
+ GetShapeProperties( Exp_aWhat.Current(), tab_aWhat, aPnt_aWhat );
+ if ( fabs(tab_aWhat[3] - tab_aWhere[3]) <= Tol_Mass && aPnt_aWhat.Distance(aPnt) <= Tol_1D )
+ isFound = true;
+ else {
+ if ( (tab_aWhat[3] - tab_aWhere[3]) > Tol_Mass ) {
+ aPntShape = BRepBuilderAPI_MakeVertex( aPnt ).Shape();
+ aVertex = TopoDS::Vertex( aPntShape );
+ BRepExtrema_DistShapeShape aWhereDistance ( aVertex, Exp_aWhere.Current() );
+ BRepExtrema_DistShapeShape aWhatDistance ( aVertex, Exp_aWhat.Current() );
+ if ( aWhereDistance.IsDone() && aWhatDistance.IsDone() &&
+ fabs(aWhereDistance.Value() - aWhatDistance.Value()) <= Tol_1D )
+ {
+ // 0020162: "EDF 961 GEOM : Getinplace is getting additionnal orthogonal faces"
+ // aVertex must be projected to the same point on Where and on What
+ gp_Pnt pOnWhat = aWhatDistance.PointOnShape2(1);
+ gp_Pnt pOnWhere = aWhereDistance.PointOnShape2(1);
+ isFound = ( pOnWhat.Distance(pOnWhere) <= Tol_1D );
+ if ( isFound && iType == TopAbs_FACE )
+ {
+ // check normals at pOnWhat and pOnWhere
+ const double angleTol = PI/180.;
+ gp_Vec normToWhat = GetNormal( TopoDS::Face(Exp_aWhat.Current()), aWhatDistance);
+ gp_Vec normToWhere = GetNormal( TopoDS::Face(Exp_aWhere.Current()), aWhereDistance);
+ if ( normToWhat * normToWhere < 0 )
+ normToWhat.Reverse();
+ isFound = ( normToWhat.Angle( normToWhere ) < angleTol );
+ }
+ }
+ }
+ }
+ if ( isFound ) {
+ aWhereIndex = aWhereIndices.FindIndex(Exp_aWhere.Current());
+ aModifiedList.Append(aWhereIndex);
+ aWhere_Mass += tab_aWhere[3];
+ isFound = false;
+ break;
+ }
+ }
+ if ( fabs( aWhat_Mass - aWhere_Mass ) <= Tol_Mass ) break;
+ }
+
+ if (aModifiedList.Extent() == 0) { // Not found any Results
+ SetErrorCode(NOT_FOUND_ANY);
+ return NULL;
+ }
+
+ aModifiedArray = new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
+ TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
+ for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++)
+ aModifiedArray->SetValue(imod, anIterModif.Value());
+
+ //Add a new object
+ aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
+ if (aResult.IsNull()) {
+ SetErrorCode("Error in algorithm: result found, but cannot be returned.");
+ return NULL;
+ }
+
+ if (aModifiedArray->Length() > 1) {
+ //Set a GROUP type
+ aResult->SetType(GEOM_GROUP);
+
+ //Set a sub shape type
+ TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
+ TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
+
+ TDF_Label aFreeLabel = aResult->GetFreeLabel();
+ TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
+ }
+
+ //Make a Python command
+ Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
+
+ GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlace("
+ << theShapeWhere << ", " << theShapeWhat << ")";
+
+ SetErrorCode(OK);
+ return aResult;
+}
+
+//=======================================================================
+//function : GetInPlaceByHistory
+//purpose :
+//=======================================================================
+Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory
+ (Handle(GEOM_Object) theShapeWhere,
+ Handle(GEOM_Object) theShapeWhat)
+{
+ SetErrorCode(KO);
+
+ if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return NULL;
+
+ TopoDS_Shape aWhere = theShapeWhere->GetValue();
+ TopoDS_Shape aWhat = theShapeWhat->GetValue();
+
+ if (aWhere.IsNull() || aWhat.IsNull()) return NULL;
+
+ Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction();
+ if (aWhereFunction.IsNull()) return NULL;
+
+ //Fill array of indices
+ TopTools_IndexedMapOfShape aWhereIndices;
+ TopExp::MapShapes(aWhere, aWhereIndices);
+
+ // process shape
+ TColStd_ListOfInteger aModifiedList;
+ bool isFound = GetInPlaceOfShape(aWhereFunction, aWhereIndices, aWhat, aModifiedList);
+
+ if (!isFound || aModifiedList.Extent() < 1) {
+ SetErrorCode("Error: No history found for the sought shape or its sub-shapes.");
+ return NULL;
+ }
+
+ Handle(TColStd_HArray1OfInteger) aModifiedArray =
+ new TColStd_HArray1OfInteger (1, aModifiedList.Extent());
+ TColStd_ListIteratorOfListOfInteger anIterModif (aModifiedList);
+ for (Standard_Integer imod = 1; anIterModif.More(); anIterModif.Next(), imod++) {
+ aModifiedArray->SetValue(imod, anIterModif.Value());
+ }
+
+ //Add a new object
+ Handle(GEOM_Object) aResult = GetEngine()->AddSubShape(theShapeWhere, aModifiedArray);
+ if (aResult.IsNull()) {
+ SetErrorCode("Error in algorithm: result found, but cannot be returned.");
+ return NULL;
+ }
+
+ if (aModifiedArray->Length() > 1) {
+ //Set a GROUP type
+ aResult->SetType(GEOM_GROUP);
+
+ //Set a sub shape type
+ TopoDS_Shape aFirstFound = aWhereIndices.FindKey(aModifiedArray->Value(1));
+ TopAbs_ShapeEnum aShapeType = aFirstFound.ShapeType();
+
+ TDF_Label aFreeLabel = aResult->GetFreeLabel();
+ TDataStd_Integer::Set(aFreeLabel, (Standard_Integer)aShapeType);
+ }
+
+ //Make a Python command
+ Handle(GEOM_Function) aFunction = aResult->GetFunction(1);
+
+ GEOM::TPythonDump(aFunction) << aResult << " = geompy.GetInPlaceByHistory("
+ << theShapeWhere << ", " << theShapeWhat << ")";
+
+ SetErrorCode(OK);
+ return aResult;
+}
+
+//=======================================================================
+//function : SortShapes
+//purpose :
+//=======================================================================
+void GEOMImpl_IShapesOperations::SortShapes(TopTools_ListOfShape& SL)