Salome HOME
Merge ASERIS development.
authorrnv <rnv@opencascade.com>
Tue, 19 Dec 2017 15:56:16 +0000 (18:56 +0300)
committerrnv <rnv@opencascade.com>
Tue, 19 Dec 2017 15:56:16 +0000 (18:56 +0300)
17 files changed:
doc/salome/examples/ex_MakePolyLine.py [new file with mode: 0644]
idl/SMESH_MeshEditor.idl
src/OBJECT/SMESH_Actor.cxx
src/OBJECT/SMESH_ActorDef.h
src/OBJECT/SMESH_DeviceActor.cxx
src/OBJECT/SMESH_DeviceActor.h
src/SMESH/SMESH_MeshEditor.cxx
src/SMESH/SMESH_MeshEditor.hxx
src/SMESHGUI/SMESHGUI_SingleEditDlg.cxx
src/SMESHUtils/SMESH_TryCatch.cxx
src/SMESHUtils/SMESH_TryCatch.hxx
src/SMESH_I/SMESH_MeshEditor_i.cxx
src/SMESH_I/SMESH_MeshEditor_i.hxx
src/SMESH_SWIG/smeshBuilder.py
src/SMESH_SWIG_WITHIHM/libSMESH_Swig.cxx
src/SMESH_SWIG_WITHIHM/libSMESH_Swig.h
src/SMESH_SWIG_WITHIHM/libSMESH_Swig.i

diff --git a/doc/salome/examples/ex_MakePolyLine.py b/doc/salome/examples/ex_MakePolyLine.py
new file mode 100644 (file)
index 0000000..530d39c
--- /dev/null
@@ -0,0 +1,37 @@
+import salome
+salome.salome_init()
+
+### create geometry
+
+from salome.geom import geomBuilder
+geompy = geomBuilder.New(salome.myStudy)
+
+Box_1 = geompy.MakeBoxDXDYDZ(200, 200, 200)
+geompy.addToStudy( Box_1, 'Box_1' )
+
+### create a mesh
+
+import SMESH
+from salome.smesh import smeshBuilder
+smesh = smeshBuilder.New(salome.myStudy)
+
+Mesh_1 = smesh.Mesh( Box_1 )
+Mesh_1.Segment().NumberOfSegments(15)
+Mesh_1.Triangle()
+Mesh_1.Compute()
+
+# define arguments for MakePolyLine
+
+segments = []
+# between nodes 20 and 1, default plane
+segments.append( SMESH.PolySegment( 20, 0, 1, 0, smesh.MakeDirStruct(0,0,0) ))
+# between nodes 1 and 100, default plane
+segments.append( SMESH.PolySegment( 1, 0, 200, 0, smesh.MakeDirStruct(0,0,0) ))
+# between nodes 200 and edge (578, 577), plane includes vector (1,1,1)
+segments.append( SMESH.PolySegment( 200, 0, 578, 577, smesh.MakeDirStruct(1,1,1) ))
+
+Mesh_1.MakePolyLine( segments, "1D group")
+
+
+if salome.sg.hasDesktop():
+  salome.sg.updateObjBrowser(True)
index fd5362cdafea089e9d3388988e137f639ef48b04..9d568ff16c136c2e032e54376c7b06013ae31885 100644 (file)
@@ -57,6 +57,24 @@ module SMESH
   };
 
 
+  // structure used in MakePolyLine() to define a cutting plane
+  struct PolySegment
+  {
+    // point 1: if node1ID2 > 0, then the point is in the middle of a face edge defined
+    //          by two nodes, else it is at node1ID1
+    long node1ID1;
+    long node1ID2;
+
+    // point 2: if node2ID2 > 0, then the point is in the middle of a face edge defined
+    //          by two nodes, else it is at node2ID1
+    long node2ID1;
+    long node2ID2;
+
+    DirStruct vector; // vector on the plane; to use a default plane set vector = (0,0,0)
+  };
+  typedef sequence<PolySegment> ListOfPolySegments;
+
+
   /*!
    * This interface makes modifications on the Mesh - removing elements and nodes etc.
    */
@@ -1208,7 +1226,28 @@ module SMESH
                         in GEOM::GEOM_Object theShape,
                         in string groupName,
                         in double_array theNodesCoords,
-                        out array_of_long_array GroupsOfNodes) 
+                        out array_of_long_array GroupsOfNodes)
+      raises (SALOME::SALOME_Exception);
+
+
+    /*!
+     * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
+     *        the initial mesh. Positions of new nodes are found by cutting the mesh by the
+     *        plane passing through pairs of points specified by each PolySegment structure.
+     *        If there are several paths connecting a pair of points, the shortest path is
+     *        selected by the module. Position of the cutting plane is defined by the two
+     *        points and an optional vector lying on the plane specified by a PolySegment.
+     *        By default the vector is defined by Mesh module as following. A middle point
+     *        of the two given points is computed. The middle point is projected to the mesh.
+     *        The vector goes from the middle point to the projection point. In case of planar
+     *        mesh, the vector is normal to the mesh.
+     *  \param [inout] segments - PolySegment's defining positions of cutting planes.
+     *        Return the used vector which goes from the middle point to its projection.
+     *  \param [in] groupName - optional name of a group where created mesh segments will
+     *        be added.
+     */
+    void MakePolyLine(inout ListOfPolySegments segments,
+                      in    string             groupName)
       raises (SALOME::SALOME_Exception);
   };
 };
index cf9c45312ea226a5f576069249bd5e27a3fe6ab9..6bd4e2c629a2000a66d4db19e085e5136b971abf 100644 (file)
@@ -1438,6 +1438,10 @@ double* SMESH_ActorDef::GetNodeCoord(int theObjID)
   return myPickableActor->GetNodeCoord(theObjID);
 }
 
+int SMESH_ActorDef::GetNodeVtkId(int theObjID)
+{
+  return myPickableActor->GetNodeVtkId(theObjID);
+}
 
 int SMESH_ActorDef::GetElemObjId(int theVtkID)
 {
index dd8879ec6527b3fd4b6965a7eb33e5b66abd2c73..3b9d9c68f97a4de811e5531ed78b268ce4ddf815 100644 (file)
@@ -150,6 +150,7 @@ class SMESH_ActorDef : public SMESH_Actor
 
   virtual int GetNodeObjId(int theVtkID);
   virtual double* GetNodeCoord(int theObjID);
+  virtual int GetNodeVtkId(int theObjID);
 
   virtual int GetElemObjId(int theVtkID);
   virtual vtkCell* GetElemCell(int theObjID);
index cfe6159a2c0e7e4484c444878060473940d275f2..6ef8c4d6112ea2f68167da82ab0ea1e836dae461 100644 (file)
@@ -861,6 +861,12 @@ SMESH_DeviceActor
   return aCoord;
 }
 
