-// Copyright (C) 2007-2014 CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2015 CEA/DEN, EDF R&D, OPEN CASCADE
//
// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN,
// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS
}
}
+namespace
+{
+ const double MAX_TOLERANCE = 1.e-7;
+
+ /**
+ * \brief Returns the vertex from theWhere shape that is coincident with
+ * theVertex.
+ *
+ * \param theWhere the shape where the coinsident vertex is searched.
+ * \param theVertex the vertex to be searched.
+ * \return the coincident vertex if it is found. Otherwise null object.
+ */
+ static TopoDS_Vertex getSameVertex(const TopoDS_Shape &theWhere,
+ const TopoDS_Vertex &theVertex)
+ {
+ TopoDS_Vertex aResult;
+ gp_Pnt aPoint = BRep_Tool::Pnt(theVertex);
+ TopExp_Explorer anExp(theWhere, TopAbs_VERTEX);
+ TopTools_MapOfShape aMap;
+
+ for(; anExp.More(); anExp.Next()) {
+ const TopoDS_Shape &aLocalShape = anExp.Current();
+
+ if(!aMap.Add(aLocalShape)) {
+ continue;
+ }
+
+ TopoDS_Vertex aVertex = TopoDS::Vertex(aLocalShape);
+ gp_Pnt aPoint2 = BRep_Tool::Pnt(aVertex);
+
+ if(aPoint.Distance(aPoint2) <= MAX_TOLERANCE) {
+ aResult = aVertex;
+ break;
+ }
+ }
+
+ return aResult;
+ }
+} // end of namespace
+
//=============================================================================
/*!
* constructor:
}
if (aSeq->IsEmpty()) {
- SetErrorCode("The given shapes have no shared sub-shapes of the requested type");
+ SetErrorCode(NOT_FOUND_ANY);
return aSeq;
}
//=======================================================================
//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
- BRep_Builder B;
- TopoDS_Compound aCurrSelection;
-
- for ( ind = 2; ind <= shapeSeq.Length(); ind++) {
-
- TopoDS_Compound aCompound;
- B.MakeCompound(aCompound);
+ // find shared shapes
- const TopoDS_Shape& aShape2 = shapeSeq.Value( ind );
+ // here we will collect all shares
+ TopTools_ListOfShape aShared;
- 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;
return aRes;
}
+//=============================================================================
+/*!
+ * GetSubShapeEdgeSorted
+ */
+//=============================================================================
+Handle(TColStd_HSequenceOfTransient)
+ GEOMImpl_IShapesOperations::GetSubShapeEdgeSorted
+ (const Handle(GEOM_Object) &theShape,
+ const Handle(GEOM_Object) &theStartPoint)
+{
+ // Get the sorted edges indices.
+ Handle(TColStd_HSequenceOfInteger) aSortedIDs =
+ getSubShapeEdgeSortedIDs(theShape, theStartPoint);
+
+ // Get object by indices.
+ TCollection_AsciiString anAsciiList;
+ Handle(TColStd_HSequenceOfTransient) aSeq =
+ getObjectsShapesOn(theShape, aSortedIDs, anAsciiList);
+
+ if (aSeq.IsNull() || aSeq->IsEmpty()) {
+ SetErrorCode("Empty sequence of edges");
+ 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.GetSubShapeEdgeSorted("
+ << theShape << ", " << theStartPoint << ")";
+
+ SetErrorCode(OK);
+
+ return aSeq;
+}
+
//=======================================================================
//function : getShapesOnSurfaceIDs
/*!
return aSeq;
}
+//=============================================================================
+/*!
+ * getSubShapeEdgeSortedIDs
+ */
+//=============================================================================
+Handle(TColStd_HSequenceOfInteger)
+ GEOMImpl_IShapesOperations::getSubShapeEdgeSortedIDs
+ (const Handle(GEOM_Object) &theShape,
+ const Handle(GEOM_Object) &theStartPoint)
+{
+ Handle(TColStd_HSequenceOfInteger) aResult;
+
+ if (theShape.IsNull() || theStartPoint.IsNull()) {
+ SetErrorCode("NULL GEOM object");
+ return aResult;
+ }
+
+ const TopoDS_Shape aShape = theShape->GetValue();
+ const TopoDS_Shape aStartPoint = theStartPoint->GetValue();
+
+ if (aShape.IsNull() || aStartPoint.IsNull()) {
+ SetErrorCode("NULL Shape");
+ return aResult;
+ }
+
+ if (aStartPoint.ShapeType() != TopAbs_VERTEX) {
+ SetErrorCode("Starting point is not a vertex");
+ return aResult;
+ }
+
+ TopExp_Explorer anExp(aShape, TopAbs_EDGE);
+ TopTools_MapOfShape aMapFence;
+ TopTools_ListOfShape anEdges;
+
+ for (; anExp.More(); anExp.Next()) {
+ const TopoDS_Shape &anEdge = anExp.Current();
+
+ if (aMapFence.Add(anEdge)) {
+ anEdges.Append(anEdge);
+ }
+ }
+
+ if (anEdges.IsEmpty()) {
+ SetErrorCode("Shape doesn't contain edges");
+ return aResult;
+ }
+
+ // Step 1: Sort edges
+ GEOMUtils::SortShapes(anEdges, Standard_False);
+
+ TopTools_ListIteratorOfListOfShape anIter(anEdges);
+ TopoDS_Vertex aV[2];
+ TopTools_DataMapOfShapeListOfShape aMapVE;
+
+ // Step 2: Fill the map vertex - list of edges.
+ for (; anIter.More(); anIter.Next()) {
+ TopoDS_Edge anEdge = TopoDS::Edge(anIter.Value());
+
+ TopExp::Vertices(anEdge, aV[0], aV[1]);
+
+ const Standard_Integer aNbV = aV[0].IsSame(aV[1]) ? 1 : 2;
+ Standard_Integer i;
+
+ for (i = 0; i < aNbV; ++i) {
+ if (aV[i].IsNull() == Standard_False) {
+ if (!aMapVE.IsBound(aV[i])) {
+ // There is no this vertex in the map.
+ aMapVE.Bind(aV[i], TopTools_ListOfShape());
+ }
+
+ // Add the edge to the list bound with the vertex aV[i].
+ TopTools_ListOfShape &aLEdges = aMapVE.ChangeFind(aV[i]);
+
+ aLEdges.Append(anEdge);
+ }
+ }
+ }
+
+ // Step 3: Find starting point in aMapVE.
+ TopoDS_Vertex aStartVtx = TopoDS::Vertex(aStartPoint);
+
+ if (!aMapVE.IsBound(aStartVtx)) {
+ aStartVtx = getSameVertex(aShape, aStartVtx);
+
+ if (aStartVtx.IsNull()) {
+ SetErrorCode("Invalid Starting point");
+ return aResult;
+ }
+ }
+
+ TopTools_IndexedMapOfShape anIndices;
+ TopTools_MapOfShape aMapVFence;
+ TopoDS_Shape aCurVtx = aStartVtx;
+ TopoDS_Edge aCurEdge =
+ TopoDS::Edge(aMapVE.Find(aCurVtx).First());
+
+ aResult = new TColStd_HSequenceOfInteger;
+ TopExp::MapShapes(aShape, anIndices);
+
+ // Step 4: Fill the list of sorted edges.
+ while (aMapVFence.Add(aCurVtx)) {
+ // Append the ID of the current edge to the list of sorted.
+ aResult->Append(anIndices.FindIndex(aCurEdge));
+ TopExp::Vertices(aCurEdge, aV[0], aV[1]);
+
+ // Get the next vertex.
+ if (aCurVtx.IsSame(aV[0])) {
+ if (aCurVtx.IsSame(aV[1])) {
+ // There is no next vertex.
+ break;
+ } else {
+ aCurVtx = aV[1];
+ }
+ } else {
+ aCurVtx = aV[0];
+ }
+
+ if (aCurVtx.IsNull()) {
+ // There is no next vertex.
+ break;
+ }
+
+ // Get the next edge.
+ const TopTools_ListOfShape &aLEdges = aMapVE.Find(aCurVtx);
+ TopTools_ListIteratorOfListOfShape anEIter(aLEdges);
+
+ for (; anEIter.More(); anEIter.Next()) {
+ const TopoDS_Shape &aLocalEdge = anEIter.Value();
+
+ if (aLocalEdge.IsNull() == Standard_False) {
+ if (!aCurEdge.IsSame(aLocalEdge)) {
+ aCurEdge = TopoDS::Edge(aLocalEdge);
+ break;
+ }
+ }
+ }
+
+ if (!anEIter.More()) {
+ // There is no next edge.
+ break;
+ }
+ }
+
+ return aResult;
+}
+
//=======================================================================
//function : getShapesOnSurface
/*!
return aResult;
}
-#define MAX_TOLERANCE 1.e-7
-
//=======================================================================
//function : isSameEdge
//purpose : Returns True if two edges coincide
switch (aWhat.ShapeType()) {
case TopAbs_VERTEX: {
- gp_Pnt P = BRep_Tool::Pnt(TopoDS::Vertex(aWhat));
- TopExp_Explorer E(aWhere, TopAbs_VERTEX);
- for(; E.More(); E.Next()) {
- if(!aMap.Add(E.Current())) continue;
- gp_Pnt P2 = BRep_Tool::Pnt(TopoDS::Vertex(E.Current()));
- if(P.Distance(P2) <= MAX_TOLERANCE) {
- isFound = true;
- aSubShape = E.Current();
- break;
- }
- }
+ aSubShape = getSameVertex(aWhere, TopoDS::Vertex(aWhat));
+ isFound = !aSubShape.IsNull();
break;
}
case TopAbs_EDGE: {