0022747: [EDF] Improvement of Get Shared Shapes operation

Additional improvements:
- Add multi-share parameter to allow searching not sub-shapes which are shared either by all or by couples of input shapes
- Avoid raising exception if no sub-shapes is found; return empty result instead
- Add test script
This commit is contained in:
vsr 2014-12-26 11:52:00 +03:00
parent 13b11d15c8
commit 528f4842f4
15 changed files with 228 additions and 91 deletions

View File

@ -41,6 +41,7 @@ SET(GOOD_TESTS
basic_operations_ex01.py
basic_operations_ex02.py
basic_operations_ex03.py
basic_operations_ex04.py
basic_properties.py
blocks_operations_ex01.py
blocks_operations_ex02.py

View File

@ -0,0 +1,40 @@
# Get shared sub-shapes
import salome
salome.salome_init()
import GEOM
from salome.geom import geomBuilder
geompy = geomBuilder.New(salome.myStudy)
import SALOMEDS
# create a box and partigion it by two planes
box = geompy.MakeBoxDXDYDZ(200, 200, 200)
p = geompy.MakeVertex(100, 100, 100)
v1 = geompy.MakeVectorDXDYDZ(1, 1, 0)
v2 = geompy.MakeVectorDXDYDZ(1, -1, 0)
pln1 = geompy.MakePlane(p, v1, 2000)
pln2 = geompy.MakePlane(p, v2, 2000)
partition = geompy.MakePartition([box], [pln1, pln2])
# extract solids from result of partition
solids = geompy.SubShapeAllSorted(partition, geompy.ShapeType['SOLID'])
# get shared shapes from the partition (compound of 4 solids)
# a) faces that are shared by all 4 solids (0 found)
pF_T = geompy.GetSharedShapesMulti(partition, geompy.ShapeType['FACE'])
# b) faces that are shared by any couple of solids (4 found)
pF_F = geompy.GetSharedShapesMulti(partition, geompy.ShapeType['FACE'], False)
# c) edges that are shared by all 4 solids (1 found)
pE_T = geompy.GetSharedShapesMulti(partition, geompy.ShapeType['EDGE'])
# d) edges that are shared by any couple of solids (13 found)
pE_F = geompy.GetSharedShapesMulti(partition, geompy.ShapeType['EDGE'], False)
# get shared shapes from the list of solids
# a) faces that are shared by all 4 solids (0 found)
sF_T = geompy.GetSharedShapesMulti(solids, geompy.ShapeType['FACE'])
# b) faces that are shared by 1st/2nd, 1st/3rd and 1st/4th solids (2 found)
sF_F = geompy.GetSharedShapesMulti(solids, geompy.ShapeType['FACE'], False)
# c) edges that are shared by all 4 solids (1 found)
sE_T = geompy.GetSharedShapesMulti(solids, geompy.ShapeType['EDGE'])
# d) edges that are shared by 1st/2nd, 1st/3rd and 1st/4th solids (7 found)
sE_F = geompy.GetSharedShapesMulti(solids, geompy.ShapeType['EDGE'], False)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -4,7 +4,7 @@
This operation is a special case of <b>Explode</b> operation. It
produces sub-shapes of the exploded shape (the first shape in the list
of argument shapes), which are shared with all other shapes in the
of argument shapes), which are shared with other shapes in the
arguments. The argument shapes can also be contained in a compound or
group.
@ -13,19 +13,28 @@ Shared Shapes.</b> The following dialog box will appear.
\image html shared_shapes.png
<ul>
<li> <b>Name</b> is the base name of the resulting shapes. </li>
<li> <b>Shapes</b> are the shapes to fing shared sub-shapes of. </li>
<li> <b>Sub-shapes Type</b> is the type of required sub-shapes. </li>
</ul>
In this dialog:
- <b>Name</b> is the base name of the resulting shapes.
- <b>Shapes</b> are the shapes to fing shared sub-shapes of.
- <b>Sub-shapes Type</b> is the type of required sub-shapes.
- <b>Multi-shares only</b> option specifies what type of shared sub-shapes should be checked:
- \b On: causes to search sub-shapes from the first input shape shared with all other input shapes;
- \b Off: causes to search sub-shapes shared between couples of input shapes.
\note For the case when "Multi-shares only" option is switched off - if an input list of shapes
contains single compound, the sub-shapes shared between all possible couples of its top-level shapes
are searched; otherwise, only sub-shapes that are shared between first input shape and all rest input
shapes are searched.
<b>Advanced options:</b> \ref preview_anchor "Preview"
\n <b>Advanced options:</b> \ref preview_anchor "Preview"
<p>
<b>TUI Command:</b> <em> geompy.GetSharedShapesMulti( Shapes, Type ),</em>
<br> where \em Shapes is a list or compound of shapes to fing shared sub-
shapes of and \em Type is the type of required sub-shapes.
Our <b>TUI Scripts</b> provide you with useful examples of the use of
\ref swig_GetSharedShapes "Get Shared Shapes" functionality.
Get Shared Shapes functionality:
- \ref tui_shared_shapes "Example 1"
- \ref swig_GetSharedShapes "Example 2"
*/