+int
+SMESH_DeviceActor
+::GetNodeVtkId(int theObjID) 
+{
+  return myVisualObj->GetNodeVTKId(theObjID);
+}
 
 int
 SMESH_DeviceActor
index 1b8ceb48ebe216b8bca4876a5c0628dd8e6fae6c..30d7c8c42fad16257bb7734e0243be1b8325e84e 100644 (file)
@@ -70,6 +70,7 @@ class SMESHOBJECT_EXPORT SMESH_DeviceActor: public vtkLODActor{
 
   virtual int GetNodeObjId(int theVtkID);
   virtual double* GetNodeCoord(int theObjID);
+  virtual int GetNodeVtkId(int theObjID);
 
   virtual int GetElemObjId(int theVtkID);
   virtual vtkCell* GetElemCell(int theObjID);
index 83066678d521b6a2a14d49571c42920c97972e1c..4d7720381b8ff70019c14cfc43f7dac8c88c0d99 100644 (file)
@@ -96,6 +96,9 @@
 
 #include <Standard_Failure.hxx>
 #include <Standard_ErrorHandler.hxx>
+#include <OSD_Parallel.hxx>
+
+#include "SMESH_TryCatch.hxx" // include after OCCT headers!
 
 #define cast2Node(elem) static_cast<const SMDS_MeshNode*>( elem )
 
@@ -12843,3 +12846,482 @@ void SMESH_MeshEditor::copyPosition( const SMDS_MeshNode* from,
   default:;
   }
 }
