--- /dev/null
+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)
};
+ // 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.
*/
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);
};
};
return myPickableActor->GetNodeCoord(theObjID);
}
+int SMESH_ActorDef::GetNodeVtkId(int theObjID)
+{
+ return myPickableActor->GetNodeVtkId(theObjID);
+}
int SMESH_ActorDef::GetElemObjId(int theVtkID)
{
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);
return aCoord;
}
+int
+SMESH_DeviceActor
+::GetNodeVtkId(int theObjID)
+{
+ return myVisualObj->GetNodeVTKId(theObjID);
+}
int
SMESH_DeviceActor
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);
#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 )
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;
+}
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;
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:
/*!
// File : SMESHGUI_SingleEditDlg.cxx
// Author : Sergey LITONIN, Open CASCADE S.A.S.
+
+#include <SVTK_Selector.h>
+
// SMESH includes
//
#include "SMESHGUI_SingleEditDlg.h"
#include <SUIT_Desktop.h>
#include <SUIT_Session.h>
-#include <SVTK_Selector.h>
#include <SVTK_ViewWindow.h>
#include <SALOME_ListIO.hxx>
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) )
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 );
}
}
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);
// update actor
if (aResult) {
mySelector->ClearIndex();
+ mySelector->ClearCompositeIndex();
mySelectionMgr->setSelectedObjects(aList, false);
onSelectionDone();
SMESH::UpdateView();
{
MESSAGE( txt << " " << __FILE__ << ": " << __LINE__ );
}
+
+const char* SMESH::returnError(const char* txt)
+{
+ return txt;
+}
+
// ------------------------------------------------------------------
#include "SMESH_ComputeError.hxx"
{
SMESHUtils_EXPORT void throwSalomeEx(const char* txt);
SMESHUtils_EXPORT void doNothing(const char* txt);
+ SMESHUtils_EXPORT const char* returnError(const char* txt);
}
#endif
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;
+}
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
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();
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.
//
#include "libSMESH_Swig.h"
+#include <SVTK_Selector.h>
#include <SMESHGUI.h>
#include <SMESHGUI_Utils.h>
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)
{
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
{
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) );
+}
+
//std includes
#include <vector>
+#include <utility>
#include <SVTK_Selection.h>
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
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;
%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> >;
};
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 );
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 );
};