From 48e895f1fa03c335db1931cb738ca219d7e6d452 Mon Sep 17 00:00:00 2001 From: skv Date: Wed, 14 Jan 2015 16:43:10 +0300 Subject: [PATCH] 0022686: [CEA 1268] Explode a shape into edges sorted in a row from a starting point --- doc/salome/gui/GEOM/input/tui_test_all.doc | 9 +- idl/GEOM_Gen.idl | 9 + src/GEOMImpl/GEOMImpl_IShapesOperations.cxx | 239 ++++++++++++++++++-- src/GEOMImpl/GEOMImpl_IShapesOperations.hxx | 20 ++ src/GEOM_I/GEOM_IShapesOperations_i.cc | 41 ++++ src/GEOM_I/GEOM_IShapesOperations_i.hh | 3 + src/GEOM_SWIG/GEOM_TestAll.py | 13 +- src/GEOM_SWIG/geomBuilder.py | 32 +++ 8 files changed, 349 insertions(+), 17 deletions(-) diff --git a/doc/salome/gui/GEOM/input/tui_test_all.doc b/doc/salome/gui/GEOM/input/tui_test_all.doc index 56beffc5d..e2ecdac38 100644 --- a/doc/salome/gui/GEOM/input/tui_test_all.doc +++ b/doc/salome/gui/GEOM/input/tui_test_all.doc @@ -61,7 +61,7 @@ \until Scale4 \anchor swig_all_trsf_more -\until MakeOffset +\until MakeProjectionOnWire \anchor swig_ChangeOrientation \until ChangeOrientation @@ -69,11 +69,13 @@ \anchor swig_ExtractShapes \until prism_edges +\until IDlist_f + \anchor swig_FilletChamfer \until End of Local operations \anchor swig_all_patterns -\until MultiRot2D +\until MultiRot2Ds \anchor swig_all_measure \until "CheckShape(Prism) = " @@ -91,6 +93,9 @@ \until nameS \anchor swig_all_decompose +\until geompy.RestoreSubShapes(Partition1) + +\anchor swig_GetSubShapeEdgeSorted \until print "DONE" */ diff --git a/idl/GEOM_Gen.idl b/idl/GEOM_Gen.idl index 8863bae26..a85830009 100644 --- a/idl/GEOM_Gen.idl +++ b/idl/GEOM_Gen.idl @@ -2516,6 +2516,15 @@ module GEOM ListOfLong GetSameIDs (in GEOM_Object theShapeWhere, in GEOM_Object theShapeWhat); + /*! + * \brief Explode a shape into edges sorted in a row from a starting point. + * \param theShape - the shape to be exploded on edges. + * \param theStartPoint - the starting point. + * \return Ordered list of edges sorted in a row from a starting point. + */ + ListOfGO GetSubShapeEdgeSorted (in GEOM_Object theShape, + in GEOM_Object theStartPoint); + }; // # GEOM_IBlocksOperations: diff --git a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx index 75a2b46d4..f7df593ad 100644 --- a/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx +++ b/src/GEOMImpl/GEOMImpl_IShapesOperations.cxx @@ -143,6 +143,46 @@ #include #include +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: @@ -2635,6 +2675,44 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetShapesOnShapeAsCompound 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 /*! @@ -2776,6 +2854,152 @@ Handle(TColStd_HSequenceOfTransient) GEOMImpl_IShapesOperations:: 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 /*! @@ -4281,8 +4505,6 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetInPlaceByHistory return aResult; } -#define MAX_TOLERANCE 1.e-7 - //======================================================================= //function : isSameEdge //purpose : Returns True if two edges coincide @@ -4534,17 +4756,8 @@ Handle(GEOM_Object) GEOMImpl_IShapesOperations::GetSame(const Handle(GEOM_Object 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: { diff --git a/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx b/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx index d12642a36..59af88e00 100644 --- a/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx +++ b/src/GEOMImpl/GEOMImpl_IShapesOperations.hxx @@ -383,6 +383,16 @@ class GEOMImpl_IShapesOperations : public GEOM_IOperations const Standard_Integer theShapeType, GEOMAlgo_State theState); + /*! + * \brief Explode a shape into edges sorted in a row from a starting point. + * \param theShape - the shape to be exploded on edges. + * \param theStartPoint - the starting point. + * \return Ordered list of edges sorted in a row from a starting point. + */ + Standard_EXPORT Handle(TColStd_HSequenceOfTransient) + GetSubShapeEdgeSorted (const Handle(GEOM_Object) &theShape, + const Handle(GEOM_Object) &theStartPoint); + private: Handle(GEOM_Object) MakeShape (std::list theShapes, const Standard_Integer theObjectType, @@ -505,6 +515,16 @@ class GEOMImpl_IShapesOperations : public GEOM_IOperations const Handle(TColStd_HSequenceOfInteger)& theShapeIDs, TCollection_AsciiString & theShapeEntries); + /*! + * \brief Explode a shape into edges sorted in a row from a starting point. + * \param theShape - the shape to be exploded on edges. + * \param theStartPoint - the starting point. + * \return Ordered list of edges sorted in a row from a starting point. + */ + Handle(TColStd_HSequenceOfInteger) getSubShapeEdgeSortedIDs + (const Handle(GEOM_Object) &theShape, + const Handle(GEOM_Object) &theStartPoint); + /*! * \brief Select the object created last * \param theObj1 - Object 1 diff --git a/src/GEOM_I/GEOM_IShapesOperations_i.cc b/src/GEOM_I/GEOM_IShapesOperations_i.cc index e26497648..e7f4c7b90 100644 --- a/src/GEOM_I/GEOM_IShapesOperations_i.cc +++ b/src/GEOM_I/GEOM_IShapesOperations_i.cc @@ -1906,3 +1906,44 @@ GEOM::ListOfLong* GEOM_IShapesOperations_i::GetSameIDs return aSeq._retn(); } + +//============================================================================= +/*! + * GetSubShapeEdgeSorted + */ +//============================================================================= +GEOM::ListOfGO* GEOM_IShapesOperations_i::GetSubShapeEdgeSorted + (GEOM::GEOM_Object_ptr theShape, + GEOM::GEOM_Object_ptr theStartPoint) +{ + GEOM::ListOfGO_var aSeq = new GEOM::ListOfGO; + + //Set a not done flag + GetOperations()->SetNotDone(); + + //Get the reference objects + Handle(GEOM_Object) aShape = GetObjectImpl(theShape); + Handle(GEOM_Object) aStartPoint = GetObjectImpl(theStartPoint); + + if (aShape.IsNull() || aStartPoint.IsNull()) { + return aSeq._retn(); + } + + //Get Shapes On Shape + Handle(TColStd_HSequenceOfTransient) aHSeq = + GetOperations()->GetSubShapeEdgeSorted(aShape, aStartPoint); + + if (!GetOperations()->IsDone() || aHSeq.IsNull()) + return aSeq._retn(); + + const Standard_Integer aLength = aHSeq->Length(); + Standard_Integer i; + + aSeq->length(aLength); + + for (i = 1; i <= aLength; i++) { + aSeq[i-1] = GetObject(Handle(GEOM_Object)::DownCast(aHSeq->Value(i))); + } + + return aSeq._retn(); +} diff --git a/src/GEOM_I/GEOM_IShapesOperations_i.hh b/src/GEOM_I/GEOM_IShapesOperations_i.hh index 028d927e0..5baa75ce3 100644 --- a/src/GEOM_I/GEOM_IShapesOperations_i.hh +++ b/src/GEOM_I/GEOM_IShapesOperations_i.hh @@ -271,6 +271,9 @@ class GEOM_I_EXPORT GEOM_IShapesOperations_i : GEOM::ListOfLong* GetSameIDs (GEOM::GEOM_Object_ptr theShapeWhere, GEOM::GEOM_Object_ptr theShapeWhat); + GEOM::ListOfGO* GetSubShapeEdgeSorted (GEOM::GEOM_Object_ptr theShape, + GEOM::GEOM_Object_ptr theStartPoint); + ::GEOMImpl_IShapesOperations* GetOperations() { return (::GEOMImpl_IShapesOperations*)GetImpl(); } }; diff --git a/src/GEOM_SWIG/GEOM_TestAll.py b/src/GEOM_SWIG/GEOM_TestAll.py index b644c196b..46c79bc52 100644 --- a/src/GEOM_SWIG/GEOM_TestAll.py +++ b/src/GEOM_SWIG/GEOM_TestAll.py @@ -216,7 +216,6 @@ def TestAll (geompy, math): Line3 = geompy.MakeLineTwoFaces(prism1_faces[0], prism1_faces[1]) #(2 GEOM_Object)->GEOM_Object #Create advanced objects - Copy = geompy.MakeCopy(Box) #(GEOM_Object)->GEOM_Object Prism = geompy.MakePrismVecH(Face, vz, 100.0) #(2 GEOM_Object, Double)->GEOM_Object Prism2Ways = geompy.MakePrismVecH2Ways(Face, vz, 10.0) #(2 GEOM_Object, Double)->GEOM_Object PrismTwoPnt = geompy.MakePrism(Face2, p0, pxyz) #(3 GEOM_Object)->GEOM_Object @@ -229,6 +228,7 @@ def TestAll (geompy, math): tol2d, tol3d, nbiter) #(GEOM_Object, 4 Doubles, Short)->GEOM_Object Pipe = geompy.MakePipe(Wire, Edge) #(2 GEOM_Object)->GEOM_Object Sewing = geompy.MakeSewing([Face, S], precision) #(List Of GEOM_Object, Double)->GEOM_Object + Copy = geompy.MakeCopy(Box) #(GEOM_Object)->GEOM_Object #Transform objects Translation = geompy.MakeTranslationTwoPoints(Box, px, pz) #(3 GEOM_Object)->GEOM_Object @@ -252,8 +252,8 @@ def TestAll (geompy, math): Position = geompy.MakePosition(Box, cs1, cs2) #(3 GEOM_Object)->GEOM_Object Position2 = geompy.PositionAlongPath(Box, Arc, 0.5, 1, 0) #(2 GEOM_Object, 1 Double, 2 Bool)->GEOM_Object Offset = geompy.MakeOffset(Box, 10.) #(GEOM_Object, Double)->GEOM_Object - Orientation = geompy.ChangeOrientation(Box) ProjOnWire = geompy.MakeProjectionOnWire(p0, Wire) + Orientation = geompy.ChangeOrientation(Box) #IDList for Fillet/Chamfer prism_edges = geompy.ExtractShapes(Prism, geompy.ShapeType["EDGE"], True) @@ -541,4 +541,13 @@ def TestAll (geompy, math): geompy.RestoreSubShapes(Partition, [Box]) geompy.RestoreSubShapes(Partition1) + # GetSubShapeEdgeSorted + p1 = geompy.GetFirstVertex(Sketcher) + p2 = geompy.GetFirstVertex(Sketcher3d_1) + p3 = geompy.GetFirstVertex(Sketcher3d_2) + geompy.GetSubShapeEdgeSorted(Sketcher, p1, "OrderedEdges") + geompy.GetSubShapeEdgeSorted(Sketcher3d_1, p2, "OrderedEdges") + geompy.GetSubShapeEdgeSorted(Sketcher3d_2, p3, "OrderedEdges") + + print "DONE" diff --git a/src/GEOM_SWIG/geomBuilder.py b/src/GEOM_SWIG/geomBuilder.py index 93e6da907..bb6519a93 100644 --- a/src/GEOM_SWIG/geomBuilder.py +++ b/src/GEOM_SWIG/geomBuilder.py @@ -6047,6 +6047,38 @@ class geomBuilder(object, GEOM._objref_GEOM_Gen): self._autoPublish(ListObj, theName, "subshape") return ListObj + ## Explode a shape into edges sorted in a row from a starting point. + # @param theShape the shape to be exploded on edges. + # @param theStartPoint the starting point. + # @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 GEOM.GEOM_Object that is actually an ordered list + # of edges sorted in a row from a starting point. + # + # @ref swig_GetSubShapeEdgeSorted "Example" + @ManageTransactions("ShapesOp") + def GetSubShapeEdgeSorted(self, theShape, theStartPoint, theName=None): + """ + Explode a shape into edges sorted in a row from a starting point. + + Parameters: + theShape the shape to be exploded on edges. + theStartPoint the starting point. + 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. + + Returns: + List of GEOM.GEOM_Object that is actually an ordered list + of edges sorted in a row from a starting point. + """ + # Example: see GEOM_TestAll.py + ListObj = self.ShapesOp.GetSubShapeEdgeSorted(theShape, theStartPoint) + RaiseIfFailed("GetSubShapeEdgeSorted", self.ShapesOp) + self._autoPublish(ListObj, theName, "SortedEdges") + return ListObj + # end of l4_decompose ## @} -- 2.39.2