+
+namespace // utils for MakePolyLine
+{
+  //================================================================================
+  /*!
+   * \brief Sequence of found points and a current point data
+   */
+  struct Path
+  {
+    std::vector< gp_XYZ >   myPoints;
+    double                  myLength;
+
+    int                     mySrcPntInd; //!< start point index
+    const SMDS_MeshElement* myFace;
+    SMESH_NodeXYZ           myNode1;
+    SMESH_NodeXYZ           myNode2;
+    int                     myNodeInd1;
+    int                     myNodeInd2;
+    double                  myDot1;
+    double                  myDot2;
+    TIDSortedElemSet        myElemSet, myAvoidSet;
+
+    Path(): myLength(0.0), myFace(0) {}
+
+    bool SetCutAtCorner( const SMESH_NodeXYZ&    cornerNode,
+                         const SMDS_MeshElement* face,
+                         const gp_XYZ&           plnNorm,
+                         const gp_XYZ&           plnOrig );
+
+    void AddPoint( const gp_XYZ& p );
+
+    bool Extend( const gp_XYZ& plnNorm, const gp_XYZ& plnOrig );
+
+    bool ReachSamePoint( const Path& other );
+
+    static void Remove( std::vector< Path > & paths, size_t& i );
+  };
+
+  //================================================================================
+  /*!
+   * \brief Return true if this Path meats another
+   */
+  //================================================================================
+
+  bool Path::ReachSamePoint( const Path& other )
+  {
+    return ( mySrcPntInd != other.mySrcPntInd &&
+             myFace == other.myFace );
+  }
+
+  //================================================================================
+  /*!
+   * \brief Remove a path from a vector
+   */
+  //================================================================================
+
+  void Path::Remove( std::vector< Path > & paths, size_t& i )
+  {
+    if ( paths.size() > 1 )
+    {
+      size_t j = paths.size() - 1; // last item to be removed
+      if ( i < j )
+      {
+        paths[ i ].myPoints.swap( paths[ j ].myPoints );
+        paths[ i ].myLength    = paths[ j ].myLength;
+        paths[ i ].mySrcPntInd = paths[ j ].mySrcPntInd;
+        paths[ i ].myFace      = paths[ j ].myFace;
+        paths[ i ].myNode1     = paths[ j ].myNode1;
+        paths[ i ].myNode2     = paths[ j ].myNode2;
+        paths[ i ].myNodeInd1  = paths[ j ].myNodeInd1;
+        paths[ i ].myNodeInd2  = paths[ j ].myNodeInd2;
+        paths[ i ].myDot1      = paths[ j ].myDot1;
+        paths[ i ].myDot2      = paths[ j ].myDot2;
+      }
+    }
+    paths.pop_back();
+    if ( i > 0 )
+      --i;
+  }
+
+  //================================================================================
+  /*!
+   * \brief Store a point that is at a node of a face if the face is intersected by plane.
+   *        Return false if the node is a sole intersection point of the face and the plane
+   */
+  //================================================================================
+
+  bool Path::SetCutAtCorner( const SMESH_NodeXYZ&    cornerNode,
+                             const SMDS_MeshElement* face,
+                             const gp_XYZ&           plnNorm,
+                             const gp_XYZ&           plnOrig )
+  {
+    if ( face == myFace )
+      return false;
+    myNodeInd1 = face->GetNodeIndex( cornerNode._node );
+    myNodeInd2 = ( myNodeInd1 + 1 ) % face->NbCornerNodes();
+    int   ind3 = ( myNodeInd1 + 2 ) % face->NbCornerNodes();
+    myNode1.Set( face->GetNode( ind3 ));
+    myNode2.Set( face->GetNode( myNodeInd2 ));
+
+    myDot1 = plnNorm * ( myNode1 - plnOrig );
+    myDot2 = plnNorm * ( myNode2 - plnOrig );
+
+    bool ok = ( myDot1 * myDot2 < 0 );
+    if ( !ok && myDot1 * myDot2 == 0 )
+    {
+      ok = ( myDot1 != myDot2 );
+      if ( ok && myFace )
+        ok = ( myFace->GetNodeIndex(( myDot1 == 0 ? myNode1 : myNode2 )._node ) < 0 );
+    }
+    if ( ok )
+    {
+      myFace = face;
+      myDot1 = 0;
+      AddPoint( cornerNode );
+    }
+    return ok;
+  }
+
+  //================================================================================
+  /*!
+   * \brief Store a point and update myLength
+   */
+  //================================================================================
+
+  void Path::AddPoint( const gp_XYZ& p )
+  {
+    if ( !myPoints.empty() )
+      myLength += ( p - myPoints.back() ).Modulus();
+    else
+      myLength = 0;
+    myPoints.push_back( p );
+  }
+
+  //================================================================================
+  /*!
+   * \brief Try to find the next point
+   *  \param [in] plnNorm - cutting plane normal
+   *  \param [in] plnOrig - cutting plane origin
+   */
+  //================================================================================
+
+  bool Path::Extend( const gp_XYZ& plnNorm, const gp_XYZ& plnOrig )
+  {
+    int nodeInd3 = ( myNodeInd1 + 1 ) % myFace->NbCornerNodes();
+    if ( myNodeInd2 == nodeInd3 )
+      nodeInd3 = ( myNodeInd1 + 2 ) % myFace->NbCornerNodes();
+
+    SMESH_NodeXYZ node3 = myFace->GetNode( nodeInd3 );
+    double         dot3 = plnNorm * ( node3 - plnOrig );
+
+    if ( dot3 * myDot1 < 0. )
+    {
+      myNode2    = node3;
+      myNodeInd2 = nodeInd3;
+      myDot2     = dot3;
+    }
+    else if ( dot3 * myDot2 < 0. )
+    {
+      myNode1    = node3;
+      myNodeInd1 = nodeInd3;
+      myDot1     = dot3;
+    }
+    else if ( dot3 == 0. )
+    {
+      SMDS_ElemIteratorPtr fIt = node3._node->GetInverseElementIterator(SMDSAbs_Face);
+      while ( fIt->more() )
+        if ( SetCutAtCorner( node3, fIt->next(), plnNorm, plnOrig ))
+          return true;
+      return false;
+    }
+    else if ( myDot2 == 0. )
+    {
+      SMESH_NodeXYZ node2 = myNode2; // copy as myNode2 changes in SetCutAtCorner()
+      SMDS_ElemIteratorPtr fIt = node2._node->GetInverseElementIterator(SMDSAbs_Face);
+      while ( fIt->more() )
+        if ( SetCutAtCorner( node2, fIt->next(), plnNorm, plnOrig ))
+          return true;
+      return false;
+    }
+
+    double r = Abs( myDot1 / ( myDot2 - myDot1 ));
+    AddPoint( myNode1 * ( 1 - r ) + myNode2 * r );
+
+    myAvoidSet.clear();
+    myAvoidSet.insert( myFace );
+    myFace = SMESH_MeshAlgos::FindFaceInSet( myNode1._node, myNode2._node,
+                                             myElemSet,   myAvoidSet,
+                                             &myNodeInd1, &myNodeInd2 );
+    return myFace;
+  }
+
+  //================================================================================
+  /*!
+   * \brief Compute a path between two points of PolySegment
+   */
+  struct PolyPathCompute
+  {
+    SMESH_MeshEditor::TListOfPolySegments& mySegments; //!< inout PolySegment's
+    std::vector< Path >&                   myPaths;    //!< path of each of segments to compute
+    SMESH_Mesh*                            myMesh;
+    mutable std::vector< std::string >     myErrors;
+
+    PolyPathCompute( SMESH_MeshEditor::TListOfPolySegments& theSegments,
+                     std::vector< Path >&                   thePaths,
+                     SMESH_Mesh*                            theMesh):
+      mySegments( theSegments ),
+      myPaths( thePaths ),
+      myMesh( theMesh ),
+      myErrors( theSegments.size() )
+    {
+    }
+#undef SMESH_CAUGHT
+#define SMESH_CAUGHT myErrors[i] =
+    void operator() ( const int i ) const
+    {
+      SMESH_TRY;
+      const_cast< PolyPathCompute* >( this )->Compute( i );
+      SMESH_CATCH( SMESH::returnError );
+    }
+#undef SMESH_CAUGHT
+    //================================================================================
+    /*!
+     * \brief Compute a path of a given segment
+     */
+    //================================================================================
+
+    void Compute( const int iSeg )
+    {
+      SMESH_MeshEditor::PolySegment& polySeg = mySegments[ iSeg ];
+
+      // get a cutting plane
+
+      gp_XYZ p1 = SMESH_NodeXYZ( polySeg.myNode1[0] );
+      gp_XYZ p2 = SMESH_NodeXYZ( polySeg.myNode1[1] );
+      if ( polySeg.myNode2[0] ) p1 = 0.5 * ( p1 + SMESH_NodeXYZ( polySeg.myNode2[0] ));
+      if ( polySeg.myNode2[1] ) p2 = 0.5 * ( p2 + SMESH_NodeXYZ( polySeg.myNode2[1] ));
+
+      gp_XYZ plnNorm = ( p1 - p2 ) ^ polySeg.myVector.XYZ();
+      gp_XYZ plnOrig = p2;
+
+      // find paths connecting the 2 end points of polySeg
+
+      std::vector< Path > paths; paths.reserve(10);
+
+      // initialize paths
+
+      for ( int iP = 0; iP < 2; ++iP ) // loop on the polySeg end points
+      {
+        Path path;
+        path.mySrcPntInd = iP;
+        size_t nbPaths = paths.size();
+
+        if ( polySeg.myNode2[ iP ] && polySeg.myNode2[ iP ] != polySeg.myNode1[ iP ] )
+        {
+          while (( path.myFace = SMESH_MeshAlgos::FindFaceInSet( polySeg.myNode1[ iP ],
+                                                                 polySeg.myNode2[ iP ],
+                                                                 path.myElemSet,
+                                                                 path.myAvoidSet,
+                                                                 &path.myNodeInd1,
+                                                                 &path.myNodeInd2 )))
+          {
+            path.myNode1.Set( polySeg.myNode1[ iP ]);
+            path.myNode2.Set( polySeg.myNode2[ iP ]);
+            path.myDot1 = plnNorm * ( path.myNode1 - plnOrig );
+            path.myDot2 = plnNorm * ( path.myNode2 - plnOrig );
+            path.myPoints.clear();
+            path.AddPoint( 0.5 * ( path.myNode1 + path.myNode2 ));
+            path.myAvoidSet.insert( path.myFace );
+            paths.push_back( path );
+          }
+          if ( nbPaths == paths.size() )
+            throw SALOME_Exception ( SMESH_Comment("No face edge found by point ") << iP+1
+                                     << " in a PolySegment " << iSeg );
+        }
+        else // an end point is at node
+        {
+          std::set<const SMDS_MeshNode* > nodes;
+          SMDS_ElemIteratorPtr fIt = polySeg.myNode1[ iP ]->GetInverseElementIterator(SMDSAbs_Face);
+          while ( fIt->more() )
+          {
+            path.myPoints.clear();
+            if ( path.SetCutAtCorner( polySeg.myNode1[ iP ], fIt->next(), plnNorm, plnOrig ))
+            {
+              if (( path.myDot1 * path.myDot2 != 0 ) ||
+                  ( nodes.insert( path.myDot1 == 0 ? path.myNode1._node : path.myNode2._node ).second ))
+                paths.push_back( path );
+            }
+          }
+        }
+
+        // look for a one-segment path
+        for ( size_t i = 0; i < nbPaths; ++i )
+          for ( size_t j = nbPaths; j < paths.size(); ++j )
+            if ( paths[i].myFace == paths[j].myFace )
+            {
+              myPaths[ iSeg ].myPoints.push_back( paths[i].myPoints[0] );
+              myPaths[ iSeg ].myPoints.push_back( paths[j].myPoints[0] );
+              paths.clear();
+            }
+      }
+
+      // extend paths
+
+      myPaths[ iSeg ].myLength = 1e100;
+
+      while ( paths.size() >= 2 )
+      {
+        for ( size_t i = 0; i < paths.size(); ++i )
+        {
+          Path& path = paths[ i ];
+          if ( !path.Extend( plnNorm, plnOrig ) ||         // path reached a mesh boundary
+               path.myLength > myPaths[ iSeg ].myLength ) // path is longer than others
+          {
+            Path::Remove( paths, i );
+            continue;
+          }
+
+          // join paths that reach same point
+          for ( size_t j = 0; j < paths.size(); ++j )
+          {
+            if ( i != j && paths[i].ReachSamePoint( paths[j] ))
+            {
+              double   distLast = ( paths[i].myPoints.back() - paths[j].myPoints.back() ).Modulus();
+              double fullLength = ( paths[i].myLength + paths[j].myLength + distLast );
+              if ( fullLength < myPaths[ iSeg ].myLength )
+              {
+                myPaths[ iSeg ].myLength = fullLength;
+                std::vector< gp_XYZ > & allPoints = myPaths[ iSeg ].myPoints;
+                allPoints.swap( paths[i].myPoints );
+                allPoints.insert( allPoints.end(),
+                                  paths[j].myPoints.rbegin(),
+                                  paths[j].myPoints.rend() );
+              }
+              Path::Remove( paths, i );
+              Path::Remove( paths, j );
+            }
+          }
+        }
+        if ( !paths.empty() && (int) paths[0].myPoints.size() > myMesh->NbFaces() )
+          throw SALOME_Exception(LOCALIZED( "Infinite loop in MakePolyLine()"));
+      }
+
+      if ( myPaths[ iSeg ].myPoints.empty() )
+        throw SALOME_Exception( SMESH_Comment("Can't find a full path for PolySegment #") << iSeg );
+
+    } // PolyPathCompute::Compute()
+
+  }; // struct PolyPathCompute
+
+} // namespace
+
+//=======================================================================
+//function : MakePolyLine
+//purpose  : Create a polyline consisting of 1D mesh elements each lying on a 2D element of
+//           the initial mesh
+//=======================================================================
+
+void SMESH_MeshEditor::MakePolyLine( TListOfPolySegments&   theSegments,
+                                     SMESHDS_Group*         theGroup,
+                                     SMESH_ElementSearcher* theSearcher)
+{
+  std::vector< Path > segPaths( theSegments.size() ); // path of each of segments
+
+  SMESH_ElementSearcher* searcher = theSearcher;
+  SMESHUtils::Deleter<SMESH_ElementSearcher> delSearcher;
+  if ( !searcher )
+  {
+    searcher = SMESH_MeshAlgos::GetElementSearcher( *GetMeshDS() );
+    delSearcher._obj = searcher;
+  }
+
+  // get cutting planes
+
+  std::vector< bool > isVectorOK( theSegments.size(), true );
+  const double planarCoef = 0.333; // plane height in planar case
+
+  for ( size_t iSeg = 0; iSeg < theSegments.size(); ++iSeg )
+  {
+    PolySegment& polySeg = theSegments[ iSeg ];
+
+    gp_XYZ p1 = SMESH_NodeXYZ( polySeg.myNode1[0] );
+    gp_XYZ p2 = SMESH_NodeXYZ( polySeg.myNode1[1] );
+    if ( polySeg.myNode2[0] ) p1 = 0.5 * ( p1 + SMESH_NodeXYZ( polySeg.myNode2[0] ));
+    if ( polySeg.myNode2[1] ) p2 = 0.5 * ( p2 + SMESH_NodeXYZ( polySeg.myNode2[1] ));
+
+    gp_XYZ plnNorm = ( p1 - p2 ) ^ polySeg.myVector.XYZ();
+
+    isVectorOK[ iSeg ] = ( plnNorm.Modulus() > std::numeric_limits<double>::min() );
+    if ( !isVectorOK[ iSeg ])
+    {
+      gp_XYZ pMid = 0.5 * ( p1 + p2 );
+      const SMDS_MeshElement* face;
+      polySeg.myMidProjPoint = searcher->Project( pMid, SMDSAbs_Face, &face );
+      polySeg.myVector       = polySeg.myMidProjPoint.XYZ() - pMid;
+
+      gp_XYZ faceNorm;
+      SMESH_MeshAlgos::FaceNormal( face, faceNorm );
+
+      if ( polySeg.myVector.Magnitude() < Precision::Confusion() ||
+           polySeg.myVector * faceNorm  < Precision::Confusion() )
+      {
+        polySeg.myVector = faceNorm;
+        polySeg.myMidProjPoint = pMid + faceNorm * ( p1 - p2 ).Modulus() * planarCoef;
+      }
+    }
+    else
+    {
+      polySeg.myVector = plnNorm ^ ( p1 - p2 );
+    }
+  }
+
+  // assure that inverse elements are constructed, avoid their concurrent building in threads
+  GetMeshDS()->nodesIterator()->next()->NbInverseElements();
+
+  // find paths
+
+  PolyPathCompute algo( theSegments, segPaths, myMesh );
+  OSD_Parallel::For( 0, theSegments.size(), algo, theSegments.size() == 1 );
+
+  for ( size_t iSeg = 0; iSeg < theSegments.size(); ++iSeg )
+    if ( !algo.myErrors[ iSeg ].empty() )
+      throw SALOME_Exception( algo.myErrors[ iSeg ].c_str() );
+
+  // create an 1D mesh
+
+  const SMDS_MeshNode *n, *nPrev = 0;
+  SMESHDS_Mesh* mesh = GetMeshDS();
+
+  for ( size_t iSeg = 0; iSeg < theSegments.size(); ++iSeg )
+  {
+    const Path& path = segPaths[iSeg];
+    if ( path.myPoints.size() < 2 )
+      continue;
+
+    double tol = path.myLength / path.myPoints.size() / 1000.;
+    if ( !nPrev || ( SMESH_NodeXYZ( nPrev ) - path.myPoints[0] ).SquareModulus() > tol*tol )
+    {
+      nPrev = mesh->AddNode( path.myPoints[0].X(), path.myPoints[0].Y(), path.myPoints[0].Z() );
+      myLastCreatedNodes.Append( nPrev );
+    }
+    for ( size_t iP = 1; iP < path.myPoints.size(); ++iP )
+    {
+      n = mesh->AddNode( path.myPoints[iP].X(), path.myPoints[iP].Y(), path.myPoints[iP].Z() );
+      myLastCreatedNodes.Append( n );
+
+      const SMDS_MeshElement* elem = mesh->AddEdge( nPrev, n );
+      myLastCreatedElems.Append( elem );
+      if ( theGroup )
+        theGroup->Add( elem );
+
+      nPrev = n;
+    }
+
+    // return a vector
+
+    gp_XYZ pMid = 0.5 * ( path.myPoints[0] + path.myPoints.back() );
+    if ( isVectorOK[ iSeg ])
+    {
+      // find the most distance point of a path
+      double maxDist = 0;
+      for ( size_t iP = 1; iP < path.myPoints.size(); ++iP )
+      {
+        double dist = Abs( theSegments[iSeg].myVector * ( path.myPoints[iP] - path.myPoints[0] ));
+        if ( dist > maxDist )
+        {
+          maxDist = dist;
+          theSegments[iSeg].myMidProjPoint = path.myPoints[iP];
+        }
+      }
+      if ( maxDist < Precision::Confusion() ) // planar case
+        theSegments[iSeg].myMidProjPoint =
+          pMid + theSegments[iSeg].myVector.XYZ().Normalized() * path.myLength * planarCoef;
+    }
+    theSegments[iSeg].myVector = gp_Vec( pMid, theSegments[iSeg].myMidProjPoint );
+  }
+
+  return;
+}
index 3fc13aca6c7bbc28927caf09b9f91d0da05f4b61..1773a1bf6980c605141cbc56f74586c4bfe1f2ed 100644 (file)
 class SMDS_MeshElement;
 class SMDS_MeshFace;
 class SMDS_MeshNode;
