From: jfa Date: Wed, 25 Jul 2007 07:07:07 +0000 (+0000) Subject: NPAL16588: Bug in GetInPlace method. X-Git-Tag: T15881 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=b2926171f3acdd95f861e6e9ca8a3e73d974f0b2;p=modules%2Fgeom.git NPAL16588: Bug in GetInPlace method. --- diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index bed796e59..118971724 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -1311,7 +1311,7 @@ module GEOM in shape_state theState); /*! - * Get sub-shape(s) of theShapeWhere, which are + * Get sub-shape(s) of \a theShapeWhere, which are * coincident with \a theShapeWhat or could be a part of it. * \param theShapeWhere Shape to find sub-shapes of. * \param theShapeWhat Shape, specifying what to find. @@ -1320,6 +1320,23 @@ module GEOM GEOM_Object GetInPlace (in GEOM_Object theShapeWhere, in GEOM_Object theShapeWhat); + /*! + * Get sub-shape(s) of \a theShapeWhere, which are + * coincident with \a theShapeWhat or could be a part of it. + * + * Implementation of this method is based on a saved history of an operation, + * produced \a theShapeWhere. The \a theShapeWhat must be among this operation's + * arguments (an argument shape or a sub-shape of an argument shape). + * The operation could be the Partition or one of boolean operations, + * performed on simple shapes (not on compounds). + * + * \param theShapeWhere Shape to find sub-shapes of. + * \param theShapeWhat Shape, specifying what to find. + * \return Group of all found sub-shapes or a single found sub-shape. + */ + GEOM_Object GetInPlaceByHistory (in GEOM_Object theShapeWhere, + in GEOM_Object theShapeWhat); + /*! * Get sub-shape of theShapeWhere, which are * coincident with \a theShapeWhat that can either SOLID, FACE, EDGE or VERTEX. diff --git a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx index 957c1840a..8f698def7 100644 --- a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx @@ -17,6 +17,11 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // +// File : GEOMImpl_IShapesOperations.cxx +// Created : +// Author : modified by Lioka RAZAFINDRAZAKA (CEA) 22/06/2007 +// Project : SALOME +// $Header$ #include @@ -111,6 +116,16 @@ #include #include // CAREFUL ! position of this file is critic : see Lucien PIGNOLONI / OCC +// Includes added for GetInPlace algorithm improvement + +#include +#include +#include + +#include +#include +#include + //============================================================================= /*! * constructor: @@ -2408,7 +2423,7 @@ Handle(TColStd_HSequenceOfInteger) //============================================================================= /*! - * GetInPlace + * GetInPlaceOfShape */ //============================================================================= static bool GetInPlaceOfShape (const Handle(GEOM_Function)& theWhereFunction, @@ -2530,7 +2545,182 @@ static bool GetInPlaceOfShape (const Handle(GEOM_Function)& theWhereFunction, return isFound; } -Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlace +//============================================================================= +/*! + * GetShapeProperties + */ +//============================================================================= + +void GEOMImpl_IShapesOperations::GetShapeProperties( const TopoDS_Shape aShape, Standard_Real tab[], + gp_Pnt & aVertex ) +{ + GProp_GProps SProps, VProps; + gp_Pnt aCenterMass; + TopoDS_Shape aPntShape; + Standard_Real aShapeSize; + + BRepGProp::VolumeProperties(aShape, VProps); + aCenterMass = VProps.CentreOfMass(); + aShapeSize = VProps.Mass(); + if (aShape.ShapeType() == TopAbs_FACE) { + BRepGProp::SurfaceProperties(aShape, SProps); + aCenterMass = SProps.CentreOfMass(); + aShapeSize = SProps.Mass(); + } + + aPntShape = BRepBuilderAPI_MakeVertex(aCenterMass).Shape(); + aVertex = BRep_Tool::Pnt( TopoDS::Vertex( aPntShape ) ); + tab[0] = aVertex.X(); + tab[1] = aVertex.Y(); + tab[2] = aVertex.Z(); + tab[3] = aShapeSize; + return; +} + +//============================================================================= +/*! + * GetInPlace + */ +//============================================================================= +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(); + + 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_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; + gp_Pnt aPnt, aPnt_aWhat; + GProp_GProps aProps; + + // 2D or 3D shapes + if ( aWhat.ShapeType() == TopAbs_COMPOUND || + aWhat.ShapeType() == TopAbs_SHELL || + aWhat.ShapeType() == TopAbs_COMPSOLID ) { + TopExp_Explorer Exp( aWhat, TopAbs_ShapeEnum( iType ) ); + if ( ! Exp.More() ) iType = TopAbs_FACE; + } + else if ( aWhat.ShapeType() == TopAbs_FACE ) + iType = TopAbs_FACE; + + 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 + for ( Standard_Integer nbEdge = 0; Exp_Edge.More(); Exp_Edge.Next(), nbEdge++ ) { + BRepGProp::LinearProperties(Exp_Edge.Current(), aProps); + if ( ! nbEdge ) min_l = aProps.Mass(); + 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) ); + + Tol_Mass = Tol_3D; + if ( iType == TopAbs_FACE ) Tol_Mass = Tol_2D; + + // Compute the ShapeWhat Mass + for ( ; Exp_aWhat.More(); Exp_aWhat.Next() ) { + if ( iType == TopAbs_SOLID ) BRepGProp::VolumeProperties(Exp_aWhat.Current(), aProps); + else if ( iType == TopAbs_FACE ) BRepGProp::SurfaceProperties(Exp_aWhat.Current(), aProps); + aWhat_Mass += aProps.Mass(); + } + + // Finding the Sub-ShapeWhere + for ( Exp_aWhere.ReInit(); Exp_aWhere.More(); Exp_aWhere.Next() ) { + 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) ) { + BRepClass3d_SolidClassifier SC_aWhere (Exp_aWhere.Current(), aPnt, Precision::Confusion()); + BRepClass3d_SolidClassifier SC_aWhat (Exp_aWhat.Current(), aPnt, Precision::Confusion()); + // Block construction 3D + if ( SC_aWhere.State() == TopAbs_IN && SC_aWhat.State() == TopAbs_IN ) isFound = true; + // Block construction 2D + else if ( SC_aWhere.State() == TopAbs_ON && SC_aWhat.State() == TopAbs_ON ) isFound = true; + } + 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; + } + + 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) { diff --git a/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx b/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx index b34567755..1e8cdc2c8 100644 --- a/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx @@ -17,7 +17,14 @@ // // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com // - +//============================================================================= +// File : GEOMImpl_IShapesOperations.hxx +// Created : +// Author : modified by Lioka RAZAFINDRAZAKA (CEA) 22/06/2007 +// Project : SALOME +// Copyright : CEA 2003 +// $Header$ +//============================================================================= #ifndef _GEOMImpl_IShapesOperations_HXX_ #define _GEOMImpl_IShapesOperations_HXX_ @@ -32,6 +39,8 @@ #include #include +#include + class GEOM_Engine; class Handle(GEOM_Object); class Handle(TColStd_HArray1OfInteger); @@ -206,9 +215,14 @@ class GEOMImpl_IShapesOperations : public GEOM_IOperations Handle(GEOM_Object) theCenter, const Standard_Real theRadius); + void GetShapeProperties(const TopoDS_Shape aShape, Standard_Real propertiesArray[], gp_Pnt & aPnt); + Standard_EXPORT Handle(GEOM_Object) GetInPlace (Handle(GEOM_Object) theShapeWhere, Handle(GEOM_Object) theShapeWhat); + Standard_EXPORT Handle(GEOM_Object) GetInPlaceByHistory (Handle(GEOM_Object) theShapeWhere, + Handle(GEOM_Object) theShapeWhat); + /*! * \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 7e022a0c3..32dd0f023 100644 --- a/src/GEOM_I/GEOM_IShapesOperations_i.cc +++ b/src/GEOM_I/GEOM_IShapesOperations_i.cc @@ -1325,6 +1325,41 @@ GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::GetInPlace return GetObject(anObject); } +//============================================================================= +/*! + * GetInPlaceByHistory + */ +//============================================================================= +GEOM::GEOM_Object_ptr GEOM_IShapesOperations_i::GetInPlaceByHistory + (GEOM::GEOM_Object_ptr theShapeWhere, + GEOM::GEOM_Object_ptr theShapeWhat) +{ + GEOM::GEOM_Object_var aGEOMObject; + + //Set a not done flag + GetOperations()->SetNotDone(); + + if (theShapeWhere == NULL || + theShapeWhat == NULL) return aGEOMObject._retn(); + + //Get the reference objects + Handle(GEOM_Object) aShapeWhere = GetOperations()->GetEngine()->GetObject + (theShapeWhere->GetStudyID(), theShapeWhere->GetEntry()); + Handle(GEOM_Object) aShapeWhat = GetOperations()->GetEngine()->GetObject + (theShapeWhat->GetStudyID(), theShapeWhat->GetEntry()); + + if (aShapeWhere.IsNull() || + aShapeWhat.IsNull()) return aGEOMObject._retn(); + + //Get Shapes in place of aShapeWhat + Handle(GEOM_Object) anObject = + GetOperations()->GetInPlaceByHistory(aShapeWhere, aShapeWhat); + if (!GetOperations()->IsDone() || anObject.IsNull()) + return aGEOMObject._retn(); + + return GetObject(anObject); +} + //============================================================================= /*! * GetSame diff --git a/src/GEOM_I/GEOM_IShapesOperations_i.hh b/src/GEOM_I/GEOM_IShapesOperations_i.hh index 036603b7f..81c2ad8da 100644 --- a/src/GEOM_I/GEOM_IShapesOperations_i.hh +++ b/src/GEOM_I/GEOM_IShapesOperations_i.hh @@ -176,6 +176,9 @@ class GEOM_IShapesOperations_i : GEOM::GEOM_Object_ptr GetInPlace (GEOM::GEOM_Object_ptr theShapeWhere, GEOM::GEOM_Object_ptr theShapeWhat); + GEOM::GEOM_Object_ptr GetInPlaceByHistory (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/GEOM_TestOthers.py b/src/GEOM_SWIG/GEOM_TestOthers.py index a530c3433..899553a35 100644 --- a/src/GEOM_SWIG/GEOM_TestOthers.py +++ b/src/GEOM_SWIG/GEOM_TestOthers.py @@ -524,24 +524,72 @@ def TestOtherOperations (geompy, math): geompy.UnionIDs(vertices_on_quad, vertices_on_quad_ids) geompy.addToStudy(vertices_on_quad, "Group of vertices on Quadrangle F12") - # GetInPlace(theShapeWhere, theShapeWhat) + # Prepare arguments for GetInPlace and GetInPlaceByHistory box5 = geompy.MakeBoxDXDYDZ(100, 100, 100) box6 = geompy.MakeTranslation(box5, 50, 50, 0) + geompy.addToStudy(box5, "Box 5") + geompy.addToStudy(box6, "Box 6") + + part = geompy.MakePartition([box5], [box6]) + geompy.addToStudy(part, "Partitioned") + + box5_faces = geompy.SubShapeAll(box5, geompy.ShapeType["FACE"]) + box6_faces = geompy.SubShapeAll(box6, geompy.ShapeType["FACE"]) + + ifa = 1 + for aface in box5_faces: + geompy.addToStudyInFather(box5, aface, "Face" + `ifa`) + ifa = ifa + 1 + + ifa = 1 + for aface in box6_faces: + geompy.addToStudyInFather(box6, aface, "Face" + `ifa`) + ifa = ifa + 1 + + # GetInPlace(theShapeWhere, theShapeWhat) + ibb = 5 + faces_list = [box5_faces, box6_faces] + for afaces in faces_list: + ifa = 1 + for aface in afaces: + if ibb == 6 and (ifa == 2 or ifa == 4): + # use IDL interface directly to avoid error message appearence in Python console + refl_box_face = geompy.ShapesOp.GetInPlace(part, aface) + if refl_box_face is not None: + geompy.addToStudyInFather(part, refl_box_face, + "Reflection of face " + `ifa` + " of box " + `ibb`) + error = "Result of GetInPlace must be NULL for face " + `ifa` + " of box " + `ibb` + raise RuntimeError, error + else: + # use geompy interface + refl_box_face = geompy.GetInPlace(part, aface) + geompy.addToStudyInFather(part, refl_box_face, + "Reflection of face " + `ifa` + " of box " + `ibb`) + ifa = ifa + 1 + ibb = ibb + 1 + + # GetInPlaceByHistory(theShapeWhere, theShapeWhat) part = geompy.MakePartition([box5], [box6]) geompy.addToStudy(part, "Partitioned") ibb = 5 - box_list = [box5, box6] - for abox in box_list: - geompy.addToStudy(abox, "Box " + `ibb`) - box_faces = geompy.SubShapeAll(abox, geompy.ShapeType["FACE"]) + faces_list = [box5_faces, box6_faces] + for afaces in faces_list: ifa = 1 - for aface in box_faces: - geompy.addToStudyInFather(abox, aface, "Face" + `ifa`) - refl_box_face = geompy.GetInPlace(part, aface) - if refl_box_face is not None: + for aface in afaces: + if ibb == 6 and (ifa == 2 or ifa == 4): + # use IDL interface directly to avoid error message appearence in Python console + refl_box_face = geompy.ShapesOp.GetInPlaceByHistory(part, aface) + if refl_box_face is not None: + geompy.addToStudyInFather(part, refl_box_face, + "Reflection of face " + `ifa` + " of box " + `ibb` + " (by history)") + error = "Result of GetInPlaceByHistory must be NULL for face " + `ifa` + " of box " + `ibb` + raise RuntimeError, error + else: + # use geompy interface + refl_box_face = geompy.GetInPlaceByHistory(part, aface) geompy.addToStudyInFather(part, refl_box_face, - "Reflection of Face " + `ifa` + " of box " + `ibb`) + "Reflection of face " + `ifa` + " of box " + `ibb` + " (by history)") ifa = ifa + 1 ibb = ibb + 1 diff --git a/src/GEOM_SWIG/geompy.py b/src/GEOM_SWIG/geompy.py index 36db1cc3e..cf5a61fcf 100644 --- a/src/GEOM_SWIG/geompy.py +++ b/src/GEOM_SWIG/geompy.py @@ -1097,6 +1097,27 @@ def GetInPlace(theShapeWhere, theShapeWhat): print "GetInPlace : ", ShapesOp.GetErrorCode() return anObj +## Get sub-shape(s) of \a theShapeWhere, which are +# coincident with \a theShapeWhat or could be a part of it. +# +# Implementation of this method is based on a saved history of an operation, +# produced \a theShapeWhere. The \a theShapeWhat must be among this operation's +# arguments (an argument shape or a sub-shape of an argument shape). +# The operation could be the Partition or one of boolean operations, +# performed on simple shapes (not on compounds). +# +# @param theShapeWhere Shape to find sub-shapes of. +# @param theShapeWhat Shape, specifying what to find (must be in the +# building history of the ShapeWhere). +# @return Group of all found sub-shapes or a single found sub-shape. +# +# Example: see GEOM_TestOthers.py +def GetInPlaceByHistory(theShapeWhere, theShapeWhat): + anObj = ShapesOp.GetInPlaceByHistory(theShapeWhere, theShapeWhat) + if ShapesOp.IsDone() == 0: + print "GetInPlace : ", ShapesOp.GetErrorCode() + return anObj + ## Get sub-shape of theShapeWhere, which is # equal to \a theShapeWhat. # @param theShapeWhere Shape to find sub-shape of.