View File

@ -14,4 +14,8 @@
<br><h2>Restore presentation parameters and sub-shapes</h2>
\tui_script{basic_operations_ex03.py}
\anchor tui_shared_shapes
<br><h2>Get shared shapes</h2>
\tui_script{basic_operations_ex04.py}
*/

View File

@ -2267,13 +2267,21 @@ module GEOM
in long theShapeType);
/*!
* \brief Get all sub-shapes, shared by all shapes in the list \a theShapes.
* \brief Get sub-shapes, shared by input shapes.
* \param theShapes Shapes to find common sub-shapes of.
* \param theShapeType Type of sub-shapes to be retrieved.
* \return List of objects, that are sub-shapes of all given shapes.
* \param theMultiShare Specifies what type of shares should be checked:
* - \c TRUE: search sub-shapes from 1st input shape shared with all other input shapes;
* - \c FALSE: causes to search sub-shapes shared between couples of input shapes.
* \note If \a theShapes contains single compound, the shares between all possible couples of
* its top-level shapes are returned; otherwise, only shares between 1st input shape
* and all rest input shapes are returned.
*
* \return List of all found sub-shapes.
*/
ListOfGO GetSharedShapesMulti (in ListOfGO theShapes,
in long theShapeType);
in long theShapeType,
in boolean theMultiShare);
/*!
* \brief Find in \a theShape all sub-shapes of type \a theShapeType, situated relatively

View File

@ -6955,6 +6955,10 @@ Do you want to create new material?</translation>
<source>GEOM_SHARED_SHAPE</source>
<translation>Shared_%1</translation>
</message>
<message>
<source>GEOM_SHARED_SHAPES_MULTISHARE</source>
<translation>Multi-shares only</translation>
</message>
</context>
<context>
<name>GEOMToolsGUI_PublishDlg</name>

View File

@ -6883,6 +6883,10 @@ Voulez-vous en créer un nouveau ?</translation>
<source>GEOM_SHARED_SHAPE</source>
<translation>Partagé_%1</translation>
</message>
<message>
<source>GEOM_SHARED_SHAPES_MULTISHARE</source>
<translation type="unfinished">Multi-shares only</translation>
</message>
</context>
<context>
<name>GEOMToolsGUI_PublishDlg</name>

View File

@ -6860,6 +6860,10 @@
<source>GEOM_SHARED_SHAPE</source>
<translation>Shared_%1</translation>
</message>
<message>
<source>GEOM_SHARED_SHAPES_MULTISHARE</source>
<translation type="unfinished">Multi-shares only</translation>
</message>
</context>
<context>
<name>GEOMToolsGUI_PublishDlg</name>

View File

@ -2252,7 +2252,7 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
}
if (aSeq->IsEmpty()) {
SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
SetErrorCode(NOT_FOUND_ANY);
return aSeq;
}
@ -2272,121 +2272,168 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
//=======================================================================
//function : GetSharedShapes
//purpose :
//
// NOTE on the implementation
//
// 1) Resulting sub-shapes are published as a children of the 1st input shape
// from theShapes list. Due to this reason only direct sub-shapes of the 1st
// shape can be contained in the result of the operation (i.e. shares between
// 2nd/3rd, etc couples cannot be retrieved.
// 2) An exception from above case is when a single compound is specified as an
// input. In this case we search shares between its top-level content, so we
// are able to search shares between all possible couples of shapes.
// 3) Parameter theMultiShare controls what types of shares to search:
// - True: get sub-shapes that are shared between ALL input shapes;
// - False: get shares between couples of input sub-shapes (see points 1 and 2).
//
// Thus, we have the following cases:
// [1] theShapes = N shapes (N>1), theMultiShare = True
// Result: sub-shapes that are shared by all theShapes
// [2] theShapes = N shapes (N>1), theMultiShare = False
// Result: sub-shapes of 1st shape from theShapes that are shared with any shape
// from theShapes
// [3] theShapes = 1 shape, theMultiShare = True
// Result: sub-shapes that are shared by all top-level sub-objects of theShapes[0]
// [4] theShapes = 1 shape, theMultiShare = False
// Result: sub-shapes of all possible couples of all top-level sub-objects of
// theShapes[0].
//=======================================================================
Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations::GetSharedShapes
(std::list<Handle(GEOM_Object)> & theShapes,
const Standard_Integer theShapeType)
const Standard_Integer theShapeType,
const bool theMultiShare)
{
SetErrorCode(KO);
int aLen = theShapes.size();
if (aLen < 1) return NULL;
int ind = 1;
std::list<Handle(GEOM_Object)>::iterator it = theShapes.begin();
// main object is always first in the input list
// it is the object from which sub-shapes indices are taken
// and where results are published
Handle(GEOM_Object) aMainObj = *it;
Handle(GEOM_Function) aMainShape = aMainObj->GetLastFunction();
// collect all shapes from the input list (including first one) for processing
TopTools_SequenceOfShape shapeSeq;
for (; it != theShapes.end(); it++, ind++) {
for (; it != theShapes.end(); it++) {
Handle(GEOM_Function) aRefShape = (*it)->GetLastFunction();
if (aRefShape.IsNull()) {
SetErrorCode("NULL shape for GetSharedShapes");
return NULL;
}
TopoDS_Shape aShape2 = aRefShape->GetValue();
if (aShape2.IsNull()) return NULL;
shapeSeq.Append( aShape2 );
TopoDS_Shape aShape = aRefShape->GetValue();
if (aShape.IsNull()) {
SetErrorCode("NULL shape for GetSharedShapes");
return NULL;
}
shapeSeq.Append( aShape );
}
TopoDS_Shape aShape1 = shapeSeq.First();
// if only single shape is specified as input
// collect all ites top-level sub-shapes for processing
if ( shapeSeq.Length() == 1 )
{
TopoDS_Shape aShape = shapeSeq.First();
shapeSeq.Clear();
for ( TopoDS_Iterator it( aShape1); it.More(); it.Next() )
for ( TopoDS_Iterator it( aShape ); it.More(); it.Next() )
shapeSeq.Append( it.Value() );
aShape1 = shapeSeq.First();
}
// map all sub-shapes in a main shape to their indices
TopTools_IndexedMapOfShape anIndices;
TopExp::MapShapes(aMainShape->GetValue(), anIndices);
TopTools_MapOfShape mapShape;
TopTools_IndexedMapOfShape mapSelected;
TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapSelected);
// find shared shapes
// Find shared shapes
BRep_Builder B;
TopoDS_Compound aCurrSelection;
// here we will collect all shares
TopTools_ListOfShape aShared;
for ( ind = 2; ind <= shapeSeq.Length(); ind++) {
TopoDS_Compound aCompound;
B.MakeCompound(aCompound);
const TopoDS_Shape& aShape2 = shapeSeq.Value( ind );
TopTools_MapOfShape mapShape2;
TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
for (; exp.More(); exp.Next()) {
const TopoDS_Shape& aSS = exp.Current();
if (mapShape2.Add(aSS) && mapSelected.Contains(aSS)) {
B.Add(aCompound, aSS);
// number of iterations
int nbIters = theMultiShare || theShapes.size() > 1 ? 1 : shapeSeq.Length()-1;
// numShares factor to search (i.e. by what nb of shapes each found sub-shape should be shared)
int nbShares = theMultiShare ? shapeSeq.Length()-1 : 1;
for ( int iter = 1; iter <= nbIters; iter++) {
for ( int ind = iter+1; ind <= shapeSeq.Length(); ind++) {
if ( ind-1+nbShares > shapeSeq.Length() ) break;
TopoDS_Compound aCurrSelection;
TopoDS_Shape aShape1 = shapeSeq.Value( iter );
TopTools_IndexedMapOfShape mapSelected;
TopExp::MapShapes(aShape1, TopAbs_ShapeEnum(theShapeType), mapSelected);
for ( int s = 0; s < nbShares; s++ ) {
BRep_Builder B;
TopoDS_Compound aCompound;
B.MakeCompound(aCompound);
const TopoDS_Shape& aShape2 = shapeSeq.Value( ind+s );
TopTools_MapOfShape mapShape2;
TopExp_Explorer exp (aShape2, TopAbs_ShapeEnum(theShapeType));
for (; exp.More(); exp.Next()) {
const TopoDS_Shape& aSS = exp.Current();
if (mapShape2.Add(aSS) && mapSelected.Contains(aSS)) {
B.Add(aCompound, aSS);
}
}
mapSelected.Clear();
aCurrSelection = aCompound;
TopExp::MapShapes(aCurrSelection, TopAbs_ShapeEnum(theShapeType), mapSelected);
}
TopoDS_Iterator itSel(aCurrSelection, Standard_True, Standard_True);
for (; itSel.More(); itSel.Next()) {
const TopoDS_Shape& aSS = itSel.Value();
if (mapShape.Add(aSS) )
aShared.Append(aSS);
}
}
mapSelected.Clear();
TopExp::MapShapes(aCompound, TopAbs_ShapeEnum(theShapeType), mapSelected);
aCurrSelection = aCompound;
}
// Create GEOM_Object for each found shared shape (collected in aCurrSelection)
Handle(GEOM_Object) anObj, aLastCreated;
Handle(TColStd_HArray1OfInteger) anArray;
Handle(TColStd_HSequenceOfTransient) aSeq = new TColStd_HSequenceOfTransient;
TCollection_AsciiString anAsciiList, anEntry;
TopoDS_Iterator itSel (aCurrSelection, Standard_True, Standard_True);
for (; itSel.More(); itSel.Next()) {
anArray = new TColStd_HArray1OfInteger(1,1);
anArray->SetValue(1, anIndices.FindIndex(itSel.Value()));
if (aShared.IsEmpty()){
SetErrorCode(NOT_FOUND_ANY);
return aSeq;
}
// create GEOM_Object for each found shared shape (collected in aShared)
TCollection_AsciiString anAsciiList;
Handle(GEOM_Object) anObj;
TopTools_ListIteratorOfListOfShape itSub (aShared);
for (; itSub.More(); itSub.Next()) {
TopoDS_Shape aValue = itSub.Value();
Handle(TColStd_HArray1OfInteger) anArray = new TColStd_HArray1OfInteger(1,1);
anArray->SetValue(1, anIndices.FindIndex(aValue));
anObj = GetEngine()->AddSubShape(aMainObj, anArray);
aSeq->Append(anObj);
aLastCreated = GEOM::GetCreatedLast( aLastCreated, anObj );
// for python command
TCollection_AsciiString anEntry;
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
// make a Python command
anAsciiList.Trunc(anAsciiList.Length() - 1);
// IPAL22904: TC6.5.0: order of python commands is wrong after dump study
// Get the function of the latest published object
Handle(GEOM_Function) aFunction = aLastCreated->GetLastFunction();
if( aFunction.IsNull() ) // just in case
aFunction = aMainShape;
GEOM::TPythonDump pd (aFunction, /*append=*/true);
GEOM::TPythonDump pd (anObj->GetLastFunction());
pd << "[" << anAsciiList.ToCString()
<< "] = geompy.GetSharedShapesMulti([";
<< "] = geompy.GetSharedShapesMulti(";
if ( aLen > 1 )
pd << "[";
it = theShapes.begin();
pd << (*it++);
while (it != theShapes.end()) {
pd << ", " << (*it++);
}
if ( aLen > 1 )
pd << "]";
pd << "], " << TopAbs_ShapeEnum(theShapeType) << ")";
pd << ", " << TopAbs_ShapeEnum(theShapeType) << ", " << theMultiShare << ")";
SetErrorCode(OK);
return aSeq;