+class SMESHDS_Group;
 class SMESHDS_Mesh;
 class SMESHDS_SubMesh;
+class SMESH_ElementSearcher;
 class SMESH_Group;
 class SMESH_Mesh;
 class SMESH_MesherHelper;
@@ -707,6 +709,42 @@ public:
                        bool                    toAddExistingBondary = false,
                        bool                    aroundElements = false);
 
+
+  // structure used in MakePolyLine() to define a cutting plane
+  struct PolySegment
+  {
+    // 2 points: if myNode2 != 0, then the point is the middle of a face edge defined
+    //           by two nodes, else it is at myNode1
+    const SMDS_MeshNode* myNode1[2];
+    const SMDS_MeshNode* myNode2[2];
+
+    gp_Vec myVector; // vector on the plane; to use a default plane set vector = (0,0,0)
+
+    // point to return coordinates of a middle of the two points, projected to mesh
+    gp_Pnt myMidProjPoint;
+  };
+  typedef std::vector<PolySegment> TListOfPolySegments;
+
+  /*!
+   * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
+   *        the initial mesh. Positions of new nodes are found by cutting the mesh by the
+   *        plane passing through pairs of points specified by each PolySegment structure.
+   *        If there are several paths connecting a pair of points, the shortest path is
+   *        selected by the module. Position of the cutting plane is defined by the two
+   *        points and an optional vector lying on the plane specified by a PolySegment.
+   *        By default the vector is defined by Mesh module as following. A middle point
+   *        of the two given points is computed. The middle point is projected to the mesh.
+   *        The vector goes from the middle point to the projection point. In case of planar
+   *        mesh, the vector is normal to the mesh.
+   *  \param [inout] segments - PolySegment's defining positions of cutting planes.
+   *        Return the used vector and position of the middle point.
+   *  \param [in] group - an optional group where created mesh segments will
+   *        be added.
+   */
+  void MakePolyLine( TListOfPolySegments&   segments,
+                     SMESHDS_Group*         group=0,
+                     SMESH_ElementSearcher* searcher=0);
+
  private:
 
   /*!
index 08424f6d49a6d91fe65eae2ac847c5092df9ecf9..3a5e9227ae8e6dd25213c0fbd236a2a5a931259c 100755 (executable)
@@ -22,6 +22,9 @@
 
 // File   : SMESHGUI_SingleEditDlg.cxx
 // Author : Sergey LITONIN, Open CASCADE S.A.S.
+
+#include <SVTK_Selector.h>
+
 // SMESH includes
 //
 #include "SMESHGUI_SingleEditDlg.h"
@@ -42,7 +45,6 @@
 #include <SUIT_Desktop.h>
 #include <SUIT_Session.h>
 
-#include <SVTK_Selector.h>
 #include <SVTK_ViewWindow.h>
 #include <SALOME_ListIO.hxx>
 
@@ -347,9 +349,9 @@ void SMESHGUI_SingleEditDlg::onTextChange (const QString& theNewText)
       aList.Append(anIO);
       mySelectionMgr->setSelectedObjects(aList,false);
       
-      TColStd_IndexedMapOfInteger selectedIndices;
-      TColStd_MapOfInteger newIndices;
-      mySelector->GetIndex(anIO,selectedIndices);
+      SVTK_IndexedMapOfIds selectedIndices;
+      SVTK_ListOfInteger newIndices;
+      mySelector->GetCompositeIndex(anIO,selectedIndices);
 
       int id1, id2;
       if ( !getNodeIds(myEdge->text(), id1, id2) )
@@ -367,25 +369,13 @@ void SMESHGUI_SingleEditDlg::onTextChange (const QString& theNewText)
 
       if ( findTriangles(aNode1,aNode2,tria1,tria2) )
       {
-        newIndices.Add(tria1->GetID());
-
-        const SMDS_MeshNode* a3Nodes[3];
-        SMDS_ElemIteratorPtr it;
-        int edgeInd = 2, i;
-        for (i = 0, it = tria1->nodesIterator(); it->more(); i++) {
-          a3Nodes[ i ] = static_cast<const SMDS_MeshNode*>(it->next());
-          if (i > 0 && ( (a3Nodes[ i ] == aNode1 && a3Nodes[ i - 1] == aNode2) ||
-                         (a3Nodes[ i ] == aNode2 && a3Nodes[ i - 1] == aNode1) ) ) {
-            edgeInd = i - 1;
-            break;
-          }
-        }
-        newIndices.Add(-edgeInd-1);
+       newIndices.push_back( aNode1->GetID() );
+       newIndices.push_back( aNode2->GetID() );
         
         myOkBtn->setEnabled(true);
         myApplyBtn->setEnabled(true);
       }
-      mySelector->AddOrRemoveIndex(anIO,newIndices, false);
+      mySelector->AddOrRemoveCompositeIndex(anIO, newIndices, false);
       SMESH::GetViewWindow(mySMESHGUI)->highlight( anIO, true, true );
     }
   }
@@ -420,7 +410,17 @@ void SMESHGUI_SingleEditDlg::onSelectionDone()
     if(SMDS_Mesh* aMesh = aVisualObj->GetMesh())
     {
       const SMDS_MeshElement* tria[2];
-      if( SMESH::GetEdgeNodes( mySelector, aVisualObj, anId1, anId2 ) >= 1 &&
+      
+      bool valid = false;      
+      SVTK_IndexedMapOfIds anIds;
+      mySelector->GetCompositeIndex(anIO,anIds);
+      if( anIds.Extent() == 1 && anIds(1).size() == 2 ) {
+       anId1 = anIds(1)[0];
+       anId2 = anIds(1)[1];
+       valid = true;
+      }
+             
+      if( valid &&
           findTriangles( aMesh->FindNode( anId1 ), aMesh->FindNode( anId2 ), tria[0],tria[1] ) )
       {
         QString aText = QString("%1-%2").arg(anId1).arg(anId2);
@@ -523,6 +523,7 @@ bool SMESHGUI_SingleEditDlg::onApply()
   // update actor
   if (aResult) {
     mySelector->ClearIndex();
+    mySelector->ClearCompositeIndex();
     mySelectionMgr->setSelectedObjects(aList, false);
     onSelectionDone();
     SMESH::UpdateView();
index 1f987213a6fd97314b8898215c6e4fce757e3e8d..71e587caa6f566ecb4432640588176d0a7475bfc 100644 (file)
@@ -32,6 +32,12 @@ void SMESH::doNothing(const char* txt)
 {
   MESSAGE( txt << " " << __FILE__ << ": " << __LINE__ );
 }
+
+const char* SMESH::returnError(const char* txt)
+{
+  return txt;
+}
+
 // ------------------------------------------------------------------
 #include "SMESH_ComputeError.hxx"
 
index 44047a694d54aa70b71ece72df8df0430ca468c5..9e5ffd755c71baa871d4418feee5f2d73d2afb8b 100644 (file)
@@ -107,6 +107,7 @@ namespace SMESH
 {
   SMESHUtils_EXPORT void throwSalomeEx(const char* txt);
   SMESHUtils_EXPORT void doNothing(const char* txt);
+  SMESHUtils_EXPORT const char* returnError(const char* txt);
 }
 
 #endif
index 9a0f20ff74e3dd97313b087219878de167a02d0c..de17f879550e4fcc65a85394f04a35bd69f81797 100644 (file)
@@ -6957,3 +6957,130 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
   SMESH_CATCH( SMESH::throwCorbaException );
   return 0;
 }
+
+//================================================================================
+/*!
+ * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
+ *        the initial mesh. Positions of new nodes are found by cutting the mesh by the
+ *        plane passing through pairs of points specified by each PolySegment structure.
+ *        If there are several paths connecting a pair of points, the shortest path is
+ *        selected by the module. Position of the cutting plane is defined by the two
+ *        points and an optional vector lying on the plane specified by a PolySegment.
+ *        By default the vector is defined by Mesh module as following. A middle point
+ *        of the two given points is computed. The middle point is projected to the mesh.
+ *        The vector goes from the middle point to the projection point. In case of planar
+ *        mesh, the vector is normal to the mesh.
+ *  \param [inout] segments - PolySegment's defining positions of cutting planes.
+ *        Return the used vector and position of the middle point.
+ *  \param [in] groupName - optional name of a group where created mesh segments will
+ *        be added.
+ */
+//================================================================================
+
+void SMESH_MeshEditor_i::MakePolyLine(SMESH::ListOfPolySegments& theSegments,
+                                      const char*                theGroupName)
+  throw (SALOME::SALOME_Exception)
+{
+  if ( theSegments.length() == 0 )
+    THROW_SALOME_CORBA_EXCEPTION("No segments given", SALOME::BAD_PARAM );
+  if ( myMesh->NbFaces() == 0 )
+    THROW_SALOME_CORBA_EXCEPTION("No faces in the mesh", SALOME::BAD_PARAM );
+
+  SMESH_TRY;
+  initData(/*deleteSearchers=*/false);
+
+  SMESHDS_Group* groupDS = 0;
+  SMESHDS_Mesh*   meshDS = getMeshDS();
+  if ( myIsPreviewMode ) // copy faces to the tmp mesh
+  {
+    TPreviewMesh * tmpMesh = getPreviewMesh( SMDSAbs_Edge );
+    SMDS_ElemIteratorPtr faceIt = getMeshDS()->elementsIterator( SMDSAbs_Face );
+    while ( faceIt->more() )
+      tmpMesh->Copy( faceIt->next() );
+    meshDS = tmpMesh->GetMeshDS();
+  }
+  else if ( theGroupName[0] ) // find/create a group of segments
+  {
+    SMESH_Mesh::GroupIteratorPtr grpIt = myMesh->GetGroups();
+    while ( !groupDS && grpIt->more() )
+    {
+      SMESH_Group* group = grpIt->next();
+      if ( group->GetGroupDS()->GetType() == SMDSAbs_Edge &&
+           strcmp( group->GetName(), theGroupName ) == 0 )
+      {
+        groupDS = dynamic_cast< SMESHDS_Group* >( group->GetGroupDS() );
+      }
+    }
+    if ( !groupDS )
+    {
+      SMESH::SMESH_Group_var groupVar = myMesh_i->CreateGroup( SMESH::EDGE, theGroupName );
+
+      if ( SMESH_Group_i* groupImpl = SMESH::DownCast<SMESH_Group_i*>( groupVar ))
+        groupDS = dynamic_cast< SMESHDS_Group* >( groupImpl->GetGroupDS() );
+    }
+  }
+
+  // convert input polySegments
+  ::SMESH_MeshEditor::TListOfPolySegments segments( theSegments.length() );
+  for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
+  {
+    SMESH::PolySegment&               segIn = theSegments[ i ];
+    ::SMESH_MeshEditor::PolySegment& segOut = segments[ i ];
+    segOut.myNode1[0] = meshDS->FindNode( segIn.node1ID1 );
+    segOut.myNode2[0] = meshDS->FindNode( segIn.node1ID2 );
+    segOut.myNode1[1] = meshDS->FindNode( segIn.node2ID1 );
+    segOut.myNode2[1] = meshDS->FindNode( segIn.node2ID2 );
+    segOut.myVector.SetCoord( segIn.vector.PS.x,
+                              segIn.vector.PS.y,
+                              segIn.vector.PS.z );
+    if ( !segOut.myNode1[0] )
+      THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID: ") << segIn.node1ID1,
+                                    SALOME::BAD_PARAM );
+    if ( !segOut.myNode1[1] )
+      THROW_SALOME_CORBA_EXCEPTION( SMESH_Comment( "Invalid node ID: ") << segIn.node2ID1,
+                                    SALOME::BAD_PARAM );
+  }
+
+  // get a static ElementSearcher
+  SMESH::SMESH_IDSource_var idSource = SMESH::SMESH_IDSource::_narrow( myMesh_i->_this() );
+  theSearchersDeleter.Set( myMesh, getPartIOR( idSource, SMESH::FACE ));
+  if ( !theElementSearcher )
+    theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS() );
+
+  // compute
+  getEditor().MakePolyLine( segments, groupDS, theElementSearcher );
+
+  // return vectors
+  if ( myIsPreviewMode )
+  {
+    for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
+    {
+      SMESH::PolySegment&             segOut = theSegments[ i ];
+      ::SMESH_MeshEditor::PolySegment& segIn = segments[ i ];
+      segOut.vector.PS.x = segIn.myVector.X();
+      segOut.vector.PS.y = segIn.myVector.Y();
+      segOut.vector.PS.z = segIn.myVector.Z();
+    }
+  }
+  else
+  {
+    TPythonDump() << "_segments = []";
+    for ( CORBA::ULong i = 0; i < theSegments.length(); ++i )
+    {
+      SMESH::PolySegment& segIn = theSegments[ i ];
+      TPythonDump() << "_segments.append( SMESH.PolySegment( "
+                    << segIn.node1ID1 << ", "
+                    << segIn.node1ID2 << ", "
+                    << segIn.node2ID1 << ", "
+                    << segIn.node2ID2 << ", "
+                    << "smeshBuilder.MakeDirStruct( "
+                    << segIn.vector.PS.x << ", "
+                    << segIn.vector.PS.y << ", "
+                    << segIn.vector.PS.z << ")))";
+    }
+    TPythonDump() << this << ".MakePolyLine( _segments, '" << theGroupName << "')";
+  }
+  meshDS->Modified();
+  SMESH_CATCH( SMESH::throwCorbaException );
+  return;
+}
index 5eaa5ee798d25b8312c6d640b2b23c69268c4b7e..bcc0dfc64393f0eb06c0833b3f579b64cef59c8a 100644 (file)
@@ -840,7 +840,7 @@ public:
                       const char* groupName,
                       const SMESH::double_array& theNodesCoords,
                       SMESH::array_of_long_array_out GroupsOfNodes)
