diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index f8776a9dd..bf6543f81 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -256,6 +256,7 @@ module GEOM typedef sequence ListOfLong; typedef sequence ListOfDouble; typedef sequence ListOfListOfDouble; + typedef sequence ListOfListOfLong; interface GEOM_Object; interface GEOM_BaseObject; @@ -2692,6 +2693,18 @@ module GEOM GEOM_Object GetInPlaceByHistory (in GEOM_Object theShapeWhere, in GEOM_Object theShapeWhat); + /*! + * \brief A sort of GetInPlace functionality, returning for each sub-shape ID of + * \a theShapeWhat a list of corresponding sub-shape IDs of \a theShapeWhere. + * For example, if theShapeWhat is a box and theShapeWhere is this box cut into + * two parts by a plane, then the result can be as this: + * len( result_list ) = 35, + * result_list[ 1 ] = [ 2, 36 ], which means that the box turned into two solids + * with IDs 2 and 36 within theShapeWhere + */ + ListOfListOfLong GetInPlaceMap (in GEOM_Object theShapeWhere, + in GEOM_Object theShapeWhat); + /*! * \brief Get sub-shape of theShapeWhere, which are * coincident with \a theShapeWhat that can either SOLID, FACE, EDGE or VERTEX. diff --git a/src/GEOMAlgo/GEOMAlgo_GetInPlaceAPI.cxx b/src/GEOMAlgo/GEOMAlgo_GetInPlaceAPI.cxx index bc796863b..4ad518610 100644 --- a/src/GEOMAlgo/GEOMAlgo_GetInPlaceAPI.cxx +++ b/src/GEOMAlgo/GEOMAlgo_GetInPlaceAPI.cxx @@ -45,6 +45,7 @@ #include #include #include +#include //======================================================================= //function : GetInPlace @@ -427,3 +428,156 @@ Standard_Boolean GEOMAlgo_GetInPlaceAPI::GetInPlaceByHistory return isFound; } + +//======================================================================= +//function : GetInPlaceByHistory +//purpose : +//======================================================================= +Standard_Boolean +GEOMAlgo_GetInPlaceAPI::GetInPlaceMap (const Handle(GEOM_Function) & theWhereFunction, + const TopoDS_Shape & theWhat, + std::vector< std::vector< int > > & theResVec) +{ + //theResVec.clear(); + + if (theWhereFunction.IsNull() || theWhat.IsNull() || theWhereFunction->GetValue().IsNull() ) + return Standard_False; + TopoDS_Shape theWhere = theWhereFunction->GetValue(); + + TopTools_IndexedMapOfShape whereIndices, whatIndices; + TopExp::MapShapes( theWhere, whereIndices ); + TopExp::MapShapes( theWhat, whatIndices ); + + theResVec.resize( whatIndices.Extent() + 1 ); + + // first, try by history + + Standard_Boolean isFound = 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 (( isFound = anArgumentIndices.Contains(theWhat))) + { + // Find corresponding label in history + TDF_Label anArgumentHistoryLabel = + theWhereFunction->GetArgumentHistoryEntry(anArgumentRefLabel, Standard_False); + if ( anArgumentHistoryLabel.IsNull()) + { + // Lost History of operation argument. Possibly, theWhat was removed from theWhere + isFound = false; + break; + } + else + { + Standard_Integer aWhatIndex = anArgumentIndices.FindIndex(theWhat); + for ( int i = 0, iSubWhat = aWhatIndex; i < whatIndices.Extent(); ++i, ++iSubWhat ) + { + TDF_Label aHistoryLabel = anArgumentHistoryLabel.FindChild( iSubWhat, Standard_False ); + if ( !aHistoryLabel.IsNull() ) + { + Handle(TDataStd_IntegerArray) anIntegerArray; + if (aHistoryLabel.FindAttribute(TDataStd_IntegerArray::GetID(), anIntegerArray)) + { + Standard_Integer imod, aModifLen = anIntegerArray->Array()->Length(); + for ( imod = 1; imod <= aModifLen; imod++ ) + { + Standard_Integer whereIndex = anIntegerArray->Array()->Value( imod ); + const TopoDS_Shape& argSubShape = anArgumentIndices( iSubWhat ); + Standard_Integer whatIndex = whatIndices.FindIndex( argSubShape ); + theResVec[ whatIndex ].push_back( whereIndex ); + } + } + } + } + } + } + } + + if ( !isFound ) // use GetInPlace() + { + GEOMAlgo_GetInPlace gip; + if ( ! GetInPlace( theWhere, theWhat, gip )) + return false; + + const TopTools_DataMapOfShapeListOfShape& img = gip.Images(); + TopTools_DataMapIteratorOfDataMapOfShapeListOfShape imgIt( img ); + for ( ; imgIt.More(); imgIt.Next() ) + { + const TopoDS_Shape& whatSub = imgIt.Key(); + const TopTools_ListOfShape& whereSubList = imgIt.Value(); + int whatID = whatIndices.FindIndex( whatSub ); + if ( whatID == 0 ) continue; + TopTools_ListIteratorOfListOfShape whereIt( whereSubList ); + for ( ; whereIt.More(); whereIt.Next() ) + { + int whereID = whereIndices.FindIndex( whereIt.Value() ); + if ( whereID && whatSub.ShapeType() == whereIt.Value().ShapeType() ) + theResVec[ whatID ].push_back( whereID ); + } + isFound = true; + } + } + + if ( isFound ) + { + // check that all sub-shapes are found and restore missing history of wires, shells etc. + for ( int iSubWhat = 1; iSubWhat <= whatIndices.Extent(); ++iSubWhat ) + { + if ( !theResVec[ iSubWhat ].empty() ) + continue; + const TopoDS_Shape& whatSubShape = whatIndices( iSubWhat ); + switch ( whatSubShape.ShapeType() ) + { + case TopAbs_COMPOUND: + case TopAbs_COMPSOLID: + continue; // not possible? + case TopAbs_SHELL: + case TopAbs_WIRE: + { + // find a corresponding sub-shape in theWhere + TColStd_MapOfInteger whereIDs; + TopAbs_ShapeEnum subType = + whatSubShape.ShapeType() == TopAbs_WIRE ? TopAbs_EDGE : TopAbs_FACE; + for ( TopExp_Explorer subIt( whatSubShape, subType ); subIt.More(); subIt.Next() ) + { + int whatID = whatIndices.FindIndex( subIt.Current() ); + std::vector< int > & whereIDsVec = theResVec[ whatID ]; + for ( size_t i = 0; i < whereIDsVec.size(); ++i ) + whereIDs.Add( whereIDsVec[i] ); + } + // look for a Where sub-shape including all whereIDs + TopExp_Explorer whereIt( theWhere, whatSubShape.ShapeType() ); + for ( ; whereIt.More(); whereIt.Next() ) + { + bool isAllIn = true; + for ( TopoDS_Iterator it( whereIt.Current() ); it.More() && isAllIn; it.Next() ) + { + int whereID = whereIndices.FindIndex( it.Value() ); + isAllIn = whereIDs.Contains( whereID ); + } + if ( isAllIn ) + { + theResVec[ iSubWhat ].push_back( whereIndices.FindIndex( whereIt.Current() )); + break; + } + } + } + default:; // removed sub-shape + } + } + } + + return isFound; +} diff --git a/src/GEOMAlgo/GEOMAlgo_GetInPlaceAPI.hxx b/src/GEOMAlgo/GEOMAlgo_GetInPlaceAPI.hxx index 1bb4db079..2747c39c6 100644 --- a/src/GEOMAlgo/GEOMAlgo_GetInPlaceAPI.hxx +++ b/src/GEOMAlgo/GEOMAlgo_GetInPlaceAPI.hxx @@ -32,6 +32,8 @@ #include #include +#include + class GEOMAlgo_GetInPlace; class BRepExtrema_DistShapeShape; class TopoDS_Face; @@ -82,11 +84,21 @@ public: * list is not cleared at first. */ Standard_EXPORT static Standard_Boolean GetInPlaceByHistory - (const Handle(GEOM_Function) &theWhereFunction, + (const Handle(GEOM_Function) &theWhereFunction, const TopTools_IndexedMapOfShape &theWhereIndices, const TopoDS_Shape &theWhat, TopTools_ListOfShape &theShapesInPlace); + /** + * \brief GetInPlaceMap method implementation. + * For each sub-shape ID in theWhat fills an array of corresponding + * sub-shape IDs in theWhere + */ + Standard_EXPORT static Standard_Boolean GetInPlaceMap + (const Handle(GEOM_Function) &theWhereFunction, + const TopoDS_Shape &theWhat, + std::vector< std::vector< int > > &theResVec); + protected: /*! diff --git a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx index bd1464bbf..dbec77626 100644 --- a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx @@ -4715,6 +4715,42 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory return aResult; } +//======================================================================= +//function : GetInPlaceMap +//purpose : +//======================================================================= +void GEOMImpl_IShapesOperations::GetInPlaceMap (Handle(GEOM_Object) theShapeWhere, + Handle(GEOM_Object) theShapeWhat, + std::vector< std::vector< int > > & theResVec) +{ + SetErrorCode(KO); + + if (theShapeWhere.IsNull() || theShapeWhat.IsNull()) return; + + TopoDS_Shape aWhere = theShapeWhere->GetValue(); + TopoDS_Shape aWhat = theShapeWhat->GetValue(); + + if (aWhere.IsNull() || aWhat.IsNull()) return; + + Handle(GEOM_Function) aWhereFunction = theShapeWhere->GetLastFunction(); + if (aWhereFunction.IsNull()) return; + + bool isFound = GEOMAlgo_GetInPlaceAPI::GetInPlaceMap( aWhereFunction, aWhat, theResVec ); + + if ( isFound ) + SetErrorCode(OK); + + Handle(GEOM_Function) aFunction = + GEOM::GetCreatedLast(theShapeWhere,theShapeWhat)->GetLastFunction(); + + GEOM::TPythonDump(aFunction, /*append=*/true) + << "resultList = geompy.GetInPlaceMap( " + << theShapeWhere << ", " + << theShapeWhat << ")"; + + return; +} + //======================================================================= //function : isSameEdge //purpose : Returns True if two edges coincide diff --git a/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx b/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx index 1e0b008b3..cc87f2189 100644 --- a/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx @@ -42,6 +42,7 @@ #include #include +#include class GEOM_Engine; class GEOM_Object; @@ -329,6 +330,10 @@ class GEOMImpl_IShapesOperations : public GEOM_IOperations Standard_EXPORT Handle(GEOM_Object) GetInPlaceByHistory (Handle(GEOM_Object) theShapeWhere, Handle(GEOM_Object) theShapeWhat); + Standard_EXPORT void GetInPlaceMap (Handle(GEOM_Object) theShapeWhere, + Handle(GEOM_Object) theShapeWhat, + std::vector< std::vector< int > > & theResVec); + /*! * \brief Searches a shape equal to theWhat in the context of theWhere * \param theShapeWhere - a context shap diff --git a/src/GEOM_I/GEOM_IShapesOperations_i.cc b/src/GEOM_I/GEOM_IShapesOperations_i.cc index 6aa10a803..c9f451328 100644 --- a/src/GEOM_I/GEOM_IShapesOperations_i.cc +++ b/src/GEOM_I/GEOM_IShapesOperations_i.cc @@ -35,6 +35,8 @@ #include #include +#include + /** * This function converts GEOM::comparison_condition type into * GEOMUtils::ComparisonCondition type. @@ -1985,6 +1987,39 @@ GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::GetInPlaceByHistory return GetObject(anObject); } +//============================================================================= +/*! + * GetInPlaceMap + */ +//============================================================================= +GEOM::ListOfListOfLong* +GEOM_IShapesOperations_i::GetInPlaceMap (GEOM::GEOM_Object_ptr theShapeWhere, + GEOM::GEOM_Object_ptr theShapeWhat) +{ + GEOM::ListOfListOfLong_var aResult = new GEOM::ListOfListOfLong(); + + //Get the reference objects + Handle(::GEOM_Object) aShapeWhere = GetObjectImpl(theShapeWhere); + Handle(::GEOM_Object) aShapeWhat = GetObjectImpl(theShapeWhat); + + if (!aShapeWhere.IsNull() && + !aShapeWhat.IsNull()) + { + std::vector< std::vector< int > > resVec; + GetOperations()->GetInPlaceMap(aShapeWhere, aShapeWhat, resVec); + + aResult->length( resVec.size() ); + for ( size_t i = 0; i < resVec.size(); ++i ) + { + //if ( !resVec[i].empty() ) + aResult[i].length( resVec[i].size() ); + for ( size_t j = 0; j < resVec[i].size(); ++j ) + aResult[i][j] = resVec[i][j]; + } + } + return aResult._retn(); +} + //============================================================================= /*! * GetSame diff --git a/src/GEOM_I/GEOM_IShapesOperations_i.hh b/src/GEOM_I/GEOM_IShapesOperations_i.hh index c48e6b7e1..f9e457629 100644 --- a/src/GEOM_I/GEOM_IShapesOperations_i.hh +++ b/src/GEOM_I/GEOM_IShapesOperations_i.hh @@ -279,6 +279,9 @@ class GEOM_I_EXPORT GEOM_IShapesOperations_i : GEOM::GEOM_Object_ptr GetInPlaceByHistory (GEOM::GEOM_Object_ptr theShapeWhere, GEOM::GEOM_Object_ptr theShapeWhat); + GEOM::ListOfListOfLong* GetInPlaceMap(GEOM::GEOM_Object_ptr theShapeWhere, + GEOM::GEOM_Object_ptr theShapeWhat); + GEOM::GEOM_Object_ptr GetSame (GEOM::GEOM_Object_ptr theShapeWhere, GEOM::GEOM_Object_ptr theShapeWhat); diff --git a/src/GEOM_SWIG/geomBuilder.py b/src/GEOM_SWIG/geomBuilder.py index e3b56a228..b28117581 100644 --- a/src/GEOM_SWIG/geomBuilder.py +++ b/src/GEOM_SWIG/geomBuilder.py @@ -5960,6 +5960,38 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): self._autoPublish(anObj, theName, "inplace") return anObj + ## A sort of GetInPlace functionality, returning IDs of sub-shapes. + # For each sub-shape ID of @a theShapeWhat return a list of corresponding sub-shape + # IDs of @a theShapeWhere. + # For example, if theShapeWhat is a box and theShapeWhere is this box cut into + # two parts by a plane, then the result can be as this: + # len( result_list ) = 35, + # result_list[ 1 ] = [ 2, 36 ], which means that the box (ID 1) turned into two + # solids with IDs 2 and 36 within theShapeWhere + # + # @param theShapeWhere Shape to find sub-shapes of. + # @param theShapeWhat Shape, specifying what to find. + # @return List of lists of sub-shape IDS of theShapeWhere. + def GetInPlaceMap(self, theShapeWhere, theShapeWhat): + """ + A sort of GetInPlace functionality, returning IDs of sub-shapes. + For each sub-shape ID of @a theShapeWhat return a list of corresponding sub-shape + IDs of @a theShapeWhere. + For example, if theShapeWhat is a box and theShapeWhere is this box cut into + two parts by a plane, then the result can be as this: + len( result_list ) = 35, + result_list[ 1 ] = [ 2, 36 ], which means that the box (ID 1) turned into two + solids with IDs 2 and 36 within theShapeWhere + + Parameters: + theShapeWhere Shape to find sub-shapes of. + theShapeWhat Shape, specifying what to find. + + Returns: + List of lists of sub-shape IDS of theShapeWhere. + """ + return self.ShapesOp.GetInPlaceMap(theShapeWhere, theShapeWhat) + ## Get sub-shape of theShapeWhere, which is # equal to \a theShapeWhat. # @param theShapeWhere Shape to find sub-shape of.