View File

@ -176,7 +176,8 @@ class GEOMImpl_IShapesOperations : public GEOM_IOperations
Standard_EXPORT Handle(TColStd_HSequenceOfTransient)
GetSharedShapes (std::list<Handle(GEOM_Object)>& theShapes,
const Standard_Integer theShapeType);
const Standard_Integer theShapeType,
const bool theMultiShare = true);
Standard_EXPORT Handle(TColStd_HSequenceOfTransient)
GetShapesOnPlane (const Handle(GEOM_Object)& theShape,

View File

@ -1155,7 +1155,8 @@ GEOM::ListOfGO* GEOM_IShapesOperations_i::GetSharedShapes
//=============================================================================
GEOM::ListOfGO* GEOM_IShapesOperations_i::GetSharedShapesMulti
(const GEOM::ListOfGO& theShapes,
const CORBA::Long theShapeType)
const CORBA::Long theShapeType,
CORBA::Boolean theMultiShare)
{
//Set a not done flag
GetOperations()->SetNotDone();
@ -1168,7 +1169,7 @@ GEOM::ListOfGO* GEOM_IShapesOperations_i::GetSharedShapesMulti
return aSeq._retn();
Handle(TColStd_HSequenceOfTransient) aHSeq =
GetOperations()->GetSharedShapes(aShapes, theShapeType);
GetOperations()->GetSharedShapes(aShapes, theShapeType, theMultiShare);
if (!GetOperations()->IsDone() || aHSeq.IsNull())
return aSeq._retn();

View File

@ -165,7 +165,8 @@ class GEOM_I_EXPORT GEOM_IShapesOperations_i :
CORBA::Long theShapeType);
GEOM::ListOfGO* GetSharedShapesMulti (const GEOM::ListOfGO& theShapes,
CORBA::Long theShapeType);
CORBA::Long theShapeType,
CORBA::Boolean theMultiShare);
GEOM::ListOfGO* GetShapesOnPlane (GEOM::GEOM_Object_ptr theShape,
CORBA::Long theShapeType,

View File

@ -4920,33 +4920,49 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen):
self._autoPublish(aList, theName, "shared")
return aList
## Get all sub-shapes, shared by all shapes in the list <VAR>theShapes</VAR>.
## Get sub-shapes, shared by input shapes.
# @param theShapes Either a list or compound of shapes to find common sub-shapes of.
# @param theShapeType Type of sub-shapes to be retrieved (see ShapeType())
# @param theShapeType Type of sub-shapes to be retrieved (see ShapeType()).
# @param theMultiShare Specifies what type of shares should be checked:
# - @c True (default): search sub-shapes from 1st input shape shared with all other input shapes;
# - @c False: causes to search sub-shapes shared between couples of input shapes.
# @param theName Object name; when specified, this parameter is used
# for result publication in the study. Otherwise, if automatic
# publication is switched on, default value is used for result name.
#
# @return List of objects, that are sub-shapes of all given shapes.
# @note If @a theShapes contains single compound, the shares between all possible couples of
# its top-level shapes are returned; otherwise, only shares between 1st input shape
# and all rest input shapes are returned.
#
# @ref swig_GetSharedShapes "Example"
# @return List of all found sub-shapes.
#
# Examples:
# - @ref tui_shared_shapes "Example 1"
# - @ref swig_GetSharedShapes "Example 2"
@ManageTransactions("ShapesOp")
def GetSharedShapesMulti(self, theShapes, theShapeType, theName=None):
def GetSharedShapesMulti(self, theShapes, theShapeType, theMultiShare=True, theName=None):
"""
Get all sub-shapes, shared by all shapes in the list theShapes.
Get sub-shapes, shared by input shapes.
Parameters:
theShapes Either a list or compound of shapes to find common sub-shapes of.
theShapeType Type of sub-shapes to be retrieved (see geompy.ShapeType)
theShapeType Type of sub-shapes to be retrieved (see geompy.ShapeType).
theMultiShare Specifies what type of shares should be checked:
- True (default): search sub-shapes from 1st input shape shared with all other input shapes;
- False: causes to search sub-shapes shared between couples of input shapes.
theName Object name; when specified, this parameter is used
for result publication in the study. Otherwise, if automatic
publication is switched on, default value is used for result name.
Note: if theShapes contains single compound, the shares between all possible couples of
its top-level shapes are returned; otherwise, only shares between 1st input shape
and all rest input shapes are returned.
Returns:
List of GEOM.GEOM_Object, that are sub-shapes of all given shapes.
List of all found sub-shapes.
"""
# Example: see GEOM_TestOthers.py
aList = self.ShapesOp.GetSharedShapesMulti(ToList(theShapes), theShapeType)
aList = self.ShapesOp.GetSharedShapesMulti(ToList(theShapes), theShapeType, theMultiShare)
RaiseIfFailed("GetSharedShapesMulti", self.ShapesOp)
self._autoPublish(aList, theName, "shared")
return aList