-  throw (SALOME::SALOME_Exception);
+    throw (SALOME::SALOME_Exception);
 
   /*!
    * \brief Generated skin mesh (containing 2D cells) from 3D mesh
@@ -868,7 +868,28 @@ public:
                                    SMESH::SMESH_Group_out group)
     throw (SALOME::SALOME_Exception);
 
-private: //!< private methods
+  /*!
+   * \brief Create a polyline consisting of 1D mesh elements each lying on a 2D element of
+   *        the initial mesh. Positions of new nodes are found by cutting the mesh by the
+   *        plane passing through pairs of points specified by each PolySegment structure.
+   *        If there are several paths connecting a pair of points, the shortest path is
+   *        selected by the module. Position of the cutting plane is defined by the two
+   *        points and an optional vector lying on the plane specified by a PolySegment.
+   *        By default the vector is defined by Mesh module as following. A middle point
+   *        of the two given points is computed. The middle point is projected to the mesh.
+   *        The vector goes from the middle point to the projection point. In case of planar
+   *        mesh, the vector is normal to the mesh.
+   *  \param [inout] segments - PolySegment's defining positions of cutting planes.
+   *        Return the used vector and position of the middle point.
+   *  \param [in] groupName - optional name of a group where created mesh segments will
+   *        be added.
+   */
+  void MakePolyLine(SMESH::ListOfPolySegments& segments,
+                    const char*               groupName)
+    throw (SALOME::SALOME_Exception);
+
+
+ private: //!< private methods
 
   ::SMESH_MeshEditor& getEditor();
 