View File

@ -75,7 +75,7 @@ OperationGUI_GetSharedShapesDlg::OperationGUI_GetSharedShapesDlg
GroupPoints->LineEdit1->setReadOnly(true);
GroupPoints->LineEdit2->hide();
GroupPoints->LineEdit1->setEnabled(true);
GroupPoints->CheckButton1->hide();
GroupPoints->CheckButton1->setText(tr("GEOM_SHARED_SHAPES_MULTISHARE"));
QVBoxLayout* layout = new QVBoxLayout(centralWidget());
layout->setMargin(0); layout->setSpacing(6);
@ -308,12 +308,9 @@ GEOM::GEOM_IOperations_ptr OperationGUI_GetSharedShapesDlg::createOperation()
//=================================================================================
bool OperationGUI_GetSharedShapesDlg::isValid (QString& msg)
{
bool isOK = true;
if (myListShapes.length() < 2) {
isOK = false;
if ( myListShapes.length() == 1 )
isOK = ( myListShapes[0]->GetShapeType() == GEOM::COMPOUND );
}
bool isOK = myListShapes.length() > 1 ||
( myListShapes.length() > 0 && myListShapes[0]->GetShapeType() == GEOM::COMPOUND );
if ( !isOK )
msg = tr("MSG_SHARED_SHAPES_TOO_FEW_SHAPES");
@ -327,7 +324,7 @@ bool OperationGUI_GetSharedShapesDlg::isValid (QString& msg)
bool OperationGUI_GetSharedShapesDlg::execute (ObjectList& objects)
{
GEOM::GEOM_IShapesOperations_var anOper = GEOM::GEOM_IShapesOperations::_narrow(getOperation());
GEOM::ListOfGO_var aList = anOper->GetSharedShapesMulti(myListShapes, GetType());
GEOM::ListOfGO_var aList = anOper->GetSharedShapesMulti(myListShapes, GetType(), GroupPoints->CheckButton1->isChecked());
if (!aList->length())
return false;