index 6e0f59579baa41d3aac4cd8947262b06f25d36eb..9e30399e4040110adc075d2f95d97f02fd8f08d3 100644 (file)
@@ -4974,6 +4974,32 @@ class Mesh:
     def CreateHoleSkin(self, radius, theShape, groupName, theNodesCoords):
         return self.editor.CreateHoleSkin( radius, theShape, groupName, theNodesCoords )
 
+    ## Create a polyline consisting of 1D mesh elements each lying on a 2D element of
+    #  the initial mesh. Positions of new nodes are found by cutting the mesh by the
+    #  plane passing through pairs of points specified by each PolySegment structure.
+    #  If there are several paths connecting a pair of points, the shortest path is
+    #  selected by the module. Position of the cutting plane is defined by the two
+    #  points and an optional vector lying on the plane specified by a PolySegment.
+    #  By default the vector is defined by Mesh module as following. A middle point
+    #  of the two given points is computed. The middle point is projected to the mesh.
+    #  The vector goes from the middle point to the projection point. In case of planar
+    #  mesh, the vector is normal to the mesh.
+    #  @param segments - PolySegment's defining positions of cutting planes.
+    #         Return the used vector which goes from the middle point to its projection.
+    #  @param groupName - optional name of a group where created mesh segments will
+    #         be added.
+    #  @ingroup l2_modif_duplicat
+    def MakePolyLine(self, segments, groupName='', isPreview=False ):
+        editor = self.editor
+        if isPreview:
+            editor = self.mesh.GetMeshEditPreviewer()
+        segmentsRes = editor.MakePolyLine( segments, groupName )
+        for i, seg in enumerate( segmentsRes ):
+            segments[i].vector = seg.vector
+        if isPreview:
+            return editor.GetPreviewData()
+        return None        
+
     ## Return a cached numerical functor by its type.
     #  @param theCriterion functor type - an item of SMESH.FunctorType enumeration.
     #          Type SMESH.FunctorType._items in the Python Console to see all items.
index 0a111304ec6e22945118c471f05f8211e9701878..e5a7aeeb068b838349bca1e1a913d45b8a99ec4b 100644 (file)
@@ -24,6 +24,7 @@
 //
 #include "libSMESH_Swig.h"
 
+#include <SVTK_Selector.h>
 
 #include <SMESHGUI.h>
 #include <SMESHGUI_Utils.h>
@@ -820,6 +821,25 @@ void SMESH_Swig::EraseActor( const char* Mesh_Entry, const bool allViewers )
   ProcessVoidEvent(new TEvent(Mesh_Entry, allViewers));
 }
 
+void SMESH_Swig::UpdateActor( const char* Mesh_Entry ) {
+  class TEvent: public SALOME_Event
+  {
+  private:
+    const char* _entry;
+  public:
+    TEvent( const char* Mesh_Entry ) {
+      _entry = Mesh_Entry;
+    }
+    virtual void Execute() {
+      Handle(SALOME_InteractiveObject) anIO = new SALOME_InteractiveObject
+        ( _entry, "SMESH", "" );
+      SMESH::Update( anIO, true );
+    }
+  };
+
+  ProcessVoidEvent( new TEvent(Mesh_Entry) );
+}
+
 void SMESH_Swig::SetName(const char* theEntry,
                          const char* theName)
 {
@@ -962,6 +982,78 @@ void SMESH_Swig::select( const char* id, int id1, bool append ) {
   ProcessVoidEvent( new TSelectListEvent( id, ids, append ) );
 }
 
+/*!
+  \brief Helper class for selection edges of cell event
+*/
+class TSelectListOfPairEvent: public SALOME_Event
+{
+  const char*                        myId;
+  std::vector<std::pair<int, int> >  myIdsList;
+  bool                               myIsAppend;
+
+public:
+  TSelectListOfPairEvent(const char* id, std::vector<std::pair<int, int> > ids, bool append) :
+    myId(id),
+    myIdsList(ids),
+    myIsAppend(append)
+  {}
+  virtual void Execute()
+  {
+    
+    LightApp_SelectionMgr* selMgr = 0;
+    SalomeApp_Application* anApp = dynamic_cast<SalomeApp_Application*>( SUIT_Session::session()->activeApplication() );
+    if( anApp )
+      selMgr = dynamic_cast<LightApp_SelectionMgr*>( anApp->selectionMgr() );
+
+    if( !selMgr )
+      return;
+    
+    selMgr->clearFilters();
+
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow();
+    if(!aViewWindow)
+      return;
+
+    SMESH_Actor* anActor = SMESH::FindActorByEntry( myId );
+    
+    if (!anActor || !anActor->hasIO())
+      return;
+    
+    Handle(SALOME_InteractiveObject) anIO = anActor->getIO();
+    SALOME_ListIO aList;
+    aList.Append(anIO);
+    selMgr->setSelectedObjects(aList, false);
+
+    if ( aViewWindow->SelectionMode() !=  EdgeOfCellSelection ) {
+      return;
+    }
+        
+    SVTK_IndexedMapOfIds aMap;
+    std::vector<std::pair<int, int> >::const_iterator anIter;
+    for (anIter = myIdsList.begin(); anIter != myIdsList.end(); ++anIter) {
+      std::vector<int> aCompositeId;
+      aCompositeId.push_back((*anIter).first);
+      aCompositeId.push_back((*anIter).second);
+      aMap.Add(aCompositeId);
+    }
+
+    // Set new selection
+    SVTK_Selector* aSelector  = aViewWindow->GetSelector();
+    aSelector->AddOrRemoveCompositeIndex(anIO, aMap, myIsAppend);
+    aViewWindow->highlight( anIO, true, true );
+    aViewWindow->GetInteractor()->onEmitSelectionChanged();
+  }
+};
+
+/*!
+  \brief Select the elements on the mesh, sub-mesh or group.
+  \param id object entry
+  \param ids list of the element ids
+  \param mode selection mode
+*/
+void SMESH_Swig::select( const char* id, std::vector<std::pair<int,int> > ids, bool append ) {
+  ProcessVoidEvent( new TSelectListOfPairEvent( id, ids, append ) );
+}
 
 class TGetSelectionModeEvent : public SALOME_Event
 {
@@ -1069,3 +1161,46 @@ public:
 std::vector<int> SMESH_Swig::getSelected( const char* Mesh_Entry ) {
   return ProcessEvent( new TGetSelectedEvent(Mesh_Entry) );
 }
+
+class TGetSelectedPairEvent : public SALOME_Event
+{
+public:
+  typedef std::vector<std::pair<int, int> > TResult;
+  TResult myResult;
+  const char* myId;
+  
+  TGetSelectedPairEvent( const char* id) : 
+    myResult( std::vector<std::pair<int,int> >() ),
+    myId(id)
+  {}
+  
+  virtual void Execute()
+  {
+    SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow();
+    if( !aViewWindow )
+      return;
+
+    if(aViewWindow->SelectionMode() != EdgeOfCellSelection )
+      return;
+
+    SVTK_Selector* aSelector  = aViewWindow->GetSelector();    
+    if( !aSelector )
+      return;
+
+    SMESH_Actor* anActor = SMESH::FindActorByEntry( myId );
+    
+    if ( !anActor || !anActor->hasIO() )
+      return;
+
+    SVTK_IndexedMapOfIds aMapIndex;
+    aSelector->GetCompositeIndex(anActor->getIO(),aMapIndex);
+
+    for( int i = 1; i <= aMapIndex.Extent(); i++ )
+      myResult.push_back( std::make_pair<int,int>( (int)aMapIndex( i )[0], (int)aMapIndex( i )[1]) );
+  }
+};
+
+std::vector<std::pair<int,int> > SMESH_Swig::getSelectedEdgeOfCell( const char* Mesh_Entry ) {
+  return ProcessEvent( new TGetSelectedPairEvent(Mesh_Entry) );
+}
+
index 5522e95a219589618616afe3caf3ba781a8f6f43..931614c1ef0082a5216bb505475e78dfafc3e329 100644 (file)
@@ -40,6 +40,7 @@
 
 //std includes
 #include <vector>
+#include <utility>
 
 #include <SVTK_Selection.h>
 
@@ -119,6 +120,8 @@ public:
 
   void                       EraseActor( const char*, const bool allViewers = false );
 
+  void                       UpdateActor( const char* Mesh_Entry );
+
   /*!
    * \brief Set mesh icon according to compute status
     * \param Mesh_Entry - entry of a mesh
@@ -131,11 +134,13 @@ public:
 
   void setSelectionMode( SelectionMode selectionMode );
   std::vector<int> getSelected( const char* Mesh_Entry );
+  std::vector<std::pair<int, int> > getSelectedEdgeOfCell( const char* Mesh_Entry );
 
   // --------------------- for the test purposes -----------------------
   SelectionMode getSelectionMode();
   void select( const char *id, std::vector<int> ids, bool append = false );
   void select( const char *id, int id1, bool append = false );
+  void select( const char *id, std::vector<std::pair<int,int> >, bool apend = false );
 
 private:
   SALOMEDS::Study_var        myStudy;
index 339668801d7b8402ef44207d911f9e18c723c593..cb5cc2200bfb49789f0875b97a17e5fd0c593de4 100644 (file)
 
 %include "typemaps.i"
 %include "std_vector.i"
+%include "std_pair.i"
 
 namespace std {
+  
     %template(VectorInt) vector<int>;
+    %template() std::pair<int,int>;
+    %template(PairVector) std::vector<std::pair<int,int> >;
 };
 
 
@@ -128,6 +132,11 @@ class SMESH_Swig
 
   void CreateAndDisplayActor( const char* Mesh_Entry );
   void EraseActor( const char* Mesh_Entry, const bool allViewers = false );
+  void UpdateActor( const char* Mesh_Entry );
+
+  void setSelectionMode( SelectionMode selectionMode);
+  std::vector<int> getSelected( const char* Mesh_Entry );
+  std::vector<std::pair<int,int> > getSelectedEdgeOfCell( const char* Mesh_Entry );
 
   actorAspect GetActorAspect(const char* Mesh_Entry, int viewId = 0 );
   void SetActorAspect( const actorAspect& actorPres, const char* Mesh_Entry, int viewId = 0 );
@@ -139,5 +148,6 @@ class SMESH_Swig
   SelectionMode  getSelectionMode();
   void select( const char *id, std::vector<int> ids, bool append = false );
   void select( const char *id, int id1, bool append = false );
+  void select( const char *id, std::vector<std::pair<int,int> >, bool apend = false );
 
 };