SET(${PROJECT_NAME_UC}_PATCH_VERSION 0)
SET(${PROJECT_NAME_UC}_VERSION
${${PROJECT_NAME_UC}_MAJOR_VERSION}.${${PROJECT_NAME_UC}_MINOR_VERSION}.${${PROJECT_NAME_UC}_PATCH_VERSION})
-SET(${PROJECT_NAME_UC}_VERSION_DEV 0)
+SET(${PROJECT_NAME_UC}_VERSION_DEV 1)
# Common CMake macros
# ===================
--- /dev/null
+# Creating groups of faces separated by sharp edges
+
+import salome
+salome.salome_init()
+from salome.geom import geomBuilder
+from salome.smesh import smeshBuilder
+geompy = geomBuilder.New()
+smesh = smeshBuilder.New()
+
+# create a mesh on a box
+box = geompy.MakeBoxDXDYDZ( 10,10,10, theName="Box" )
+mesh = smesh.Mesh(box,"Mesh")
+mesh.AutomaticHexahedralization()
+
+# create groups of faces of each side of the box
+groups = mesh.FaceGroupsSeparatedByEdges( 89 )
--- /dev/null
+# Angle measurement
+
+
+import salome
+salome.salome_init()
+from salome.smesh import smeshBuilder
+smesh = smeshBuilder.New()
+
+# use smeshBuilder.GetAngle() to compute angle between 3 arbitrary points
+
+p0 = [1,0,0]
+p1 = [0,0,0]
+p2 = [0,1,0]
+
+a1 = smesh.GetAngle(p0, p1, p2)
+print("Right angle measure", a1 )
+
+# use Mesh.GetAngle() to compute angle between 3 nodes of a mesh
+
+mesh = smesh.Mesh()
+n0 = mesh.AddNode( *p0 )
+n1 = mesh.AddNode( *p1 )
+n2 = mesh.AddNode( *p2 )
+
+a2 = mesh.GetAngle( n0,n1,n2 )
+
grouping_elements_ex06.py
grouping_elements_ex07.py
grouping_elements_ex08.py
+ grouping_elements_ex09.py
measurements_ex01.py
measurements_ex02.py
+ measurements_ex03.py
+ measurements_ex04.py
modifying_meshes_ex01.py
modifying_meshes_ex02.py
modifying_meshes_ex03.py
The type of each new group is defined automatically by the nature of the **Geometry**.
The group names will be the same as the names of geometrical objects.
-.. warning:: It's impossible to create a group of *0D elements* or *ball elements* with this operation. For this, it is necessary to use :ref:`Create group <creating_groups_page>` operation.
-
To use this operation, select in the **Mesh** menu or in the contextual menu in the Object browser **Create Groups from Geometry** item.
.. image:: ../images/create_groups_from_geometry.png
--- /dev/null
+************************************
+Face Groups Separated By Sharp Edges
+************************************
+
+**Face groups separated by sharp edges** operation distributes all faces of the mesh among groups using sharp edges and optionally existing 1D elements as group boundaries. Edges where more than two faces meet are always considered as a group boundary. The operation is available in **Mesh** menu.
+
+The operation dialog looks as follows:
+
+.. image:: ../images/groups_by_sharp_edges_dlg.png
+ :align: center
+
+In this dialog box specify
+
+ * **Mesh** including the faces to distribute among groups.
+ * **Sharp angle** in degrees, by which edges used as group boundaries are detected. An edge is considered as a group boundary if an angle between normals of adjacent faces is more than this angle.
+ * Activate **Create edges** option if you wish that 1D elements to be created (if not yet exist) on the edges that served as group boundaries.
+ * Activate **Use existing edges** option if you wish that existing 1D elements to be used as group boundaries.
+ * Activate **Preview** to see the edges that will be used as group boundaries highlighted in the Viewer.
+
+
+.. image:: ../images/Nut_sharp_edges.png
+ :align: center
+
+.. centered::
+ **Preview of boundary edges detected at Sharp Angle = 10 degrees**
+
+**See Also** a sample TUI Script of a :ref:`tui_groups_by_sharp_edges` operation.
+
+
* :ref:`Create group <creating_groups_page>` dialog allows creation of a group of any type: :ref:`Standalone group<standalone_group>`, :ref:`Group on geometry <group_on_geom>` and :ref:`Group on filter <group_on_filter>` using dedicated tabs.
* :ref:`Create Groups from Geometry <create_groups_from_geometry_page>` dialog allows creation of several groups on geometry at once.
+* :doc:`face_groups_by_sharp_edges` operation distributes all faces of the mesh among groups using sharp edges and/or existing 1D elements as group boundaries.
* Standalone groups of all nodes and elements of the chosen sub-mesh (type of elements depends on dimension of sub-mesh geometry) can be created using **Mesh -> Construct Group** menu item (available from the context menu as well).
* Standalone groups of any element type can be created basing on nodes of other groups - using :ref:`Group based on nodes of other groups <group_of_underlying_elements_page>` dialog.
* Standalone groups can be created by applying :ref:`Boolean operations <using_operations_on_groups_page>` to other groups.
An important tool, providing filters for creation of standalone groups and groups on filter is :ref:`selection_filter_library_page`.
+**See Also** sample TUI Scripts of :doc:`tui_grouping_elements` operations.
+
+
**Table of Contents**
.. toctree::
creating_groups.rst
create_groups_from_geometry.rst
+ face_groups_by_sharp_edges.rst
group_of_underlying_elements.rst
using_operations_on_groups.rst
editing_groups.rst
In MESH there is a functionality allowing import/export of meshes in the following formats:
* **MED**,
+* **SAUV** (format of the CASTEM code),
* **UNV** (I-DEAS 10),
-* **DAT** (simple ascii format),
* **STL**,
+* **CGNS**,
* **GMF** (internal format of DISTENE products from the MeshGems suite),
-* **CGNS**.
+* **DAT** (simple ascii format).
You can also export a group as a whole mesh.
* **Don't show this warning anymore** check-box allows to switch off the warning. You can re-activate the warning in :ref:`Preferences <group_export_warning_pref>`.
+Only MED format supports all types of elements that can be created in the module. If you export a mesh or group that includes elements of types that are not supported by chosen format, you will be warned about that.
+
There are additional parameters available at export to MED and SAUV format files.
.. _export_auto_groups:
+* **Z tolerance** field if enabled specifies distance of nodes from the XOY plane below which the nodes snap to this plane. A default value can be set in :ref:`Preferences <medexport_z_tolerance_pref>`.
* **Automatically create groups** check-box specifies whether to create groups of all mesh entities of available dimensions or not. The created groups have names like "Group_On_All_Nodes", "Group_On_All_Faces", etc. A default state of this check-box can be set in :ref:`Preferences <export_auto_groups_pref>`.
* **Automatically define space dimension** check-box specifies whether to define space dimension for export by mesh configuration or not. Usually the mesh is exported as a mesh in 3D space, just as it is in Mesh module. The mesh can be exported as a mesh of a lower dimension in the following cases, provided that this check-box is checked:
* As calculation result is a sum of lengths, areas and volumes of all mesh elements, the duplication is not taken into account; i.e. all duplicated elements (elements built on the same set of nodes) will be included into the result.
* Similarly, intersection of elements is not taken into account.
-**See Also** a sample TUI Script of :ref:`tui_measurements_page`.
+.. _angle_anchor:
+
+Angle
+#####
+This operation measures angle defined by three nodes. The second of the specified nodes is a vertex of angle.
+You can specify nodes either by clicking them in the Viewer or by typing their IDs in **Tree nodes** field. If the nodes are correctly specified, upon pressing **Compute** button the angle measure will be displayed and the angle will be shown in the Viewer.
+
+.. image:: ../images/angle_measure.png
+ :align: center
+
+
+**See Also** a sample TUI Script of :ref:`tui_measurements_page`.
.. _display_mode_pref:
-* **Display mode**
+* **Display**
+
+ * **Fit All upon Show Only** - if activated, *Show Only* command additionally performs *Fit All* command.
* **Default display mode** - allows to set Wireframe, Shading, Nodes or Shrink :ref:`presentation mode <display_mode_page>` as default.
* **Show warning when exporting group** - if activated, a warning is displayed when exporting a group.
+.. _medexport_z_tolerance_pref:
+
+ * **Z tolerance for MED export** - defines Z tolerance in :ref:`MED Export <export_auto_groups>` dialog.
+
.. _show_comp_result_pref:
* **Mesh computation**
Mesh.MakeGroupByCriterion
Mesh.MakeGroupByCriteria
Mesh.MakeGroupByFilter
+ Mesh.FaceGroupsSeparatedByEdges
Mesh.GetGroups
Mesh.NbGroups
Mesh.GetGroupNames
smeshBuilder.GetLength
smeshBuilder.GetArea
smeshBuilder.GetVolume
+ smeshBuilder.GetAngle
Mesh.GetFreeBorders
Mesh.MinDistance
Mesh.GetMinDistance
Mesh.GetLength
Mesh.GetArea
Mesh.GetVolume
+ Mesh.GetAngle
****************
Modifying meshes
.. py:class:: SMESH_MeshEditor.Sew_Error
- Enumeration of errors SMESH_MeshEditor.Sewing... methods
+ Enumeration of errors of SMESH_MeshEditor.Sewing... methods
.. py:attribute::
SEW_OK
-.. _tui_grouping_elements_page:
-
*****************
Grouping Elements
*****************
.. image:: ../images/dimgroup_tui1.png
:align: center
+Creating face groups separated by sharp edges
+=============================================
+.. literalinclude:: ../../../examples/grouping_elements_ex09.py
+ :language: python
-
-
+:download:`Download this script <../../../examples/grouping_elements_ex09.py>`
:language: python
:download:`Download this script <../../../examples/measurements_ex03.py>`
+
+Angle
+=====
+
+.. literalinclude:: ../../../examples/measurements_ex04.py
+ :language: python
+
+:download:`Download this script <../../../examples/measurements_ex04.py>`
* :ref:`Transparency <transparency_page>` - allows to change the transparency of mesh elements.
* :ref:`Controls <quality_page>` - graphically presents various information about the mesh.
* **Hide** - allows to hide the selected mesh from the viewer.
-* **Show Only** - allows to display only the selected mesh, hiding all others from the viewer.
-* :ref:`Clipping <clipping_page>` - allows to create cross-sections of the displayed objects.
+* **Show Only** - allows to display only the selected mesh, hiding all others from the viewer. If :ref:`Fit All upon Show Only <display_mode_pref>` Preference option is active, *Fit All* command is additionally performed.
+* :doc:`clipping` - allows to create cross-sections of the displayed objects.
* **Dump view** - exports an object from the viewer in bmp, png or jpeg image format.
* **Change background** - allows to redefine the background color. By default it is black.
* **View Operations** - allows to show/hide the visualization toolbar in the Viewer window.
* gravity center of the source
*/
PointStruct GravityCenter(in SMESH_IDSource source);
+
+ /*!
+ * angle in radians defined by 3 points <(p1,p2,p3)
+ */
+ double Angle(in PointStruct p1, in PointStruct p2, in PointStruct p3 );
};
};
in boolean underlyingOnly )
raises (SALOME::SALOME_Exception);
+ /*!
+ * Distribute all faces of the mesh among groups using sharp edges and optionally
+ * existing 1D elements as group boundaries.
+ * \param [in] sharpAngle - edge is considered sharp if an angle between normals of
+ * adjacent faces is more than \a sharpAngle in degrees.
+ * \param [in] createEdges - to create 1D elements for detected sharp edges.
+ * \param [in] useExistingEdges - to use existing edges as group boundaries
+ * \return ListOfGroups - the created groups
+ */
+ ListOfGroups FaceGroupsSeparatedByEdges( in double sharpAngle,
+ in boolean createEdges,
+ in boolean useExistingEdges )
+ raises (SALOME::SALOME_Exception);
+
/*!
* Convert group on geometry or on filter into standalone group
*/
* - 'e' stands for _edges_ field;
* - 'f' stands for _faces_ field;
* - 's' stands for _solids_ field.
+ * - ZTolerance : tolerance in Z direction. If Z coordinate of a node is close to zero
+ * within a given tolerance, the coordinate is set to zero.
+ * If @a ZTolerance is negative, the node coordinates are kept as is.
*/
void ExportPartToMED( in SMESH_IDSource meshPart,
in string fileName,
in boolean overwrite,
in boolean autoDimension,
in GEOM::ListOfFields fields,
- in string geomAssocFields ) raises (SALOME::SALOME_Exception);
+ in string geomAssocFields,
+ in double ZTolerance) raises (SALOME::SALOME_Exception);
/*!
* Export Mesh to SAUV formatted file
// 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
+ // a point is defined as follows:
+ // ( node*ID1 > 0 && node*ID2 > 0 ) ==> point is in the middle of an edge defined by two nodes
+ // ( node*ID1 > 0 && node*ID2 <=0 ) ==> point is at node*ID1
+ // else ==> point is at xyz*
+
+ // point 1
long node1ID1;
long node1ID2;
+ PointStruct xyz1;
- // 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
+ // point 2
long node2ID1;
long node2ID2;
+ PointStruct xyz2;
- DirStruct vector; // vector on the plane; to use a default plane set vector = (0,0,0)
+ // vector on the plane; to use a default plane set vector = (0,0,0)
+ DirStruct vector;
};
typedef sequence<PolySegment> ListOfPolySegments;
+ // face edge defined by two nodes + optional medium node
+ struct FaceEdge
+ {
+ long node1;
+ long node2;
+ long medium;
+ };
+ typedef sequence<FaceEdge> ListOfEdges;
+
/*!
* This interface makes modifications on the Mesh - removing elements and nodes etc.
+ * Also provides some analysis functions.
*/
interface SMESH_MeshEditor
{
in ElementType type)
raises (SALOME::SALOME_Exception);
+ /*!
+ * Project a point to a mesh object.
+ * Return ID of an element of given type where the given point is projected
+ * and coordinates of the projection point.
+ * In the case if nothing found, return -1 and []
+ */
+ long ProjectPoint(in double x,
+ in double y,
+ in double z,
+ in SMESH_IDSource meshObject,
+ in ElementType type,
+ out double_array projecton)
+ raises (SALOME::SALOME_Exception);
+
/*!
* Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
* TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
boolean IsCoherentOrientation2D()
raises (SALOME::SALOME_Exception);
+ /*!
+ * Return sharp edges of faces and non-manifold ones.
+ * Optionally add existing edges. Angle is in degrees.
+ */
+ ListOfEdges FindSharpEdges(in double angle, in boolean addExistingEdges)
+ raises (SALOME::SALOME_Exception);
+
/*!
* Returns all or only closed FreeBorder's.
*/
/*!
* \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.
+ * the initial triangle 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.
mesh_octahedron.png
mesh_orientation.png
mesh.png
+ mesh_plugins_meshcut.png
mesh_polygon.png
mesh_polyhedron.png
mesh_pyramid_n.png
mesh_hide.png
mesh_deflection.png
mesh_offset.png
+ mesh_face_groups_by_edges.png
+ mesh_angle_measure.png
)
INSTALL(FILES ${SMESH_RESOURCES_FILES} DESTINATION ${SALOME_SMESH_INSTALL_RES_DATA})
<parameter name="update_limit" value="500000" />
<parameter name="display_entity" value="true" />
<parameter name="display_mode" value="1" />
+ <parameter name="fitall_on_displayonly" value="1" />
<parameter name="auto_groups" value="false"/>
<parameter name="show_warning" value="true"/>
<parameter name="show_result_notification" value="2"/>
myAutoDimension(false),
myAddODOnVertices(false),
myDoAllInGroups(false),
- myVersion(-1)
+ myVersion(-1),
+ myZTolerance(-1.)
{}
void DriverMED_W_SMESHDS_Mesh::SetFile(const std::string& theFileName, int theVersion)
anIsXDimension = (aBounds[1] - aBounds[0]) + abs(aBounds[1]) + abs(aBounds[0]) > EPS;
anIsYDimension = (aBounds[3] - aBounds[2]) + abs(aBounds[3]) + abs(aBounds[2]) > EPS;
anIsZDimension = (aBounds[5] - aBounds[4]) + abs(aBounds[5]) + abs(aBounds[4]) > EPS;
+ if ( myZTolerance > 0 && anIsZDimension )
+ anIsZDimension = (aBounds[5] > myZTolerance || aBounds[4] < -myZTolerance );
aSpaceDimension = Max( aMeshDimension, anIsXDimension + anIsYDimension + anIsZDimension );
if ( !aSpaceDimension )
aSpaceDimension = 3;
for(TInt iCoord = 0; iCoord < aSpaceDimension; iCoord++){
aTCoordSlice[iCoord] = aCoordHelperPtr->GetCoord(iCoord);
}
+ if ( aSpaceDimension == 3 &&
+ -myZTolerance < aTCoordSlice[2] && aTCoordSlice[2] < myZTolerance )
+ aTCoordSlice[2] = 0.;
+
// node number
int aNodeID = aCoordHelperPtr->GetID();
aNodeInfo->SetElemNum( iNode, aNodeID );
void SetFile(const std::string& theFileName, int theVersion=-1);
void SetAutoDimension(bool toFindOutDimension) { myAutoDimension = toFindOutDimension; }
+ void SetZTolerance(double tol) { myZTolerance = tol; }
static std::string GetVersionString(int theMinor, int theNbDigits=2);
bool myAutoDimension;
bool myAddODOnVertices;
bool myDoAllInGroups;
- int myVersion;
+ int myVersion;
+ double myZTolerance;
};
#endif
SMDS_ElemIteratorPtr SMDS_Mesh::elementGeomIterator(SMDSAbs_GeometryType type) const
{
+ int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbElements( type );
return myCellFactory->GetIterator< SMDS_ElemIterator >( new SMDS_MeshElement::GeomFilter( type ),
- myInfo.NbElements( type ));
+ nbElems);
}
SMDS_ElemIteratorPtr SMDS_Mesh::elementEntityIterator(SMDSAbs_EntityType type) const
{
return myNodeFactory->GetIterator< SMDS_ElemIterator >( new SMDS_MeshElement::NonNullFilter );
}
+ int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbElements( type );
return myCellFactory->GetIterator<SMDS_ElemIterator>( new SMDS_MeshElement::EntityFilter( type ),
- myInfo.NbElements( type ));
+ nbElems);
}
///////////////////////////////////////////////////////////////////////////////
return myNodeFactory->GetIterator< TIterator >( new SMDS_MeshElement::NonNullFilter );
default:
+ int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbElements( type );
return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( type ),
- myInfo.NbElements( type ));
+ nbElems);
}
return SMDS_ElemIteratorPtr();
}
SMDS_EdgeIteratorPtr SMDS_Mesh::edgesIterator() const
{
typedef SMDS_EdgeIterator TIterator;
+ int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbEdges();
return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( SMDSAbs_Edge ),
- myInfo.NbEdges());
+ nbElems);
}
///////////////////////////////////////////////////////////////////////////////
SMDS_FaceIteratorPtr SMDS_Mesh::facesIterator() const
{
typedef SMDS_FaceIterator TIterator;
+ int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbFaces();
return myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( SMDSAbs_Face ),
- myInfo.NbFaces());
+ nbElems);
}
///////////////////////////////////////////////////////////////////////////////
SMDS_VolumeIteratorPtr SMDS_Mesh::volumesIterator() const
{
typedef SMDS_VolumeIterator TIterator;
+ int nbElems = myCellFactory->CompactChangePointers() ? -1 : myInfo.NbVolumes();
return
myCellFactory->GetIterator< TIterator >( new SMDS_MeshElement::TypeFilter( SMDSAbs_Volume ),
- myInfo.NbVolumes());
+ nbElems );
}
SMDS_NodeIteratorPtr SMDS_Mesh::shapeNodesIterator(int shapeID,
* The major version (x, where version is x.y.z) cannot be changed.
* \param [in] meshPart - mesh data to export
* \param [in] theAutoDimension - if \c true, a space dimension of a MED mesh can be either
- * - 1D if all mesh nodes lie on OX coordinate axis, or
- * - 2D if all mesh nodes lie on XOY coordinate plane, or
- * - 3D in the rest cases.
- * If \a theAutoDimension is \c false, the space dimension is always 3.
+ * - 1D if all mesh nodes lie on OX coordinate axis, or
+ * - 2D if all mesh nodes lie on XOY coordinate plane, or
+ * - 3D in the rest cases.
+ * If \a theAutoDimension is \c false, the space dimension is always 3.
* \param [in] theAddODOnVertices - to create 0D elements on all vertices
* \param [in] theAllElemsToGroup - to make every element to belong to any group (PAL23413)
+ * \param [in] ZTolerance - tolerance in Z direction. If Z coordinate of a node is close to zero
+ * within a given tolerance, the coordinate is set to zero.
+ * If \a ZTolerance is negative, the node coordinates are kept as is.
* \return int - mesh index in the file
*/
//================================================================================
-void SMESH_Mesh::ExportMED(const char * file,
- const char* theMeshName,
+void SMESH_Mesh::ExportMED(const char * file,
+ const char* theMeshName,
bool theAutoGroups,
int theVersion,
const SMESHDS_Mesh* meshPart,
bool theAutoDimension,
bool theAddODOnVertices,
+ double theZTolerance,
bool theAllElemsToGroup)
- throw(SALOME_Exception)
+throw(SALOME_Exception)
{
MESSAGE("MED_VERSION:"<< theVersion);
SMESH_TRY;
myWriter.SetMesh ( meshPart ? (SMESHDS_Mesh*) meshPart : _myMeshDS );
myWriter.SetAutoDimension( theAutoDimension );
myWriter.AddODOnVertices ( theAddODOnVertices );
- if ( !theMeshName )
+ myWriter.SetZTolerance ( theZTolerance );
+ if ( !theMeshName )
myWriter.SetMeshId ( _id );
else {
myWriter.SetMeshId ( -1 );
system(cmd.c_str());
ExportMED(medfilename.c_str(), theMeshName, theAutoGroups, /*minor=*/-1,
/*meshPart=*/NULL, /*theAutoDimension=*/false, /*theAddODOnVertices=*/false,
- /*theAllElemsToGroup=*/true ); // theAllElemsToGroup is for PAL0023413
+ /*zTol=*/-1, /*theAllElemsToGroup=*/true ); // theAllElemsToGroup is for PAL0023413
#ifdef WIN32
cmd = "%PYTHONBIN% ";
#else
*/
bool HasDuplicatedGroupNamesMED();
- void ExportMED(const char * theFile,
- const char* theMeshName = NULL,
- bool theAutoGroups = true,
+ void ExportMED(const char * theFile,
+ const char* theMeshName = NULL,
+ bool theAutoGroups = true,
int theVersion = -1,
const SMESHDS_Mesh* theMeshPart = 0,
bool theAutoDimension = false,
bool theAddODOnVertices = false,
+ double theZTolerance = -1.,
bool theAllElemsToGroup = false)
throw(SALOME_Exception);
for ( size_t i = 0; i < new2OldNodes.size(); ++i )
if ( const SMDS_MeshNode* n = new2OldNodes[ i ].first )
{
+#ifndef _DEBUG_
if ( n->NbInverseElements() > 0 )
+#endif
{
const SMDS_MeshNode* n2 =
tgtMeshDS->AddNodeWithID( n->X(), n->Y(), n->Z(), idShift + n->GetID() );
else
{
const double aTol = Precision::Confusion();
- auto_ptr< BRepClass3d_SolidClassifier> bsc3d;
- auto_ptr<_FaceClassifier> aFaceClassifier;
+ std::unique_ptr< BRepClass3d_SolidClassifier> bsc3d;
+ std::unique_ptr<_FaceClassifier> aFaceClassifier;
if ( theShape.ShapeType() == TopAbs_SOLID )
{
bsc3d.reset( new BRepClass3d_SolidClassifier(theShape));;
std::vector< gp_XYZ > myPoints;
double myLength;
- int mySrcPntInd; //!< start point index
const SMDS_MeshElement* myFace;
- SMESH_NodeXYZ myNode1;
+ SMESH_NodeXYZ myNode1; // nodes of the edge the path entered myFace
SMESH_NodeXYZ myNode2;
int myNodeInd1;
int myNodeInd2;
double myDot1;
double myDot2;
+
+ int mySrcPntInd; //!< start point index
TIDSortedElemSet myElemSet, myAvoidSet;
Path(): myLength(0.0), myFace(0) {}
myErrors( theSegments.size() )
{
}
+
#undef SMESH_CAUGHT
#define SMESH_CAUGHT myErrors[i] =
void operator() ( const int i ) const
SMESH_CATCH( SMESH::returnError );
}
#undef SMESH_CAUGHT
+
//================================================================================
/*!
* \brief Compute a path of a given segment
{
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;
+ // the cutting plane
+ gp_XYZ plnNorm = ( polySeg.myXYZ[0] - polySeg.myXYZ[1] ) ^ polySeg.myVector.XYZ();
+ gp_XYZ plnOrig = polySeg.myXYZ[1];
- // find paths connecting the 2 end points of polySeg
+ // Find paths connecting the 2 end points of polySeg
std::vector< Path > paths; paths.reserve(10);
- // initialize paths
+ // 1) initialize paths; two paths starts at each end point
for ( int iP = 0; iP < 2; ++iP ) // loop on the polySeg end points
{
path.mySrcPntInd = iP;
size_t nbPaths = paths.size();
+ if ( polySeg.myFace[ iP ]) // the end point lies on polySeg.myFace[ iP ]
+ {
+ // check coincidence of polySeg.myXYZ[ iP ] with nodes
+ const double tol = 1e-20;
+ SMESH_NodeXYZ nodes[4];
+ for ( int i = 0; i < 3 && !polySeg.myNode1[ iP ]; ++i )
+ {
+ nodes[ i ] = polySeg.myFace[ iP ]->GetNode( i );
+ if (( nodes[ i ] - polySeg.myXYZ[ iP ]).SquareModulus() < tol*tol )
+ polySeg.myNode1[ iP ] = nodes[ i ].Node();
+ }
+ nodes[ 3 ] = nodes[ 0 ];
+
+ // check coincidence of polySeg.myXYZ[ iP ] with edges
+ for ( int i = 0; i < 3 && !polySeg.myNode1[ iP ]; ++i )
+ {
+ SMDS_LinearEdge edge( nodes[i].Node(), nodes[i+1].Node() );
+ if ( SMESH_MeshAlgos::GetDistance( &edge, polySeg.myXYZ[ iP ]) < tol )
+ {
+ polySeg.myNode1[ iP ] = nodes[ i ].Node();
+ polySeg.myNode2[ iP ] = nodes[ i + 1 ].Node();
+ }
+ }
+
+ if ( !polySeg.myNode1[ iP ] ) // polySeg.myXYZ[ iP ] is within polySeg.myFace[ iP ]
+ {
+ double dot[ 4 ];
+ for ( int i = 0; i < 3; ++i )
+ dot[ i ] = plnNorm * ( nodes[ i ] - plnOrig );
+ dot[ 3 ] = dot[ 0 ];
+
+ int iCut = 0; // index of a cut edge
+ if ( dot[ 1 ] * dot[ 2 ] < 0. ) iCut = 1;
+ else if ( dot[ 2 ] * dot[ 3 ] < 0. ) iCut = 2;
+
+ // initialize path so as if it entered the face via iCut-th edge
+ path.myFace = polySeg.myFace[ iP ];
+ path.myNodeInd1 = iCut;
+ path.myNodeInd2 = iCut + 1;
+ path.myNode1.Set( nodes[ iCut ].Node() );
+ path.myNode2.Set( nodes[ iCut + 1 ].Node() );
+ path.myDot1 = dot[ iCut ];
+ path.myDot2 = dot[ iCut + 1 ];
+ path.myPoints.clear();
+ path.AddPoint( polySeg.myXYZ[ iP ]);
+ paths.push_back( path );
+
+ path.Extend( plnNorm, plnOrig ); // to get another edge cut
+ path.myFace = polySeg.myFace[ iP ];
+ if ( path.myDot1 == 0. ) // cut at a node
+ {
+ path.myNodeInd1 = ( iCut + 2 ) % 3;
+ path.myNodeInd2 = ( iCut + 3 ) % 3;
+ path.myNode2.Set( path.myFace->GetNode( path.myNodeInd2 ));
+ path.myDot2 = dot[ path.myNodeInd2 ];
+ }
+ else
+ {
+ path.myNodeInd1 = path.myFace->GetNodeIndex( path.myNode1.Node() );
+ path.myNodeInd2 = path.myFace->GetNodeIndex( path.myNode2.Node() );
+ }
+ path.myPoints.clear();
+ path.AddPoint( polySeg.myXYZ[ iP ]);
+ paths.push_back( path );
+ }
+ }
+
if ( polySeg.myNode2[ iP ] && polySeg.myNode2[ iP ] != polySeg.myNode1[ iP ] )
{
+ // the end point is on an edge
while (( path.myFace = SMESH_MeshAlgos::FindFaceInSet( polySeg.myNode1[ iP ],
polySeg.myNode2[ iP ],
path.myElemSet,
path.myDot1 = plnNorm * ( path.myNode1 - plnOrig );
path.myDot2 = plnNorm * ( path.myNode2 - plnOrig );
path.myPoints.clear();
- path.AddPoint( 0.5 * ( path.myNode1 + path.myNode2 ));
+ path.AddPoint( polySeg.myXYZ[ iP ]);
path.myAvoidSet.insert( path.myFace );
paths.push_back( path );
}
throw SALOME_Exception ( SMESH_Comment("No face edge found by point ") << iP+1
<< " in a PolySegment " << iSeg );
}
- else // an end point is at node
+ else if ( polySeg.myNode1[ iP ] ) // the end point is at a node
{
std::set<const SMDS_MeshNode* > nodes;
SMDS_ElemIteratorPtr fIt = polySeg.myNode1[ iP ]->GetInverseElementIterator(SMDSAbs_Face);
}
}
- // extend paths
+ // 2) extend paths and compose the shortest one connecting the two points
myPaths[ iSeg ].myLength = 1e100;
for ( size_t i = 0; i < paths.size(); ++i )
{
Path& path = paths[ i ];
- if ( !path.Extend( plnNorm, plnOrig ) || // path reached a mesh boundary
+ if ( !path.Extend( plnNorm, plnOrig ) || // path reached a mesh boundary
path.myLength > myPaths[ iSeg ].myLength ) // path is longer than others
{
Path::Remove( paths, i );
if ( myPaths[ iSeg ].myPoints.empty() )
throw SALOME_Exception( SMESH_Comment("Can't find a full path for PolySegment #") << iSeg );
+ // reverse the path
+ double d00 = ( polySeg.myXYZ[0] - myPaths[ iSeg ].myPoints.front() ).SquareModulus();
+ double d01 = ( polySeg.myXYZ[0] - myPaths[ iSeg ].myPoints.back() ).SquareModulus();
+ if ( d00 > d01 )
+ std::reverse( myPaths[ iSeg ].myPoints.begin(), myPaths[ iSeg ].myPoints.end() );
+
} // PolyPathCompute::Compute()
}; // struct PolyPathCompute
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] ));
+ polySeg.myFace[0] = polySeg.myFace[1] = 0;
+ if ( !polySeg.myNode1[0] && !polySeg.myNode2[0] )
+ {
+ p1 = searcher->Project( polySeg.myXYZ[0], SMDSAbs_Face, &polySeg.myFace[0] );
+ }
+ if ( !polySeg.myNode1[1] && !polySeg.myNode2[1] )
+ {
+ p2 = searcher->Project( polySeg.myXYZ[1], SMDSAbs_Face, &polySeg.myFace[1] );
+ }
+ polySeg.myXYZ[0] = p1;
+ polySeg.myXYZ[1] = p2;
+
gp_XYZ plnNorm = ( p1 - p2 ) ^ polySeg.myVector.XYZ();
isVectorOK[ iSeg ] = ( plnNorm.Modulus() > std::numeric_limits<double>::min() );
typedef TNodeOfNodeListMap::iterator TNodeOfNodeListMapItr;
typedef std::vector<TNodeOfNodeListMapItr> TVecOfNnlmiMap;
typedef std::map<const SMDS_MeshElement*, TVecOfNnlmiMap, TElemSort > TElemOfVecOfNnlmiMap;
- typedef std::auto_ptr< std::list<int> > PGroupIDs;
+ typedef std::unique_ptr< std::list< int > > PGroupIDs;
PGroupIDs RotationSweep (TIDSortedElemSet theElements[2],
const gp_Ax1& theAxis,
// 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)
+ // 2 points, each defined as follows:
+ // ( myNode1 && myNode2 ) ==> point is in the middle of an edge defined by two nodes
+ // ( myNode1 && !myNode2 ) ==> point is at myNode1
+ // else ==> point is at myXYZ
+ const SMDS_MeshNode* myNode1[2];
+ const SMDS_MeshNode* myNode2[2];
+ gp_XYZ myXYZ [2];
+
+ // face on which myXYZ projects (found by MakePolyLine())
+ const SMDS_MeshElement* myFace [2];
+
+ // vector on the plane; to use a default plane set vector = (0,0,0)
+ gp_Vec myVector;
// point to return coordinates of a middle of the two points, projected to mesh
gp_Pnt myMidProjPoint;
MyIterator(SMDSAbs_ElementType type, const SMESHDS_SubMesh* subMesh)
: myType(type), myElem(0)
{
- if ( subMesh ) {
- if ( myType == SMDSAbs_Node )
+ if ( subMesh )
+ {
+ if ( myType == SMDSAbs_Node ||
+ myType == SMDSAbs_0DElement ||
+ myType == SMDSAbs_Ball )
myNodeIt = subMesh->GetNodes();
- else {
+ else
myElemIt = subMesh->GetElements();
+
+ if ( myType != SMDSAbs_Node )
next();
- }
}
}
bool more()
{
if ( myType == SMDSAbs_Node && myNodeIt )
return myNodeIt->next();
+
const SMDS_MeshElement* res = myElem;
myElem = 0;
- while ( myElemIt && myElemIt->more() ) {
- myElem = myElemIt->next();
- if ( myElem && myElem->GetType() == myType )
- break;
- else
- myElem = 0;
- }
+
+ if ( myElemIt )
+ while ( myElemIt->more() ) {
+ myElem = myElemIt->next();
+ if ( myElem && myElem->GetType() == myType )
+ break;
+ else
+ myElem = 0;
+ }
+
+ if ( !myElem && myNodeIt ) // look for a 0D element
+ while ( myNodeIt->more() ) {
+ const SMDS_MeshNode* n = myNodeIt->next();
+ if (( myElemIt = n->GetInverseElementIterator( myType )) &&
+ ( myElemIt->more() ))
+ {
+ myElem = myElemIt->next();
+ break;
+ }
+ }
+
return res;
}
};
bool SMESHDS_GroupOnGeom::Contains (const SMDS_MeshElement* elem)
{
+ if ( GetType() == SMDSAbs_0DElement ||
+ GetType() == SMDSAbs_Ball )
+ return elem ? mySubMesh->Contains( elem->GetNode(0) ) : false;
+
return mySubMesh->Contains( elem );
}
SMESHGUI_MultiEditDlg.h
SMESHGUI_DeleteGroupDlg.h
SMESHGUI_GroupOpDlg.h
+ SMESHGUI_FaceGroupsSeparatedByEdgesDlg.h
SMESHGUI_SmoothingDlg.h
SMESHGUI_RenumberingDlg.h
SMESHGUI_ExtrusionDlg.h
SMESHGUI_MultiEditDlg.cxx
SMESHGUI_DeleteGroupDlg.cxx
SMESHGUI_GroupOpDlg.cxx
+ SMESHGUI_FaceGroupsSeparatedByEdgesDlg.cxx
SMESHGUI_SmoothingDlg.cxx
SMESHGUI_RenumberingDlg.cxx
SMESHGUI_ExtrusionDlg.cxx
#include "SMESHGUI_CopyMeshDlg.h"
#include "SMESHGUI_CreatePolyhedralVolumeDlg.h"
#include "SMESHGUI_DeleteGroupDlg.h"
+#include "SMESHGUI_DisplayEntitiesDlg.h"
#include "SMESHGUI_Displayer.h"
#include "SMESHGUI_DuplicateNodesDlg.h"
#include "SMESHGUI_ExtrusionAlongPathDlg.h"
#include "SMESHGUI_ExtrusionDlg.h"
+#include "SMESHGUI_FaceGroupsSeparatedByEdgesDlg.h"
#include "SMESHGUI_FieldSelectorWdg.h"
#include "SMESHGUI_FileInfoDlg.h"
#include "SMESHGUI_FileValidator.h"
#include "SMESHGUI_FilterDlg.h"
#include "SMESHGUI_FilterLibraryDlg.h"
+#include "SMESHGUI_FilterUtils.h"
#include "SMESHGUI_FindElemByPointDlg.h"
+#include "SMESHGUI_GEOMGenUtils.h"
#include "SMESHGUI_GroupDlg.h"
#include "SMESHGUI_GroupOnShapeDlg.h"
#include "SMESHGUI_GroupOpDlg.h"
+#include "SMESHGUI_GroupUtils.h"
#include "SMESHGUI_Hypotheses.h"
+#include "SMESHGUI_HypothesesUtils.h"
#include "SMESHGUI_Make2DFrom3DOp.h"
#include "SMESHGUI_MakeNodeAtPointDlg.h"
#include "SMESHGUI_Measurements.h"
#include "SMESHGUI_MeshOp.h"
#include "SMESHGUI_MeshOrderOp.h"
#include "SMESHGUI_MeshPatternDlg.h"
+#include "SMESHGUI_MeshUtils.h"
#include "SMESHGUI_MultiEditDlg.h"
#include "SMESHGUI_NodesDlg.h"
+#include "SMESHGUI_OffsetDlg.h"
#include "SMESHGUI_Operations.h"
+#include "SMESHGUI_PatternUtils.h"
#include "SMESHGUI_Preferences_ScalarBarDlg.h"
#include "SMESHGUI_PropertiesDlg.h"
#include "SMESHGUI_RemoveElementsDlg.h"
#include "SMESHGUI_RevolutionDlg.h"
#include "SMESHGUI_RotationDlg.h"
#include "SMESHGUI_ScaleDlg.h"
-#include "SMESHGUI_OffsetDlg.h"
#include "SMESHGUI_Selection.h"
#include "SMESHGUI_SewingDlg.h"
#include "SMESHGUI_SingleEditDlg.h"
#include "SMESHGUI_SmoothingDlg.h"
+#include "SMESHGUI_SpinBox.h"
+#include "SMESHGUI_SplitBiQuad.h"
#include "SMESHGUI_SymmetryDlg.h"
#include "SMESHGUI_TranslationDlg.h"
#include "SMESHGUI_TransparencyDlg.h"
-#include "SMESHGUI_DisplayEntitiesDlg.h"
-#include "SMESHGUI_SplitBiQuad.h"
-
-#include "SMESHGUI_FilterUtils.h"
-#include "SMESHGUI_GEOMGenUtils.h"
-#include "SMESHGUI_GroupUtils.h"
-#include "SMESHGUI_HypothesesUtils.h"
-#include "SMESHGUI_MeshUtils.h"
-#include "SMESHGUI_PatternUtils.h"
#include "SMESHGUI_Utils.h"
#include "SMESHGUI_VTKUtils.h"
#include "SMESH_ActorUtils.h"
#include "SMESH_Client.hxx"
#include "SMESH_ScalarBarActor.h"
+#include <SMESH_Comment.hxx>
#include "SMESH_TypeFilter.hxx"
// SALOME GUI includes
-#include <SalomeApp_Application.h>
-#include <SalomeApp_CheckFileDlg.h>
-#include <SalomeApp_DataObject.h>
-#include <SalomeApp_Study.h>
-#include <SalomeApp_Tools.h>
-
#include <LightApp_DataOwner.h>
#include <LightApp_NameDlg.h>
#include <LightApp_Preferences.h>
#include <LightApp_SelectionMgr.h>
#include <LightApp_UpdateFlags.h>
-
-#include <SVTK_ViewManager.h>
-#include <SVTK_ViewModel.h>
-#include <SVTK_ViewWindow.h>
-
-#include <VTKViewer_Algorithm.h>
-
+#include <QtxFontEdit.h>
+#include <QtxPopupMgr.h>
+#include <SALOME_ListIO.hxx>
#include <SUIT_Desktop.h>
#include <SUIT_FileDlg.h>
#include <SUIT_MessageBox.h>
#include <SUIT_OverrideCursor.h>
#include <SUIT_ResourceMgr.h>
#include <SUIT_Session.h>
-
-#include <QtxPopupMgr.h>
-#include <QtxFontEdit.h>
-
-#include <SALOME_ListIO.hxx>
+#include <SVTK_ViewManager.h>
+#include <SVTK_ViewModel.h>
+#include <SVTK_ViewWindow.h>
+#include <SalomeApp_Application.h>
+#include <SalomeApp_CheckFileDlg.h>
+#include <SalomeApp_DataObject.h>
+#include <SalomeApp_Study.h>
+#include <SalomeApp_Tools.h>
+#include <VTKViewer_Algorithm.h>
#ifndef DISABLE_PLOT2DVIEWER
#include <SPlot2d_ViewModel.h>
// Qt includes
// #define INCLUDE_MENUITEM_DEF // VSR commented ????????
#include <QApplication>
+#include <QCheckBox>
+#include <QDialogButtonBox>
+#include <QLayout>
+#include <QListView>
#include <QMenu>
#include <QTextStream>
-#include <QListView>
#include <QTreeView>
-#include <QCheckBox>
-#include <QLayout>
-#include <QDialogButtonBox>
// BOOST includes
#include <boost/shared_ptr.hpp>
QDialogButtonBox* btnbox = msgBox.findChild<QDialogButtonBox*>();
lt->addWidget(&dontShowCheckBox, lt->rowCount(), lt->columnCount()-1, lt->rowCount(), lt->columnCount());
lt->addWidget(btnbox, lt->rowCount(), 0, lt->rowCount(), lt->columnCount());
- if(msgBox.exec() == QMessageBox::Ok)
- {
- if(dontShowCheckBox.checkState() == Qt::Checked)
- {
- if ( resMgr )
- resMgr->setValue( "SMESH", "show_warning", false);
- }
- aCheckWarn = false;
- }
- else
+ if ( msgBox.exec() != QMessageBox::Ok )
return;
+
+ if ( dontShowCheckBox.checkState() == Qt::Checked && resMgr )
+ resMgr->setValue( "SMESH", "show_warning", false);
}
QString aMeshName = anIObject->getName();
toCreateGroups = resMgr->booleanValue( "SMESH", "auto_groups", false );
bool toOverwrite = true;
bool toFindOutDim = true;
+ double zTol = resMgr ? resMgr->doubleValue( "SMESH", "med_ztolerance", 0. ) : 0.;
QString aFilter, aTitle = QObject::tr("SMESH_EXPORT_MESH");
QString anInitialPath = "";
if ( isMED ) {
//filters << QObject::tr( "MED_FILES_FILTER" ) + " (*.med)";
//QString vmed (aMesh->GetVersionString(-1, 2));
- //MESSAGE("MED version: " << vmed.toStdString());
SMESH::long_array_var mvok = aMesh->GetMEDVersionsCompatibleForAppend();
- for ( int i = 0; i < mvok->length(); ++i ) // i=0 must correspond to the current version to set the default filter on it
- {
- int versionInt = mvok[i];
- if (i == 0)
- defaultVersion = versionInt;
- std::ostringstream vss;
- vss << versionInt/10;
- vss << ".";
- vss << versionInt%10;
- QString vs = vss.str().c_str();
- MESSAGE("MED version: " << vs.toStdString());
- aFilterMap.insert( QObject::tr( "MED_VX_FILES_FILTER" ).arg( vs ) + " (*.med)", versionInt);
- }
+ if ( mvok->length() > 0)
+ defaultVersion = mvok[0]; // the current version to set the default filter on it
+ for ( CORBA::ULong i = 0; i < mvok->length(); ++i )
+ {
+ QString vs = (char*)( SMESH_Comment( mvok[i]/10 ) << "." << mvok[i]%10 );
+ MESSAGE("MED version: " << vs.toStdString());
+ aFilterMap.insert( QObject::tr( "MED_VX_FILES_FILTER" ).arg( vs ) + " (*.med)", mvok[i]);
+ }
}
else { // isSAUV
aFilterMap.insert("All files (*)", -1 );
aFilterMap.insert("SAUV files (*.sauv)", defaultVersion ); // 0 = default filter (defaultVersion)
aFilterMap.insert("SAUV files (*.sauve)", -1 );
}
- MESSAGE("default version="<< defaultVersion);
QStringList filters;
QMap<QString, int>::const_iterator it = aFilterMap.begin();
QString aDefaultFilter = it.key();
if ( fieldSelWdg->GetAllFields( aMeshList, aFieldList ))
wdgList.append( fieldSelWdg );
+ QWidget* zTolWdg = new QWidget();
+ QCheckBox* zTolCheck = new QCheckBox( QObject::tr( "SMESH_ZTOLERANCE" ), zTolWdg );
+ SMESHGUI_SpinBox* zTolSpin = new SMESHGUI_SpinBox( zTolWdg );
+ QHBoxLayout* zTolLayout = new QHBoxLayout( zTolWdg );
+ zTolLayout->addWidget( zTolCheck );
+ zTolLayout->addWidget( zTolSpin );
+ zTolLayout->setMargin( 0 );
+ zTolSpin->RangeStepAndValidator( 0, 1e+100, 1., "length_precision" );
+ zTolSpin->setValue( zTol );
+ QObject::connect( zTolCheck, SIGNAL( toggled(bool)), zTolSpin, SLOT( setEnabled(bool)));
+ zTolCheck->setChecked( resMgr->booleanValue( "SMESH", "enable_ztolerance", false ));
+ zTolSpin ->setEnabled( zTolCheck->isChecked() );
+ wdgList.append( zTolWdg );
+
SalomeApp_CheckFileDlg* fd =
new SalomeApp_CheckFileDlg ( SMESHGUI::desktop(), false, checkBoxes, true, true, wdgList );
fd->setWindowTitle( aTitle );
fd->setValidator( fv );
bool is_ok = false;
- while (!is_ok) {
- MESSAGE("******* Loop on file dialog ***********");
+ while (!is_ok)
+ {
+ //MESSAGE("******* Loop on file dialog ***********");
isOkToWrite =true;
if ( fd->exec() )
aFilename = fd->selectedFile();
break;
}
aFormat = aFilterMap[fd->selectedNameFilter()];
- MESSAGE("selected version: " << aFormat << " file: " << aFilename.toUtf8().constData());
+ //MESSAGE("selected version: " << aFormat << " file: " << aFilename.toUtf8().constData());
toOverwrite = fv->isOverwrite(aFilename);
- MESSAGE("toOverwrite:" << toOverwrite);
+ //MESSAGE("toOverwrite:" << toOverwrite);
is_ok = true;
if ( !aFilename.isEmpty() ) {
if( !toOverwrite ) {
QObject::tr("SMESH_BUT_YES"),
QObject::tr("SMESH_BUT_NO"), 0, 1);
if (aRet == 0)
- {
- toOverwrite = true;
- MESSAGE("incompatible MED file version for add, overwrite accepted");
- }
+ {
+ toOverwrite = true;
+ //MESSAGE("incompatible MED file version for add, overwrite accepted");
+ }
else
- {
- isOkToWrite = false;
- is_ok = false;
- MESSAGE("incompatible MED file version for add, overwrite refused");
- }
+ {
+ isOkToWrite = false;
+ is_ok = false;
+ //MESSAGE("incompatible MED file version for add, overwrite refused");
+ }
}
QStringList aMeshNamesCollisionList;
SMESH::string_array_var aMeshNames = SMESHGUI::GetSMESHGen()->GetMeshNames( aFilename.toUtf8().constData() );
}
}
}
- if( !aMeshNamesCollisionList.isEmpty() ) {
+ if( !aMeshNamesCollisionList.isEmpty() ) {
isOkToWrite = false;
QString aMeshNamesCollisionString = aMeshNamesCollisionList.join( ", " );
int aRet = SUIT_MessageBox::warning(SMESHGUI::desktop(),
QObject::tr("SMESH_BUT_YES"),
QObject::tr("SMESH_BUT_NO"),
QObject::tr("SMESH_BUT_CANCEL"), 0, 2);
- MESSAGE("answer collision name " << aRet);
- if (aRet == 0) {
+ MESSAGE("answer collision name " << aRet);
+ if (aRet == 0) {
toOverwrite = true;
isOkToWrite = true;
}
}
}
}
- MESSAGE(" ****** end of file dialog loop, toOverwrite:" << toOverwrite << " isOkToWrite:" << isOkToWrite);
toCreateGroups = fd->IsChecked(0);
toFindOutDim = fd->IsChecked(1);
+ zTol = zTolCheck->isChecked() ? zTolSpin->value() : -1;
fieldSelWdg->GetSelectedFields();
+ if ( resMgr ) resMgr->setValue( "SMESH", "enable_ztolerance", zTolCheck->isChecked() );
+
if ( !fieldSelWdg->parent() )
delete fieldSelWdg;
+ if ( !zTolWdg->parent() )
+ delete zTolWdg;
delete fd;
}
else
try {
// Renumbering is not needed since SMDS redesign in V6.2.0 (Nov 2010)
-// bool Renumber = false;
-// // PAL 14172 : Check of we have to renumber or not from the preferences before export
-// if (resMgr)
-// Renumber= resMgr->booleanValue("renumbering");
-// if (Renumber){
-// SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
+ // bool Renumber = false;
+ // // PAL 14172 : Check of we have to renumber or not from the preferences before export
+ // if (resMgr)
+ // Renumber= resMgr->booleanValue("renumbering");
+ // if (Renumber){
+ // SMESH::SMESH_MeshEditor_var aMeshEditor = aMesh->GetMeshEditor();
// aMeshEditor->RenumberNodes();
// aMeshEditor->RenumberElements();
// if ( SMESHGUI::automaticUpdate() )
const GEOM::ListOfFields& fields = aFieldList[ aMeshIndex ].first.in();
const QString& geoAssFields = aFieldList[ aMeshIndex ].second;
const bool hasFields = ( fields.length() || !geoAssFields.isEmpty() );
- if ( !hasFields && aMeshOrGroup->_is_equivalent( aMeshItem ))
+ if ( !hasFields && aMeshOrGroup->_is_equivalent( aMeshItem ) && zTol < 0 )
aMeshItem->ExportMED( aFilename.toUtf8().data(), toCreateGroups, aFormat,
toOverwrite && aMeshIndex == 0, toFindOutDim );
else
- aMeshItem->ExportPartToMED( aMeshOrGroup, aFilename.toUtf8().data(), toCreateGroups, aFormat,
+ aMeshItem->ExportPartToMED( aMeshOrGroup, aFilename.toUtf8().data(),
+ toCreateGroups, aFormat,
toOverwrite && aMeshIndex == 0, toFindOutDim,
- fields, geoAssFields.toLatin1().data() );
+ fields, geoAssFields.toLatin1().data(), zTol );
}
}
else if ( isSAUV )
break;
}
+ case SMESHOp::OpFaceGroupsByEdges: // Create face groups separated by sharp edges
+ {
+ if ( isStudyLocked() )
+ break;
+
+ EmitSignalDeactivateDialog();
+ SMESHGUI_FaceGroupsSeparatedByEdgesDlg* aDlg = new SMESHGUI_FaceGroupsSeparatedByEdgesDlg( this );
+ aDlg->show();
+
+ break;
+ }
+
case SMESHOp::OpDeleteGroup: // Delete groups with their contents
{
if ( !vtkwnd )
case SMESHOp::OpPropertiesVolume:
case SMESHOp::OpMinimumDistance:
case SMESHOp::OpBoundingBox:
+ case SMESHOp::OpAngle:
{
int page = SMESHGUI_MeasureDlg::MinDistance;
if ( theCommandID == SMESHOp::OpBoundingBox )
page = SMESHGUI_MeasureDlg::Area;
else if ( theCommandID == SMESHOp::OpPropertiesVolume )
page = SMESHGUI_MeasureDlg::Volume;
+ else if ( theCommandID == SMESHOp::OpAngle )
+ page = SMESHGUI_MeasureDlg::Angle;
EmitSignalDeactivateDialog();
SMESHGUI_MeasureDlg* dlg = new SMESHGUI_MeasureDlg( SMESHGUI::desktop(), page );
createSMESHAction( SMESHOp::OpIntersectGroups, "INT_GROUP", "ICON_INTERSECT" );
createSMESHAction( SMESHOp::OpCutGroups, "CUT_GROUP", "ICON_CUT" );
createSMESHAction( SMESHOp::OpGroupUnderlyingElem, "UNDERLYING_ELEMS", "ICON_UNDERLYING_ELEMS" );
+ createSMESHAction( SMESHOp::OpFaceGroupsByEdges, "FACE_GROUPS_BY_EDGES", "ICON_FACE_GROUPS_BY_EDGES" );
createSMESHAction( SMESHOp::OpAddElemGroupPopup, "ADD_TO_GROUP" );
createSMESHAction( SMESHOp::OpRemoveElemGroupPopup, "REMOVE_FROM_GROUP" );
createSMESHAction( SMESHOp::OpDeleteGroup, "DEL_GROUP", "ICON_DEL_GROUP" );
createSMESHAction( SMESHOp::OpPropertiesLength, "MEASURE_LENGTH", "ICON_MEASURE_LENGTH" );
createSMESHAction( SMESHOp::OpPropertiesArea, "MEASURE_AREA", "ICON_MEASURE_AREA" );
createSMESHAction( SMESHOp::OpPropertiesVolume, "MEASURE_VOLUME", "ICON_MEASURE_VOLUME" );
+ createSMESHAction( SMESHOp::OpAngle, "MEASURE_ANGLE", "ICON_MEASURE_ANGLE" );
createSMESHAction( SMESHOp::OpHide, "HIDE", "ICON_HIDE" );
createSMESHAction( SMESHOp::OpShow, "SHOW", "ICON_SHOW" );
createMenu( SMESHOp::OpCutGroups, meshId, -1 );
createMenu( separator(), meshId, -1 );
createMenu( SMESHOp::OpGroupUnderlyingElem, meshId, -1 );
+ createMenu( SMESHOp::OpFaceGroupsByEdges, meshId, -1 );
createMenu( separator(), meshId, -1 );
createMenu( SMESHOp::OpMeshInformation, meshId, -1 );
//createMenu( SMESHOp::OpStdInfo, meshId, -1 );
createMenu( SMESHOp::OpMinimumDistance, measureId, -1 );
createMenu( SMESHOp::OpBoundingBox, measureId, -1 );
+ createMenu( SMESHOp::OpAngle, measureId, -1 );
createMenu( SMESHOp::OpPropertiesLength, basicPropId, -1 );
createMenu( SMESHOp::OpPropertiesArea, basicPropId, -1 );
createMenu( SMESHOp::OpPropertiesVolume, basicPropId, -1 );
int dispgroup = addPreference( tr( "PREF_DISPLAY_MODE_GROUP" ), genTab );
setPreferenceProperty( dispgroup, "columns", 2 );
+
+ addPreference( tr( "PREF_FITALL_ON_DISPLAYONLY" ), dispgroup, LightApp_Preferences::Bool, "SMESH", "fitall_on_displayonly" );
+
int dispmode = addPreference( tr( "PREF_DISPLAY_MODE" ), dispgroup, LightApp_Preferences::Selector, "SMESH", "display_mode" );
QStringList modes;
modes.append( tr("MEN_WIRE") );
setPreferenceProperty( exportgroup, "columns", 2 );
addPreference( tr( "PREF_AUTO_GROUPS" ), exportgroup, LightApp_Preferences::Bool, "SMESH", "auto_groups" );
addPreference( tr( "PREF_SHOW_WARN" ), exportgroup, LightApp_Preferences::Bool, "SMESH", "show_warning" );
+ int zTol = addPreference( tr( "PREF_ZTOLERANCE" ), exportgroup, LightApp_Preferences::DblSpin, "SMESH", "med_ztolerance" );
+ setPreferenceProperty( zTol, "precision", 10 );
+ setPreferenceProperty( zTol, "min", 0.0000000001 );
+ setPreferenceProperty( zTol, "max", 1000000.0 );
+ setPreferenceProperty( zTol, "step", 1. );
//addPreference( tr( "PREF_RENUMBER" ), exportgroup, LightApp_Preferences::Bool, "SMESH", "renumbering" );
int computeGroup = addPreference( tr( "PREF_GROUP_COMPUTE" ), genTab );
std::string aWarning;
SUIT_ResourceMgr* aResourceMgr = SMESH::GetResourceMgr(this);
- if ( name== "selection_object_color" ||
- name=="selection_element_color" ||
- name== "highlight_color" ||
- name=="selection_precision_node" ||
- name=="selection_precision_element" ||
- name=="selection_precision_object" ||
- name=="selection_increment")
+ if ( name == "selection_object_color" ||
+ name == "selection_element_color" ||
+ name == "highlight_color" ||
+ name == "selection_precision_node" ||
+ name == "selection_precision_element" ||
+ name == "selection_precision_object" ||
+ name == "selection_increment")
{
SMESH::UpdateSelectionProp( this );
}
try {
OCC_CATCH_SIGNALS;
bool toDisplay = false;
+ std::string entry = (*anIter).second->GetID();
if ( !aMesh->_is_nil() ) // display only a mesh
{
toDisplay = true;
SMESH_Actor *anActor = SMESH::FindActorByObject( aMesh );
- if ( !anActor ) anActor = SMESH::CreateActor( (*anIter).second->GetID().c_str(),
- /*clearLog =*/ true );
+ if ( !anActor ) anActor = SMESH::CreateActor( entry.c_str(), /*clearLog =*/true );
if ( anActor ) // actor is not created for an empty mesh
{
anActor->SetEntityMode( entities );
- SMESH::DisplayActor( SMESH::GetActiveWindow(), anActor );
+ //SMESH::DisplayActor( SMESH::GetActiveWindow(), anActor ); -- 23615
}
}
- Handle(SALOME_InteractiveObject) anIO = new SALOME_InteractiveObject
- ( (*anIter).second->GetID().c_str(), "SMESH", (*anIter).second->GetName().c_str() );
- SMESH::Update(anIO, toDisplay);
+ if ( toDisplay )
+ SMESH::UpdateView( SMESH::eDisplay, entry.c_str() );
if ( SVTK_ViewWindow* vtkWnd = SMESH::GetVtkViewWindow(SMESH::GetActiveWindow() ))
if ( vtkWnd->getRenderer() )
--- /dev/null
+// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+// File : SMESHGUI_FaceGroupsSeparatedByEdges.cxx
+
+#include "SMESHGUI_FaceGroupsSeparatedByEdgesDlg.h"
+
+#include "SMESHGUI.h"
+#include "SMESHGUI_SpinBox.h"
+#include "SMESHGUI_MeshEditPreview.h"
+#include "SMESHGUI_Utils.h"
+
+// SALOME GUI includes
+#include <LightApp_Application.h>
+#include <LightApp_SelectionMgr.h>
+#include <SALOME_Actor.h>
+#include <SALOME_ListIO.hxx>
+#include <SUIT_MessageBox.h>
+#include <SUIT_OverrideCursor.h>
+#include <SUIT_ResourceMgr.h>
+#include <SUIT_Session.h>
+#include <SalomeApp_Tools.h>
+
+#include <SALOMEDS_SObject.hxx>
+
+// IDL includes
+#include <SALOMEconfig.h>
+#include CORBA_SERVER_HEADER(SMESH_Group)
+
+// Qt includes
+#include <QCheckBox>
+#include <QGridLayout>
+#include <QGroupBox>
+#include <QHBoxLayout>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QRadioButton>
+#include <QToolButton>
+
+#include <Standard_ErrorHandler.hxx>
+
+#define SPACING 6
+#define MARGIN 11
+
+/*!
+ \class SMESHGUI_FaceGroupsSeparatedByEdgesDlg
+ \brief Dialog to create face groups divided by sharp edges
+*/
+
+SMESHGUI_FaceGroupsSeparatedByEdgesDlg::
+SMESHGUI_FaceGroupsSeparatedByEdgesDlg( SMESHGUI* theModule ) :
+ SMESHGUI_PreviewDlg( theModule ),
+ mySelectionMgr( SMESH::GetSelectionMgr( theModule ))
+{
+ setModal(false);
+ setAttribute(Qt::WA_DeleteOnClose, true);
+ setWindowTitle(tr("CAPTION"));
+ setSizeGripEnabled(true);
+
+ QVBoxLayout* dlgLayout = new QVBoxLayout(this);
+ dlgLayout->setSpacing(SPACING);
+ dlgLayout->setMargin(MARGIN);
+
+ /***************************************************************/
+ GroupArgs = new QGroupBox(tr("SMESH_ARGUMENTS"), this);
+ QGridLayout* GroupArgsLayout = new QGridLayout(GroupArgs);
+ GroupArgsLayout->setSpacing(SPACING);
+ GroupArgsLayout->setMargin(MARGIN);
+
+ // mesh
+ QLabel* meshNameLabel = new QLabel(tr("SMESH_MESH"), GroupArgs);
+ myMeshName = new QLineEdit( GroupArgs );
+ myMeshName->setReadOnly( true );
+
+ // angle
+ QLabel* angleLabel = new QLabel( tr("SHARP_ANGLE"), GroupArgs );
+ myAngle = new SMESHGUI_SpinBox( GroupArgs );
+ myAngle->RangeStepAndValidator( 0, 180.0, 10.0, "angle_precision");
+
+ // check-boxes
+ myCreateEdgesCheck = new QCheckBox( tr("CREATE_EDGES" ), GroupArgs);
+ myUseExistingCheck = new QCheckBox( tr("USE_EXISTING_EDGES"), GroupArgs);
+ myPreviewCheckBox = new QCheckBox(tr("PREVIEW"), GroupArgs);
+
+ // set previous values
+ if ( SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr() )
+ {
+ myAngle->setValue( resMgr->doubleValue( "SMESH", "prev_sharp_angle", 30. ));
+ myCreateEdgesCheck->setChecked( resMgr->booleanValue( "SMESH", "prev_create_edges", false ));
+ myUseExistingCheck->setChecked( resMgr->booleanValue( "SMESH", "prev_use_existing_edges", false ));
+ }
+
+ // layout
+ GroupArgsLayout->addWidget( meshNameLabel, 0, 0);
+ GroupArgsLayout->addWidget( myMeshName, 0, 1);
+ GroupArgsLayout->addWidget( angleLabel, 1, 0);
+ GroupArgsLayout->addWidget( myAngle, 1, 1);
+ GroupArgsLayout->addWidget( myCreateEdgesCheck, 2, 0);
+ GroupArgsLayout->addWidget( myUseExistingCheck, 3, 0);
+ GroupArgsLayout->addWidget( myPreviewCheckBox, 4, 0);
+
+ /***************************************************************/
+ GroupButtons = new QGroupBox(this);
+ QHBoxLayout* GroupButtonsLayout = new QHBoxLayout(GroupButtons);
+ GroupButtonsLayout->setSpacing(SPACING);
+ GroupButtonsLayout->setMargin(MARGIN);
+
+ buttonOk = new QPushButton(tr("SMESH_BUT_APPLY_AND_CLOSE"), GroupButtons);
+ buttonOk->setAutoDefault(true);
+ buttonOk->setDefault(true);
+ buttonApply = new QPushButton(tr("SMESH_BUT_APPLY"), GroupButtons);
+ buttonApply->setAutoDefault(true);
+ buttonCancel = new QPushButton(tr("SMESH_BUT_CLOSE"), GroupButtons);
+ buttonCancel->setAutoDefault(true);
+ buttonHelp = new QPushButton(tr("SMESH_BUT_HELP"), GroupButtons);
+ buttonHelp->setAutoDefault(true);
+
+ GroupButtonsLayout->addWidget(buttonOk);
+ GroupButtonsLayout->addSpacing(10);
+ GroupButtonsLayout->addWidget(buttonApply);
+ GroupButtonsLayout->addSpacing(10);
+ GroupButtonsLayout->addStretch();
+ GroupButtonsLayout->addWidget(buttonCancel);
+ GroupButtonsLayout->addWidget(buttonHelp);
+
+ /***************************************************************/
+ dlgLayout->addWidget(GroupArgs);
+ dlgLayout->addWidget(GroupButtons);
+
+ mySMESHGUI->SetActiveDialogBox(this);
+
+ /* signals and slots connections */
+ connect(buttonOk, SIGNAL(clicked()), this, SLOT(ClickOnOk()));
+ connect(buttonCancel, SIGNAL(clicked()), this, SLOT(reject()));
+ connect(buttonApply, SIGNAL(clicked()), this, SLOT(ClickOnApply()));
+ connect(buttonHelp, SIGNAL(clicked()), this, SLOT(ClickOnHelp()));
+
+ connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog()));
+ connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
+ /* to close dialog if study change */
+ connect(mySMESHGUI, SIGNAL(SignalCloseAllDialogs()), this, SLOT(reject()));
+ connect(mySMESHGUI, SIGNAL(SignalActivatedViewManager()), this, SLOT(onOpenView()));
+ connect(mySMESHGUI, SIGNAL(SignalCloseView()), this, SLOT(onCloseView()));
+
+ connect( myAngle, SIGNAL(valueChanged(double)), this, SLOT( onArgChange() ));
+ connect( myCreateEdgesCheck, SIGNAL(toggled(bool)), this, SLOT( onArgChange() ));
+ connect( myUseExistingCheck, SIGNAL(toggled(bool)), this, SLOT( onArgChange() ));
+
+ connectPreviewControl();
+ mySimulation->GetActor()->GetProperty()->SetLineWidth( 5 );
+
+ SelectionIntoArgument();
+}
+
+SMESHGUI_FaceGroupsSeparatedByEdgesDlg::~SMESHGUI_FaceGroupsSeparatedByEdgesDlg()
+{
+}
+
+//=================================================================================
+// function : ClickOnApply()
+// purpose :
+//=================================================================================
+
+bool SMESHGUI_FaceGroupsSeparatedByEdgesDlg::ClickOnApply()
+{
+ if ( mySMESHGUI->isStudyLocked() )
+ return false;
+
+ SUIT_OverrideCursor aWaitCursor;
+
+ QStringList aParameters, anEntryList;
+ aParameters << myAngle->text();
+
+ try
+ {
+ SMESH::ListOfGroups_var groups =
+ myMesh->FaceGroupsSeparatedByEdges( myAngle->value(),
+ myCreateEdgesCheck->isChecked(),
+ myUseExistingCheck->isChecked());
+
+ for ( CORBA::ULong i = 0; i < groups->length(); ++i )
+ if( _PTR(SObject) aSObject = SMESH::ObjectToSObject( groups[i].in() ))
+ anEntryList.append( aSObject->GetID().c_str() );
+
+ SUIT_MessageBox::information(this, tr("SMESH_INFORMATION"),
+ tr("NB_GROUPS_CREATED").arg( groups->length() ));
+ }
+ catch ( const SALOME::SALOME_Exception& S_ex ) {
+ SalomeApp_Tools::QtCatchCorbaException( S_ex );
+ }
+ catch (...) {
+ }
+
+ mySMESHGUI->updateObjBrowser(true); // new groups may appear
+ if( LightApp_Application* anApp =
+ dynamic_cast<LightApp_Application*>( SUIT_Session::session()->activeApplication() ) )
+ {
+ anApp->browseObjects( anEntryList, isApplyAndClose() );
+ }
+
+ SMESHGUI::Modified();
+
+ return true;
+}
+//=================================================================================
+// function : ClickOnOk()
+// purpose :
+//=================================================================================
+
+void SMESHGUI_FaceGroupsSeparatedByEdgesDlg::ClickOnOk()
+{
+ setIsApplyAndClose( true );
+ if( ClickOnApply() )
+ reject();
+}
+
+//=================================================================================
+// function : reject()
+// purpose :
+//=================================================================================
+void SMESHGUI_FaceGroupsSeparatedByEdgesDlg::reject()
+{
+ disconnect(mySelectionMgr, 0, this, 0);
+ mySMESHGUI->ResetState();
+ QDialog::reject();
+}
+//=================================================================================
+// function : ClickOnHelp()
+// purpose :
+//=================================================================================
+
+void SMESHGUI_FaceGroupsSeparatedByEdgesDlg::ClickOnHelp()
+{
+ static QString myHelpFileName( "face_groups_by_sharp_edges.html" );
+
+ LightApp_Application* app = (LightApp_Application*)(SUIT_Session::session()->activeApplication());
+ if (app)
+ app->onHelpContextModule(mySMESHGUI ? app->moduleName(mySMESHGUI->moduleName()) : QString(""), myHelpFileName);
+ else {
+ QString platform;
+#ifdef WIN32
+ platform = "winapplication";
+#else
+ platform = "application";
+#endif
+ SUIT_MessageBox::warning(this, tr("WRN_WARNING"),
+ tr("EXTERNAL_BROWSER_CANNOT_SHOW_PAGE").
+ arg(app->resourceMgr()->stringValue("ExternalBrowser",
+ platform)).
+ arg(myHelpFileName));
+ }
+}
+
+//=================================================================================
+// function : SelectionIntoArgument()
+// purpose : Called when selection as changed or other case
+//=================================================================================
+
+void SMESHGUI_FaceGroupsSeparatedByEdgesDlg::SelectionIntoArgument()
+{
+ if (!GroupButtons->isEnabled()) // inactive
+ return;
+
+ // get selected mesh
+ SALOME_ListIO aList;
+ mySelectionMgr->selectedObjects(aList);
+
+ for ( SALOME_ListIteratorOfListIO it( aList ); it.More(); it.Next() )
+ {
+ Handle(SALOME_InteractiveObject) IO = it.Value();
+ CORBA::Object_var anObj = SMESH::IObjectToObject( IO );
+ SMESH::SMESH_Mesh_var aMesh = SMESH::SMESH_Mesh::_narrow( anObj );
+ if ( aMesh->_is_nil() || aMesh->NbFaces() == 0 )
+ continue;
+
+ if ( !aMesh->_is_equivalent( myMesh ))
+ onDisplaySimulation( false );
+
+ myMesh = aMesh;
+ myMeshName->setText( IO->getName() );
+ }
+
+ bool ok = !myMesh->_is_nil();
+
+ buttonOk->setEnabled( ok );
+ buttonApply->setEnabled( ok );
+
+ onDisplaySimulation( ok );
+}
+
+//=================================================================================
+// function : DeactivateActiveDialog()
+// purpose :
+//=================================================================================
+
+void SMESHGUI_FaceGroupsSeparatedByEdgesDlg::DeactivateActiveDialog()
+{
+ if (GroupArgs->isEnabled())
+ {
+ GroupArgs->setEnabled(false);
+ GroupButtons->setEnabled(false);
+ mySMESHGUI->ResetState();
+ mySMESHGUI->SetActiveDialogBox(0);
+ }
+}
+
+//=================================================================================
+// function : ActivateThisDialog()
+// purpose :
+//=================================================================================
+
+void SMESHGUI_FaceGroupsSeparatedByEdgesDlg::ActivateThisDialog()
+{
+ /* Emit a signal to deactivate the active dialog */
+ mySMESHGUI->EmitSignalDeactivateDialog();
+ GroupArgs->setEnabled(true);
+ GroupButtons->setEnabled(true);
+
+ mySMESHGUI->SetActiveDialogBox((QDialog*)this);
+
+ SelectionIntoArgument();
+}
+
+//=================================================================================
+// function : onDisplaySimulation
+// purpose : Show/Hide preview
+//=================================================================================
+
+void SMESHGUI_FaceGroupsSeparatedByEdgesDlg::onDisplaySimulation( bool toDisplayPreview )
+{
+ SUIT_OverrideCursor aWaitCursor;
+
+ // save current values
+ if ( SUIT_ResourceMgr* resMgr = SUIT_Session::session()->resourceMgr() )
+ {
+ resMgr->setValue( "SMESH", "prev_sharp_angle", myAngle->value() );
+ resMgr->setValue( "SMESH", "prev_create_edges", myCreateEdgesCheck->isChecked() );
+ resMgr->setValue( "SMESH", "prev_use_existing_edges", myUseExistingCheck->isChecked() );
+ }
+
+ if ( myPreviewCheckBox->isChecked() && toDisplayPreview && !myMesh->_is_nil() )
+ {
+ try
+ {
+ SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditPreviewer();
+ SMESH::ListOfEdges_var edges = aMeshEditor->FindSharpEdges( myAngle->value(),
+ myUseExistingCheck->isChecked());
+ SMESH::MeshPreviewStruct_var previewData = aMeshEditor->GetPreviewData();
+
+ mySimulation->SetData( previewData.in() );
+ showPreview();
+
+ } catch (...) {
+ hidePreview();
+ }
+ }
+ else
+ {
+ hidePreview();
+ }
+}
--- /dev/null
+// Copyright (C) 2007-2016 CEA/DEN, EDF R&D, OPEN CASCADE
+//
+// This library is free software; you can redistribute it and/or
+// modify it under the terms of the GNU Lesser General Public
+// License as published by the Free Software Foundation; either
+// version 2.1 of the License, or (at your option) any later version.
+//
+// This library is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+// Lesser General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public
+// License along with this library; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+//
+// See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
+//
+
+#ifndef SMESHGUI_FaceGroupsSeparatedByEdges_H
+#define SMESHGUI_FaceGroupsSeparatedByEdges_H
+
+// SMESH includes
+#include "SMESH_SMESHGUI.hxx"
+#include "SMESHGUI_PreviewDlg.h"
+
+#include <SALOMEconfig.h>
+#include CORBA_SERVER_HEADER(SMESH_MeshEditor)
+#include CORBA_SERVER_HEADER(SMESH_Mesh)
+
+class LightApp_SelectionMgr;
+class QCheckBox;
+class QLineEdit;
+class QWidget;
+class QPushButton;
+class SMESHGUI_SpinBox;
+
+/*!
+ * \brief Dialog to create face groups divided by sharp edges
+ */
+
+class SMESHGUI_EXPORT SMESHGUI_FaceGroupsSeparatedByEdgesDlg : public SMESHGUI_PreviewDlg
+{
+ Q_OBJECT
+
+ public:
+
+ SMESHGUI_FaceGroupsSeparatedByEdgesDlg( SMESHGUI* theModule );
+ virtual ~SMESHGUI_FaceGroupsSeparatedByEdgesDlg();
+
+ private slots:
+ void ClickOnOk();
+ bool ClickOnApply();
+ void ClickOnHelp();
+ void SelectionIntoArgument();
+ void DeactivateActiveDialog();
+ void ActivateThisDialog();
+ void reject();
+ void onArgChange() { onDisplaySimulation( true ); }
+ virtual void onDisplaySimulation( bool = true );
+
+ private:
+
+ LightApp_SelectionMgr* mySelectionMgr;
+ QWidget* GroupArgs;
+ QWidget* GroupButtons;
+
+ QLineEdit* myMeshName;
+ SMESHGUI_SpinBox* myAngle;
+ QCheckBox* myCreateEdgesCheck;
+ QCheckBox* myUseExistingCheck;
+
+ QPushButton* buttonOk;
+ QPushButton* buttonCancel;
+ QPushButton* buttonApply;
+ QPushButton* buttonHelp;
+
+ SMESH::SMESH_Mesh_var myMesh;
+};
+
+#endif // SMESHGUI_FaceGroupsSeparatedByEdges_H
{
if ( !geom->_is_nil() ) {
switch ( geom->GetShapeType() ) {
- case GEOM::VERTEX: return SMESH::NODE;
+ case GEOM::VERTEX: return SMESH::ELEM0D; // NODE; -- 0023613
case GEOM::EDGE: return SMESH::EDGE;
case GEOM::WIRE: return SMESH::EDGE;
case GEOM::FACE: return SMESH::FACE;
#include "SMESHGUI.h"
#include "SMESHGUI_IdValidator.h"
#include "SMESHGUI_Utils.h"
+#include "SMESHGUI_MeshEditPreview.h"
#include "SMESHGUI_VTKUtils.h"
#include <SMESH_TypeFilter.hxx>
+#include <SMESH_MeshAlgos.hxx>
#include <SMESH_LogicalFilter.hxx>
+#include <SMDS_Mesh.hxx>
+#include <SMDS_MeshNode.hxx>
#include <LightApp_SelectionMgr.h>
#include <SUIT_OverrideCursor.h>
#include <VTKViewer_CellLocationsArray.h>
#include <vtkProperty.h>
+#include <ElCLib.hxx>
+
#include <SALOMEconfig.h>
#include CORBA_SERVER_HEADER(SMESH_MeshEditor)
#include CORBA_SERVER_HEADER(SMESH_Measurements)
myResult->clear();
}
+/*!
+ \class SMESHGUI_Angle
+ \brief Angle measurement widget.
+
+ Widget to calculate angle between 3 nodes.
+*/
+
+/*!
+ \brief Constructor.
+ \param parent parent widget
+*/
+SMESHGUI_Angle::SMESHGUI_Angle( QWidget* parent )
+ : QWidget( parent )
+{
+ // 3 nodes
+
+ QGroupBox* aNodesGrp = new QGroupBox( tr( "NODES_GROUP" ), this );
+ myNodes = new QLineEdit( aNodesGrp );
+ myNodes->setValidator( new SMESHGUI_IdValidator( this, 3 ));
+ QHBoxLayout* aNodesLayout = new QHBoxLayout( aNodesGrp );
+ aNodesLayout->addWidget( myNodes );
+
+ // Compute button
+ QPushButton* aCompute = new QPushButton( tr( "COMPUTE" ), this );
+
+ // Angle
+
+ QGroupBox* aResultGrp = new QGroupBox( tr( "RESULT" ), this );
+
+ myResult = new QLineEdit;
+ myResult->setReadOnly( true );
+
+ QHBoxLayout* aResultLayout = new QHBoxLayout( aResultGrp );
+ aResultLayout->addWidget( myResult );
+
+ // Layout
+
+ QGridLayout* aMainLayout = new QGridLayout( this );
+ aMainLayout->setMargin( MARGIN );
+ aMainLayout->setSpacing( SPACING );
+
+ aMainLayout->addWidget( aNodesGrp, 0, 0, 1, 2 );
+ aMainLayout->addWidget( aCompute, 1, 0 );
+ aMainLayout->addWidget( aResultGrp, 2, 0, 1, 2 );
+ aMainLayout->setColumnStretch( 1, 5 );
+ aMainLayout->setRowStretch( 3, 5 );
+
+ // Connections
+ connect( aCompute, SIGNAL( clicked() ), this, SLOT( compute() ));
+
+ // preview
+ myPreview = 0;
+ if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
+ {
+ myPreview = new SMESHGUI_MeshEditPreview( aViewWindow );
+ if ( myPreview && myPreview->GetActor() )
+ myPreview->GetActor()->GetProperty()->SetLineWidth( 5 );
+ }
+ myActor = 0;
+}
+
+SMESHGUI_Angle::~SMESHGUI_Angle()
+{
+ if ( myPreview )
+ delete myPreview;
+}
+
+/*!
+ \brief Setup selection mode
+*/
+void SMESHGUI_Angle::updateSelection()
+{
+ LightApp_SelectionMgr* selMgr = SMESHGUI::selectionMgr();
+
+ disconnect( selMgr, 0, this, 0 );
+ selMgr->clearFilters();
+
+ SMESH::SetPointRepresentation( true );
+ if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
+ aViewWindow->SetSelectionMode( NodeSelection );
+
+ connect( selMgr, SIGNAL( currentSelectionChanged() ), this, SLOT( selectionChanged() ));
+ connect( myNodes, SIGNAL( textEdited( QString ) ), this, SLOT( nodesEdited() ));
+
+ if ( myPoints.empty() )
+ selectionChanged();
+}
+
+/*!
+ \brief Called when selection is changed
+*/
+void SMESHGUI_Angle::selectionChanged()
+{
+ clear();
+ QString nodesString;
+
+ TColStd_IndexedMapOfInteger idsMap;
+ SALOME_ListIO selected;
+ SMESHGUI::selectionMgr()->selectedObjects( selected );
+ selected.Reverse(); // to keep order of selection
+
+ SALOME_ListIteratorOfListIO ioIterator( selected );
+ for ( ; ioIterator.More(); ioIterator.Next() )
+ {
+ Handle(SALOME_InteractiveObject) IO = ioIterator.Value();
+
+ idsMap.Clear();
+ if ( SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector() )
+ selector->GetIndex( IO, idsMap );
+
+ if ( SMESH_Actor* actor = SMESH::FindActorByEntry( IO->getEntry() ))
+ {
+ myActor = actor;
+ for ( int i = 1; i <= idsMap.Extent() && myPoints.size() < 3; ++i )
+ if ( addPointByActor( idsMap(i) ))
+ nodesString += QString(" %1").arg( idsMap(i) );
+ idsMap.Clear();
+ }
+ SMESH::SMESH_IDSource_var obj = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>( IO );
+ if ( !CORBA::is_nil( obj ) )
+ {
+ myIDSrc = obj;
+ for ( int i = 1; i <= idsMap.Extent() && myPoints.size() < 3; ++i )
+ if ( addPointByIDSource( idsMap(i) ))
+ nodesString += QString(" %1").arg( idsMap(i) );
+ }
+ }
+
+ myNodes->setText( nodesString );
+}
+
+//=======================================================================
+//function : clear
+//purpose : Erase preview and result
+//=======================================================================
+
+void SMESHGUI_Angle::clear()
+{
+ myPoints.clear();
+ myResult->clear();
+ if ( myPreview && myPreview->GetActor())
+ {
+ myPreview->GetActor()->SetVisibility( false );
+ if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
+ aViewWindow->Repaint();
+ }
+}
+
+//=======================================================================
+//function : addPointByActor
+//purpose : append to myPoints XYZ got from myActor
+//=======================================================================
+
+bool SMESHGUI_Angle::addPointByActor( int id )
+{
+ size_t nbP = myPoints.size();
+
+ if ( myActor )
+ {
+ TVisualObjPtr obj = myActor->GetObject();
+ if ( SMDS_Mesh* mesh = obj->GetMesh() )
+ if ( const SMDS_MeshNode* node = mesh->FindNode( id ))
+ {
+ SMESH::PointStruct p = { node->X(), node->Y(), node->Z() };
+ myPoints.push_back( p );
+ }
+ }
+ return nbP < myPoints.size();
+}
+
+//=======================================================================
+//function : addPointByIDSource
+//purpose : append to myPoints XYZ got from myIDSrc
+//=======================================================================
+
+bool SMESHGUI_Angle::addPointByIDSource( int id )
+{
+ size_t nbP = myPoints.size();
+
+ if ( !myIDSrc->_is_nil() )
+ {
+ SMESH::SMESH_Mesh_var mesh = myIDSrc->GetMesh();
+ if ( !mesh->_is_nil() )
+ {
+ SMESH::double_array_var xyz = mesh->GetNodeXYZ( id );
+ if ( xyz->length() == 3 )
+ {
+ SMESH::PointStruct p = { xyz[0], xyz[1], xyz[2] };
+ myPoints.push_back( p );
+ }
+ }
+ }
+ return nbP < myPoints.size();
+}
+
+//=======================================================================
+//function : nodesEdited
+//purpose : SLOT called when the user types node IDs
+//=======================================================================
+
+void SMESHGUI_Angle::nodesEdited()
+{
+ clear();
+
+ TColStd_MapOfInteger ID;
+ QStringList ids = myNodes->text().split( " ", QString::SkipEmptyParts );
+ foreach ( QString idStr, ids )
+ {
+ int id = idStr.trimmed().toLong();
+ if (( !ID.Contains( id )) &&
+ ( addPointByActor( id ) || addPointByIDSource( id )))
+ ID.Add( id );
+ }
+
+ SVTK_Selector* selector = SMESH::GetViewWindow()->GetSelector();
+ if ( myActor && selector )
+ {
+ Handle(SALOME_InteractiveObject) IO = myActor->getIO();
+ selector->AddOrRemoveIndex( IO, ID, false );
+ if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow() )
+ aViewWindow->highlight( IO, true, true );
+ }
+}
+
+//=======================================================================
+//function : compute
+//purpose : SLOT. Compute angle and show preview
+//=======================================================================
+
+void SMESHGUI_Angle::compute()
+{
+ if ( myPoints.size() != 3 )
+ return;
+
+ // --------------
+ // compute angle
+ // --------------
+
+ SMESH::Measurements_var measure = SMESHGUI::GetSMESHGen()->CreateMeasurements();
+ double radians = measure->Angle( myPoints[0], myPoints[1], myPoints[2] );
+ measure->UnRegister();
+ if ( radians < 0 )
+ return;
+
+ int precision = SMESHGUI::resourceMgr()->integerValue( "SMESH", "length_precision", 6 );
+ myResult->setText( QString::number( radians * 180 / M_PI,
+ precision > 0 ? 'f' : 'g', qAbs( precision )));
+
+ // -------------
+ // show preview
+ // -------------
+
+ if ( !myPreview || !myPreview->GetActor() )
+ return;
+
+ SMESH::MeshPreviewStruct preveiwData;
+
+ const double anglePerSeg = 5 * M_PI/180; // angle per an arc segment
+ const double arcRadiusFactor = 0.5; // arc position, from p1
+
+ gp_Pnt p0 ( myPoints[0].x, myPoints[0].y, myPoints[0].z );
+ gp_Pnt p1 ( myPoints[1].x, myPoints[1].y, myPoints[1].z );
+ gp_Pnt p2 ( myPoints[2].x, myPoints[2].y, myPoints[2].z );
+ gp_Vec vec10( p1, p0 ), vec12( p1, p2 ), norm( vec10 ^ vec12 );
+
+ if ( norm.Magnitude() <= gp::Resolution() ) // 180 degrees
+ norm = getNormal( vec10 );
+
+ double len10 = vec10.Magnitude();
+ double len12 = vec12.Magnitude();
+ double lenMax = Max( len10, len12 );
+ double arcRadius = arcRadiusFactor * lenMax;
+
+ p0 = p1.Translated( lenMax * vec10.Normalized() );
+ p2 = p1.Translated( lenMax * vec12.Normalized() );
+
+ gp_Circ arc( gp_Ax2( p1, norm, vec10 ), arcRadius );
+
+ int nbRadialSegmensts = ceil( radians / anglePerSeg ) + 1;
+ int nbNodes = 3 + ( nbRadialSegmensts + 1 );
+
+ // coordinates
+ preveiwData.nodesXYZ.length( nbNodes );
+ int iP = 0;
+ for ( ; iP < nbRadialSegmensts + 1; ++iP )
+ {
+ double u = double( iP ) / nbRadialSegmensts * radians;
+ gp_Pnt p = ElCLib::Value( u, arc );
+ preveiwData.nodesXYZ[ iP ].x = p.X();
+ preveiwData.nodesXYZ[ iP ].y = p.Y();
+ preveiwData.nodesXYZ[ iP ].z = p.Z();
+ }
+ int iP0 = iP;
+ preveiwData.nodesXYZ[ iP ].x = p0.X();
+ preveiwData.nodesXYZ[ iP ].y = p0.Y();
+ preveiwData.nodesXYZ[ iP ].z = p0.Z();
+ int iP1 = ++iP;
+ preveiwData.nodesXYZ[ iP ].x = p1.X();
+ preveiwData.nodesXYZ[ iP ].y = p1.Y();
+ preveiwData.nodesXYZ[ iP ].z = p1.Z();
+ int iP2 = ++iP;
+ preveiwData.nodesXYZ[ iP ].x = p2.X();
+ preveiwData.nodesXYZ[ iP ].y = p2.Y();
+ preveiwData.nodesXYZ[ iP ].z = p2.Z();
+
+ // connectivity
+ preveiwData.elementConnectivities.length( 2 * ( 2 + nbRadialSegmensts ));
+ for ( int iSeg = 0; iSeg < nbRadialSegmensts; ++iSeg )
+ {
+ preveiwData.elementConnectivities[ iSeg * 2 + 0 ] = iSeg;
+ preveiwData.elementConnectivities[ iSeg * 2 + 1 ] = iSeg + 1;
+ }
+ int iSeg = nbRadialSegmensts;
+ preveiwData.elementConnectivities[ iSeg * 2 + 0 ] = iP0;
+ preveiwData.elementConnectivities[ iSeg * 2 + 1 ] = iP1;
+ ++iSeg;
+ preveiwData.elementConnectivities[ iSeg * 2 + 0 ] = iP1;
+ preveiwData.elementConnectivities[ iSeg * 2 + 1 ] = iP2;
+
+ // types
+ preveiwData.elementTypes.length( 2 + nbRadialSegmensts );
+ SMESH::ElementSubType type = { SMESH::EDGE, /*isPoly=*/false, /*nbNodesInElement=*/2 };
+ for ( CORBA::ULong i = 0; i < preveiwData.elementTypes.length(); ++i )
+ preveiwData.elementTypes[ i ] = type;
+
+ myPreview->SetData( preveiwData );
+}
+
+//================================================================================
+/*!
+ * \brief Return normal to a plane of drawing in the case of 180 degrees angle
+ */
+//================================================================================
+
+gp_Vec SMESHGUI_Angle::getNormal(const gp_Vec& vec10 )
+{
+ gp_XYZ norm;
+
+ // try to get normal by a face at the 2nd node
+ if ( myActor && myActor->GetObject()->GetMesh() )
+ {
+ QStringList ids = myNodes->text().split( " ", QString::SkipEmptyParts );
+ SMDS_Mesh* mesh = myActor->GetObject()->GetMesh();
+ if ( const SMDS_MeshNode* n = mesh->FindNode( ids[1].trimmed().toLong() ))
+ {
+ SMDS_ElemIteratorPtr faceIt = n->GetInverseElementIterator( SMDSAbs_Face );
+ while ( faceIt->more() )
+ if ( SMESH_MeshAlgos::FaceNormal( faceIt->next(), norm ))
+ return norm;
+ }
+ }
+ int iMinCoord = 1;
+ if ( vec10.Coord( iMinCoord ) > vec10.Y() ) iMinCoord = 2;
+ if ( vec10.Coord( iMinCoord ) > vec10.Z() ) iMinCoord = 3;
+
+ gp_Vec vec = vec10;
+ vec.SetCoord( iMinCoord, vec10.Coord( iMinCoord ) + 1. );
+
+ return vec ^ vec10;
+}
+
/*!
\class SMESHGUI_MeshInfoDlg
\brief Centralized dialog box for the measurements
\param page specifies the dialog page to be shown at the start-up
*/
SMESHGUI_MeasureDlg::SMESHGUI_MeasureDlg( QWidget* parent, int page )
-: QDialog( parent )
+ : QDialog( parent )
{
setModal( false );
setAttribute( Qt::WA_DeleteOnClose, true );
myBasicProps = new SMESHGUI_BasicProperties( myTabWidget );
int aBasicPropInd = myTabWidget->addTab( myBasicProps, resMgr->loadPixmap( "SMESH", tr( "ICON_MEASURE_BASIC_PROPS" ) ), tr( "BASIC_PROPERTIES" ) );
+ myAngle = new SMESHGUI_Angle( myTabWidget );
+ int aAngleInd = myTabWidget->addTab( myAngle, resMgr->loadPixmap( "SMESH", tr( "ICON_MEASURE_ANGLE" ) ), tr( "ANGLE" ) );
+
// buttons
QPushButton* okBtn = new QPushButton( tr( "SMESH_BUT_OK" ), this );
okBtn->setAutoDefault( true );
anInd = aMinDistInd;
} else if ( page == BoundingBox ) {
anInd = aBndBoxInd;
+ } else if ( page == Angle ) {
+ anInd = aAngleInd;
} else if ( page == Length || page == Area || page == Volume ) {
myBasicProps->setMode( (SMESHGUI_BasicProperties::Mode)(page - Length) );
anInd = aBasicPropInd;
myMinDist->updateSelection();
else if ( myTabWidget->currentIndex() == BoundingBox )
myBndBox->updateSelection();
+ else if ( myTabWidget->currentWidget() == myAngle )
+ myAngle->updateSelection();
else {
myBndBox->erasePreview();
myBasicProps->updateSelection();
aHelpFile = "measurements.html#min-distance-anchor";
} else if ( myTabWidget->currentIndex() == BoundingBox ) {
aHelpFile = "measurements.html#bounding-box-anchor";
+ } else if ( myTabWidget->currentWidget() == myAngle ) {
+ aHelpFile = "measurements.html#angle-anchor";
} else {
aHelpFile = "measurements.html#basic-properties-anchor";
}
class SALOME_Actor;
class SMESH_Actor;
class SMESHGUI_IdValidator;
+class SMESHGUI_MeshEditPreview;
#include <SALOMEconfig.h>
#include CORBA_SERVER_HEADER(SMESH_Mesh)
+#include <gp_Vec.hxx>
+
class SMESHGUI_EXPORT SMESHGUI_MinDistance : public QWidget
{
Q_OBJECT;
SUIT_SelectionFilter* myFilter;
};
+class SMESHGUI_EXPORT SMESHGUI_Angle : public QWidget
+{
+ Q_OBJECT;
+
+public:
+
+ SMESHGUI_Angle( QWidget* = 0 );
+ ~SMESHGUI_Angle();
+
+ void deactivate();
+ void updateSelection();
+
+private slots:
+ void selectionChanged();
+ void nodesEdited();
+ void compute();
+ void clear();
+
+private:
+
+ bool addPointByActor( int id );
+ bool addPointByIDSource( int id );
+ gp_Vec getNormal(const gp_Vec& vec10 );
+
+ QLineEdit* myNodes;
+ QLineEdit* myResult;
+
+ SMESH::SMESH_IDSource_var myIDSrc;
+ SMESH_Actor* myActor;
+
+ std::vector< SMESH::PointStruct > myPoints;
+ SMESHGUI_MeshEditPreview* myPreview;
+};
+
class SMESHGUI_EXPORT SMESHGUI_MeasureDlg : public QDialog
{
Q_OBJECT;
BoundingBox, //!< bounding box
Length, //!< length
Area, //!< area
- Volume //!< volume
+ Volume, //!< volume
+ Angle
};
SMESHGUI_MeasureDlg( QWidget* = 0, int = MinDistance );
SMESHGUI_MinDistance* myMinDist;
SMESHGUI_BoundingBox* myBndBox;
SMESHGUI_BasicProperties* myBasicProps;
+ SMESHGUI_Angle* myAngle;
};
#endif // SMESHGUI_MEASUREMENTS_H
OpIntersectGroups = 2061, // MENU MESH - INTERSECT GROUPS
OpCutGroups = 2062, // MENU MESH - CUT GROUPS
OpGroupUnderlyingElem = 2070, // MENU MESH - GROUP OF UNDERLYING ENTITIES
+ OpFaceGroupsByEdges = 2071, // MENU MESH - FACE GROUPS SEPARATED by EDGES
OpEditGroupPopup = 2080, // POPUP MENU - EDIT GROUP
OpAddElemGroupPopup = 2081, // POPUP MENU - ADD ELEMENTS TO GROUP
OpRemoveElemGroupPopup = 2082, // POPUP MENU - REMOVE ELEMENTS FROM GROUP
OpPropertiesVolume = 5002, // MENU MEASUREMENTS - BASIC PROPERTIES - VOLUME
OpMinimumDistance = 5003, // MENU MEASUREMENTS - MINIMUM DISTANCE
OpBoundingBox = 5004, // MENU MEASUREMENTS - BOUNDING BOX
+ OpAngle = 5005, // MENU MEASUREMENTS - ANGLE
// Hypothesis ---------------------//--------------------------------
OpEditHypothesis = 6000, // POPUP MENU - EDIT HYPOTHESIS
OpUnassign = 6001, // POPUP MENU - UNASSIGN
if (!aStudy)
return OK;
+ SUIT_ResourceMgr* resMgr;
{
OK = true;
vtkRenderer *aRenderer = aViewWnd->getRenderer();
anActor->SetVisibility(true);
if (theAction == eDisplayOnly) aRenderer->ResetCameraClippingRange();
aStudy->setVisibilityState(theEntry, Qtx::ShownState);
+ if (( theAction == eDisplayOnly ) &&
+ ( resMgr = SMESHGUI::resourceMgr() ) &&
+ ( resMgr->booleanValue( "SMESH", "fitall_on_displayonly", false )))
+ FitAll(); // PAL23615
break;
case eErase:
//MESSAGE("--- erase " << anActor);
anActor->SetVisibility(true);
aStudy->setVisibilityState(theEntry, Qtx::ShownState);
// FitAll(); - PAL16770(Display of a group performs an automatic fit all)
- if (needFitAll) FitAll();
- } else {
+ if (( !needFitAll ) &&
+ ( theAction == eDisplayOnly ) &&
+ ( resMgr = SMESHGUI::resourceMgr() ))
+ {
+ needFitAll = resMgr->booleanValue( "SMESH", "fitall_on_displayonly", false );
+ }
+ if ( needFitAll )
+ FitAll();
+ }
+ else {
OK = false;
}
}
SMESH_ActorProps::props()->reset();
QColor
- aHiColor = mgr->colorValue( "SMESH", "selection_object_color", Qt::white ),
+ //aHiColor = mgr->colorValue( "SMESH", "selection_object_color", Qt::white ),
aSelColor = mgr->colorValue( "SMESH", "selection_element_color", Qt::yellow ),
aPreColor = mgr->colorValue( "SMESH", "highlight_color", Qt::cyan );
aCollection->InitTraversal();
while ( vtkActor *anAct = aCollection->GetNextActor() ) {
if ( SMESH_Actor *anActor = dynamic_cast<SMESH_Actor*>(anAct) ) {
- anActor->UpdateSelectionProps();
+ anActor->UpdateSelectionProps();
}
}
}
<source>ICON_UNDERLYING_ELEMS</source>
<translation>mesh_extractGroup.png</translation>
</message>
+ <message>
+ <source>ICON_FACE_GROUPS_BY_EDGES</source>
+ <translation>mesh_face_groups_by_edges.png</translation>
+ </message>
<message>
<source>ICON_2D_FROM_3D</source>
<translation>mesh_2d_from_3d.png</translation>
<source>ICON_MEASURE_BND_BOX</source>
<translation>mesh_bounding_box.png</translation>
</message>
+ <message>
+ <source>ICON_MEASURE_ANGLE</source>
+ <translation>mesh_angle_measure.png</translation>
+ </message>
<message>
<source>ICON_SHOW</source>
<translation>mesh_show.png</translation>
<source>TOP_MEASURE_VOLUME</source>
<translation>Volume</translation>
</message>
+ <message>
+ <source>MEN_MEASURE_ANGLE</source>
+ <translation>Angle</translation>
+ </message>
+ <message>
+ <source>STB_MEASURE_ANGLE</source>
+ <translation>Measure angle defined by three nodes</translation>
+ </message>
+ <message>
+ <source>TOP_MEASURE_ANGLE</source>
+ <translation>Angle</translation>
+ </message>
<message>
<source>MEN_MOVE</source>
<translation>Move Node</translation>
<source>MEN_UNDERLYING_ELEMS</source>
<translation>Group based on nodes of other groups</translation>
</message>
+ <message>
+ <source>MEN_FACE_GROUPS_BY_EDGES</source>
+ <translation>Face groups separated by sharp edges</translation>
+ </message>
<message>
<source>MEN_UPDATE</source>
<translation>Update</translation>
<source>SMESH_AUTO_DIM</source>
<translation>Automatically define space dimension</translation>
</message>
+ <message>
+ <source>SMESH_ZTOLERANCE</source>
+ <translation>Z tolerance</translation>
+ </message>
<message>
<source>SMESH_REQUIRED_GROUPS</source>
<translation>Create groups of required entities</translation>
<source>STB_UNDERLYING_ELEMS</source>
<translation>Create groups of entities basing on nodes of other groups</translation>
</message>
+ <message>
+ <source>STB_FACE_GROUPS_BY_EDGES</source>
+ <translation>Create face groups separated by sharp edges</translation>
+ </message>
<message>
<source>STB_UPDATE</source>
<translation>Update</translation>
<source>TOP_UNDERLYING_ELEMS</source>
<translation>Create groups of entities basing on nodes of other groups</translation>
</message>
+ <message>
+ <source>TOP_FACE_GROUPS_BY_EDGES</source>
+ <translation>Create groups of faces separated by sharp edges</translation>
+ </message>
<message>
<source>TOP_UPDATE</source>
<translation>Update</translation>
<translation>Export Fields</translation>
</message>
</context>
+<context>
+ <name>SMESHGUI_FaceGroupsSeparatedByEdgesDlg</name>
+ <message>
+ <source>CAPTION</source>
+ <translation>Face groups separated by sharp edges</translation>
+ </message>
+ <message>
+ <source>SHARP_ANGLE</source>
+ <translation>Sharp angle</translation>
+ </message>
+ <message>
+ <source>CREATE_EDGES</source>
+ <translation>Create edges</translation>
+ </message>
+ <message>
+ <source>USE_EXISTING_EDGES</source>
+ <translation>Use existing edges</translation>
+ </message>
+ <message>
+ <source>NB_GROUPS_CREATED</source>
+ <translation>%1 groups of faces created</translation>
+ </message>
+</context>
<context>
<name>SMESHGUI_OffsetDlg</name>
<message>
<source>PREF_SHOW_WARN</source>
<translation>Show warning when exporting group</translation>
</message>
+ <message>
+ <source>PREF_ZTOLERANCE</source>
+ <translation>Z tolerance for MED export</translation>
+ </message>
<message>
<source>PREF_GROUP_SEGMENT_LENGTH</source>
<translation>Automatic parameters</translation>
</message>
<message>
<source>PREF_DISPLAY_MODE_GROUP</source>
- <translation>Display mode</translation>
+ <translation>Display</translation>
</message>
<message>
<source>PREF_DISPLAY_MODE</source>
<translation>Default display mode</translation>
</message>
+ <message>
+ <source>PREF_FITALL_ON_DISPLAYONLY</source>
+ <translation>Fit All upon Show Only</translation>
+ </message>
<message>
<source>PREF_ELEMENTS</source>
<translation>Elements</translation>
<translation>Compute</translation>
</message>
</context>
+<context>
+ <name>SMESHGUI_Angle</name>
+ <message>
+ <source>NODES_GROUP</source>
+ <translation>Three nodes</translation>
+ </message>
+ <message>
+ <source>RESULT</source>
+ <translation>Angle in degrees</translation>
+ </message>
+ <message>
+ <source>COMPUTE</source>
+ <translation>Compute</translation>
+ </message>
+</context>
<context>
<name>SMESHGUI_CopyMeshDlg</name>
<message>
<source>BASIC_PROPERTIES</source>
<translation>Basic Properties</translation>
</message>
+ <message>
+ <source>ANGLE</source>
+ <translation>Angle</translation>
+ </message>
</context>
<context>
<name>SMESHGUI_BoundingBox</name>
#include <IntAna_Quadric.hxx>
#include <gp_Lin.hxx>
#include <gp_Pln.hxx>
+#include <NCollection_DataMap.hxx>
#include <limits>
#include <numeric>
ElementBndBoxTree*& ebbTree = _ebbTree[ _elementType ];
if ( !ebbTree )
- ebbTree = new ElementBndBoxTree( *_mesh, _elementType );
+ ebbTree = new ElementBndBoxTree( *_mesh, _elementType, _meshPartIt );
gp_XYZ p = point.XYZ();
ElementBndBoxTree* ebbLeaf = ebbTree->getLeafAtPoint( p );
- const Bnd_B3d* box = ebbLeaf->getBox();
+ const Bnd_B3d* box = ebbLeaf ? ebbLeaf->getBox() : ebbTree->getBox();
double radius = ( box->CornerMax() - box->CornerMin() ).Modulus();
ElementBndBoxTree::TElemSeq elems;
//================================================================================
/*!
- * \brief Return of a point relative to a segment
+ * \brief Return position of a point relative to a segment
* \param point2D - the point to analyze position of
- * \param xyVec - end points of segments
+ * \param segEnds - end points of segments
* \param index0 - 0-based index of the first point of segment
* \param posToFindOut - flags of positions to detect
* \retval PointPos - point position
}
// compute distance
- PointPos pos = *pntPosSet.begin();
- switch ( pos._name )
- {
- case POS_LEFT:
- {
- // point is most close to an edge
- gp_Vec edge( xyz[ pos._index ], xyz[ pos._index+1 ]);
- gp_Vec n1p ( xyz[ pos._index ], point );
- double u = ( edge * n1p ) / edge.SquareMagnitude(); // param [0,1] on the edge
- // projection of the point on the edge
- gp_XYZ proj = xyz[ pos._index ] + u * edge.XYZ();
- if ( closestPnt ) *closestPnt = proj;
- return point.Distance( proj );
- }
- case POS_RIGHT:
+
+ double minDist2 = Precision::Infinite();
+ for ( std::set< PointPos >::iterator posIt = pntPosSet.begin(); posIt != pntPosSet.end(); ++posIt)
{
- // point is inside the face
- double distToFacePlane = Abs( tmpPnt.Y() );
- if ( closestPnt )
+ PointPos pos = *posIt;
+ if ( pos._name != pntPosSet.begin()->_name )
+ break;
+ switch ( pos._name )
+ {
+ case POS_LEFT: // point is most close to an edge
+ {
+ gp_Vec edge( xyz[ pos._index ], xyz[ pos._index+1 ]);
+ gp_Vec n1p ( xyz[ pos._index ], point );
+ double u = ( edge * n1p ) / edge.SquareMagnitude(); // param [0,1] on the edge
+ // projection of the point on the edge
+ gp_XYZ proj = xyz[ pos._index ] + u * edge.XYZ();
+ double dist2 = point.SquareDistance( proj );
+ if ( dist2 < minDist2 )
+ {
+ if ( closestPnt ) *closestPnt = proj;
+ minDist2 = dist2;
+ }
+ break;
+ }
+
+ case POS_RIGHT: // point is inside the face
{
- if ( distToFacePlane < std::numeric_limits<double>::min() ) {
- *closestPnt = point.XYZ();
+ double distToFacePlane = Abs( tmpPnt.Y() );
+ if ( closestPnt )
+ {
+ if ( distToFacePlane < std::numeric_limits<double>::min() ) {
+ *closestPnt = point.XYZ();
+ }
+ else {
+ tmpPnt.SetY( 0 );
+ trsf.Inverted().Transforms( tmpPnt );
+ *closestPnt = tmpPnt;
+ }
}
- else {
- tmpPnt.SetY( 0 );
- trsf.Inverted().Transforms( tmpPnt );
- *closestPnt = tmpPnt;
+ return distToFacePlane;
+ }
+
+ case POS_VERTEX: // point is most close to a node
+ {
+ double dist2 = point.SquareDistance( xyz[ pos._index ]);
+ if ( dist2 < minDist2 )
+ {
+ if ( closestPnt ) *closestPnt = xyz[ pos._index ];
+ minDist2 = dist2;
}
+ break;
+ }
+ default:;
+ return badDistance;
}
- return distToFacePlane;
- }
- case POS_VERTEX:
- {
- // point is most close to a node
- gp_Vec distVec( point, xyz[ pos._index ]);
- return distVec.Magnitude();
- }
- default:;
}
- return badDistance;
+ return Sqrt( minDist2 );
}
//=======================================================================
return face;
}
+//================================================================================
+/*!
+ * Return sharp edges of faces and non-manifold ones. Optionally adds existing edges.
+ */
+//================================================================================
+
+std::vector< SMESH_MeshAlgos::Edge >
+SMESH_MeshAlgos::FindSharpEdges( SMDS_Mesh* theMesh,
+ double theAngle,
+ bool theAddExisting )
+{
+ std::vector< Edge > resultEdges;
+ if ( !theMesh ) return resultEdges;
+
+ typedef std::pair< bool, const SMDS_MeshNode* > TIsSharpAndMedium;
+ typedef NCollection_DataMap< SMESH_TLink, TIsSharpAndMedium, SMESH_TLink > TLinkSharpMap;
+
+ TLinkSharpMap linkIsSharp( theMesh->NbFaces() );
+ TIsSharpAndMedium sharpMedium( true, 0 );
+ bool & isSharp = sharpMedium.first;
+ const SMDS_MeshNode* & nMedium = sharpMedium.second;
+
+ if ( theAddExisting )
+ {
+ for ( SMDS_EdgeIteratorPtr edgeIt = theMesh->edgesIterator(); edgeIt->more(); )
+ {
+ const SMDS_MeshElement* edge = edgeIt->next();
+ nMedium = ( edge->IsQuadratic() ) ? edge->GetNode(2) : 0;
+ linkIsSharp.Bind( SMESH_TLink( edge->GetNode(0), edge->GetNode(1)), sharpMedium );
+ }
+ }
+
+ // check angles between face normals
+
+ const double angleCos = Cos( theAngle * M_PI / 180. ), angleCos2 = angleCos * angleCos;
+ gp_XYZ norm1, norm2;
+ std::vector< const SMDS_MeshNode* > faceNodes, linkNodes(2);
+ std::vector<const SMDS_MeshElement *> linkFaces;
+
+ int nbSharp = linkIsSharp.Extent();
+ for ( SMDS_FaceIteratorPtr faceIt = theMesh->facesIterator(); faceIt->more(); )
+ {
+ const SMDS_MeshElement* face = faceIt->next();
+ size_t nbCorners = face->NbCornerNodes();
+
+ faceNodes.assign( face->begin_nodes(), face->end_nodes() );
+ if ( faceNodes.size() == nbCorners )
+ faceNodes.resize( nbCorners * 2, 0 );
+
+ const SMDS_MeshNode* nPrev = faceNodes[ nbCorners-1 ];
+ for ( size_t i = 0; i < nbCorners; ++i )
+ {
+ SMESH_TLink link( nPrev, faceNodes[i] );
+ if ( !linkIsSharp.IsBound( link ))
+ {
+ linkNodes[0] = link.node1();
+ linkNodes[1] = link.node2();
+ linkFaces.clear();
+ theMesh->GetElementsByNodes( linkNodes, linkFaces, SMDSAbs_Face );
+
+ isSharp = false;
+ if ( linkFaces.size() > 2 )
+ {
+ isSharp = true;
+ }
+ else if ( linkFaces.size() == 2 &&
+ FaceNormal( linkFaces[0], norm1, /*normalize=*/false ) &&
+ FaceNormal( linkFaces[1], norm2, /*normalize=*/false ))
+ {
+ double dot = norm1 * norm2; // == cos * |norm1| * |norm2|
+ if (( dot < 0 ) == ( angleCos < 0 ))
+ {
+ double cos2 = dot * dot / norm1.SquareModulus() / norm2.SquareModulus();
+ isSharp = ( angleCos < 0 ) ? ( cos2 > angleCos2 ) : ( cos2 < angleCos2 );
+ }
+ else
+ {
+ isSharp = ( angleCos > 0 );
+ }
+ }
+ nMedium = faceNodes[( i-1+nbCorners ) % nbCorners + nbCorners ];
+
+ linkIsSharp.Bind( link, sharpMedium );
+ nbSharp += isSharp;
+ }
+
+ nPrev = faceNodes[i];
+ }
+ }
+
+ resultEdges.resize( nbSharp );
+ TLinkSharpMap::Iterator linkIsSharpIter( linkIsSharp );
+ for ( int i = 0; linkIsSharpIter.More() && i < nbSharp; linkIsSharpIter.Next() )
+ {
+ const SMESH_TLink& link = linkIsSharpIter.Key();
+ const TIsSharpAndMedium& isSharpMedium = linkIsSharpIter.Value();
+ if ( isSharpMedium.first )
+ {
+ Edge & edge = resultEdges[ i++ ];
+ edge._node1 = link.node1();
+ edge._node2 = link.node2();
+ edge._medium = isSharpMedium.second;
+ }
+ }
+
+ return resultEdges;
+}
+
+//================================================================================
+/*!
+ * Distribute all faces of the mesh between groups using given edges as group boundaries
+ */
+//================================================================================
+
+std::vector< std::vector< const SMDS_MeshElement* > >
+SMESH_MeshAlgos::SeparateFacesByEdges( SMDS_Mesh* theMesh, const std::vector< Edge >& theEdges )
+{
+ std::vector< std::vector< const SMDS_MeshElement* > > groups;
+ if ( !theMesh ) return groups;
+
+ // build map of face edges (SMESH_TLink) and their faces
+
+ typedef std::vector< const SMDS_MeshElement* > TFaceVec;
+ typedef NCollection_DataMap< SMESH_TLink, TFaceVec, SMESH_TLink > TFacesByLinks;
+ TFacesByLinks facesByLink( theMesh->NbFaces() );
+
+ std::vector< const SMDS_MeshNode* > faceNodes;
+ for ( SMDS_FaceIteratorPtr faceIt = theMesh->facesIterator(); faceIt->more(); )
+ {
+ const SMDS_MeshElement* face = faceIt->next();
+ size_t nbCorners = face->NbCornerNodes();
+
+ faceNodes.assign( face->begin_nodes(), face->end_nodes() );
+ faceNodes.resize( nbCorners + 1 );
+ faceNodes[ nbCorners ] = faceNodes[0];
+
+ face->setIsMarked( false );
+
+ for ( size_t i = 0; i < nbCorners; ++i )
+ {
+ SMESH_TLink link( faceNodes[i], faceNodes[i+1] );
+ TFaceVec* linkFaces = facesByLink.ChangeSeek( link );
+ if ( !linkFaces )
+ {
+ linkFaces = facesByLink.Bound( link, TFaceVec() );
+ linkFaces->reserve(2);
+ }
+ linkFaces->push_back( face );
+ }
+ }
+
+ // remove the given edges from facesByLink map
+
+ for ( size_t i = 0; i < theEdges.size(); ++i )
+ {
+ SMESH_TLink link( theEdges[i]._node1, theEdges[i]._node2 );
+ facesByLink.UnBind( link );
+ }
+
+ // faces connected via links of facesByLink map form a group
+
+ while ( !facesByLink.IsEmpty() )
+ {
+ groups.push_back( TFaceVec() );
+ TFaceVec & group = groups.back();
+
+ group.push_back( TFacesByLinks::Iterator( facesByLink ).Value()[0] );
+ group.back()->setIsMarked( true );
+
+ for ( size_t iF = 0; iF < group.size(); ++iF )
+ {
+ const SMDS_MeshElement* face = group[iF];
+ size_t nbCorners = face->NbCornerNodes();
+ faceNodes.assign( face->begin_nodes(), face->end_nodes() );
+ faceNodes.resize( nbCorners + 1 );
+ faceNodes[ nbCorners ] = faceNodes[0];
+
+ for ( size_t iN = 0; iN < nbCorners; ++iN )
+ {
+ SMESH_TLink link( faceNodes[iN], faceNodes[iN+1] );
+ if ( const TFaceVec* faces = facesByLink.Seek( link ))
+ {
+ const TFaceVec& faceNeighbors = *faces;
+ for ( size_t i = 0; i < faceNeighbors.size(); ++i )
+ if ( !faceNeighbors[i]->isMarked() )
+ {
+ group.push_back( faceNeighbors[i] );
+ faceNeighbors[i]->setIsMarked( true );
+ }
+ facesByLink.UnBind( link );
+ }
+ }
+ }
+ }
+
+ // find faces that are alone in its group; they were not in facesByLink
+
+ int nbInGroups = 0;
+ for ( size_t i = 0; i < groups.size(); ++i )
+ nbInGroups += groups[i].size();
+ if ( nbInGroups < theMesh->NbFaces() )
+ {
+ for ( SMDS_FaceIteratorPtr faceIt = theMesh->facesIterator(); faceIt->more(); )
+ {
+ const SMDS_MeshElement* face = faceIt->next();
+ if ( !face->isMarked() )
+ {
+ groups.push_back( TFaceVec() );
+ groups.back().push_back( face );
+ }
+ }
+ }
+
+ return groups;
+}
+
//================================================================================
/*!
* \brief Calculate normal of a mesh face
bool IsRightOrder( const SMDS_MeshElement* face,
const SMDS_MeshNode* node0,
const SMDS_MeshNode* node1 );
-
/*!
* \brief Mark elements given by SMDS_Iterator
*/
MarkElems( (*it)->nodesIterator(), isMarked );
}
+ // 2 nodes + optional medium node
+ struct Edge
+ {
+ const SMDS_MeshNode* _node1;
+ const SMDS_MeshNode* _node2;
+ const SMDS_MeshNode* _medium;
+ };
+
+ /*!
+ * Return sharp edges of faces and non-manifold ones.
+ * Optionally adds existing edges to the result. Angle is in degrees.
+ */
+ SMESHUtils_EXPORT
+ std::vector< Edge > FindSharpEdges( SMDS_Mesh* mesh,
+ double angle,
+ bool addExisting );
+
+ /*!
+ * Distribute all faces of the mesh between groups using given edges.
+ */
+ SMESHUtils_EXPORT
+ std::vector< std::vector< const SMDS_MeshElement* > >
+ SeparateFacesByEdges( SMDS_Mesh* mesh, const std::vector< Edge >& edges );
typedef std::vector<const SMDS_MeshNode*> TFreeBorder;
normals[i].SetCoord( 0,0,0 ); // TODO find norm by neighbors
}
- const double tol = 1e-3 * Sqrt( minNodeDist );
const double sign = ( theOffset < 0 ? -1 : +1 );
+ const double tol = Min( 1e-3 * Sqrt( minNodeDist ),
+ 1e-2 * theOffset * sign );
// translate new nodes by normal to input faces
gp_XYZ newXYZ;
"MergeElements","MergeEqualElements","SewFreeBorders","SewConformFreeBorders",
"FindCoincidentFreeBorders", "SewCoincidentFreeBorders",
"SewBorderToSide","SewSideElements","ChangeElemNodes","GetLastCreatedNodes",
- "GetLastCreatedElems",
+ "GetLastCreatedElems", "FaceGroupsSeparatedByEdges",
"MirrorMakeMesh","MirrorObjectMakeMesh","TranslateMakeMesh","TranslateObjectMakeMesh",
"Scale","ScaleMakeMesh","RotateMakeMesh","RotateObjectMakeMesh","MakeBoundaryMesh",
"MakeBoundaryElements", "SplitVolumesIntoTetra","SplitHexahedraIntoPrisms",
return grCenter;
}
+
+//=======================================================================
+//function : Angle
+//purpose : Return angle in radians defined by 3 points <(p1,p2,p3)
+//=======================================================================
+
+CORBA::Double Measurements_i::Angle(const SMESH::PointStruct& p1,
+ const SMESH::PointStruct& p2,
+ const SMESH::PointStruct& p3 )
+{
+ gp_Vec v1( p1.x - p2.x, p1.y - p2.y, p1.z - p2.z );
+ gp_Vec v2( p3.x - p2.x, p3.y - p2.y, p3.z - p2.z );
+
+ double angle = -1;
+
+ try
+ {
+ angle = v1.Angle( v2 );
+ }
+ catch(...)
+ {
+ }
+ if ( isnan( angle ))
+ angle = -1;
+
+ return angle;
+}
* gravity center of the source
*/
SMESH::PointStruct GravityCenter(SMESH::SMESH_IDSource_ptr theSource);
+
+ /*!
+ * angle in radians defined by 3 points <(p1,p2,p3)
+ */
+ CORBA::Double Angle(const SMESH::PointStruct& p1,
+ const SMESH::PointStruct& p2,
+ const SMESH::PointStruct& p3 );
};
}
//=============================================================================
/*!
- * \brief Deleter of theNodeSearcher at any compute event occurred
+ * \brief Deleter of theNodeSearcher and theElementSearcher at any compute event occurred
*/
//=============================================================================
*/
//================================================================================
- string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type)
+ string getPartIOR( SMESH::SMESH_IDSource_ptr theMeshPart, SMESH::ElementType type = SMESH::ALL )
{
string partIOR = SMESH_Gen_i::GetORB()->object_to_string( theMeshPart );
if ( SMESH_Group_i* group_i = SMESH::DownCast<SMESH_Group_i*>( theMeshPart ))
return 0;
}
+//=======================================================================
+//function : ProjectPoint
+//purpose : Project a point to a mesh object.
+// Return ID of an element of given type where the given point is projected
+// and coordinates of the projection point.
+// In the case if nothing found, return -1 and []
+//=======================================================================
+
+CORBA::Long SMESH_MeshEditor_i::ProjectPoint(CORBA::Double x,
+ CORBA::Double y,
+ CORBA::Double z,
+ SMESH::SMESH_IDSource_ptr meshObject,
+ SMESH::ElementType type,
+ SMESH::double_array_out projecton)
+ throw (SALOME::SALOME_Exception)
+{
+ if ( CORBA::is_nil( meshObject ))
+ THROW_SALOME_CORBA_EXCEPTION("NULL meshObject", SALOME::BAD_PARAM);
+
+ SMESH_TRY;
+
+ SMESH::SMESH_Mesh_var mesh = meshObject->GetMesh();
+ SMESH_Mesh_i* mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
+ if ( mesh_i != myMesh_i )
+ {
+ SMESH::SMESH_MeshEditor_var editor=
+ myIsPreviewMode ? mesh_i->GetMeshEditPreviewer() : mesh_i->GetMeshEditor();
+ return editor->ProjectPoint( x,y,z, meshObject, type, projecton );
+ }
+
+
+ theSearchersDeleter.Set( myMesh, getPartIOR( meshObject ));
+ if ( !theElementSearcher )
+ {
+ // create a searcher from meshObject
+
+ SMDS_ElemIteratorPtr elemIt;
+ if ( ! SMESH::DownCast<SMESH_Mesh_i*>( meshObject ))
+ elemIt = myMesh_i->GetElements( meshObject, type );
+
+ theElementSearcher = SMESH_MeshAlgos::GetElementSearcher( *getMeshDS(), elemIt );
+ }
+
+ const SMDS_MeshElement* elem = 0;
+ gp_XYZ pProj = theElementSearcher->Project( gp_Pnt( x,y,z ),
+ SMDSAbs_ElementType( type ),
+ &elem );
+
+ projecton = new SMESH::double_array();
+ if ( elem && !elem->IsNull() )
+ {
+ projecton->length( 3 );
+ projecton[0] = pProj.X();
+ projecton[1] = pProj.Y();
+ projecton[2] = pProj.Z();
+ return elem->GetID();
+ }
+
+ SMESH_CATCH( SMESH::throwCorbaException );
+ return -1;
+}
+
//=======================================================================
//function : GetPointState
//purpose : Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
return isGoodOri;
}
+//=======================================================================
+//function : FindSharpEdges
+//purpose : Return sharp edges of faces and non-manifold ones. Optionally add existing edges.
+//=======================================================================
+
+SMESH::ListOfEdges* SMESH_MeshEditor_i::FindSharpEdges(CORBA::Double theAngle,
+ CORBA::Boolean theAddExisting)
+ throw (SALOME::SALOME_Exception)
+{
+ SMESH::ListOfEdges_var resultEdges = new SMESH::ListOfEdges;
+ SMESH_TRY;
+
+ initData();
+
+ std::vector< SMESH_MeshAlgos::Edge > edges =
+ SMESH_MeshAlgos::FindSharpEdges( getMeshDS(), theAngle, theAddExisting );
+
+ if ( myIsPreviewMode ) // fill a preview mesh with edges
+ {
+ TPreviewMesh* mesh = getPreviewMesh( SMDSAbs_Edge );
+ SMDS_Mesh* meshDS = mesh->GetMeshDS();
+ for ( size_t i = 0; i < edges.size(); ++i )
+ {
+ SMESH_NodeXYZ xyz1( edges[i]._node1), xyz2( edges[i]._node2);
+ SMDS_MeshNode* n1 = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
+ SMDS_MeshNode* n2 = meshDS->AddNode( xyz2.X(), xyz2.Y(), xyz2.Z() );
+ if ( edges[i]._medium )
+ {
+ xyz1.Set( edges[i]._medium );
+ SMDS_MeshNode* nm = meshDS->AddNode( xyz1.X(), xyz1.Y(), xyz1.Z() );
+ mesh->GetMeshDS()->AddEdge( n1, n2, nm );
+ }
+ else
+ {
+ mesh->GetMeshDS()->AddEdge( n1, n2 );
+ }
+ }
+ }
+ else
+ {
+ resultEdges->length( edges.size() );
+ for ( size_t i = 0; i < edges.size(); ++i )
+ {
+ resultEdges[ i ].node1 = edges[i]._node1->GetID();
+ resultEdges[ i ].node2 = edges[i]._node2->GetID();
+ resultEdges[ i ].medium = edges[i]._medium ? edges[i]._medium->GetID() : 0;
+ }
+ }
+ SMESH_CATCH( SMESH::throwCorbaException );
+ return resultEdges._retn();
+}
+
//=======================================================================
//function : FindFreeBorders
//purpose : Returns all or only closed FreeBorder's.
*/
//================================================================================
-std::string SMESH_MeshEditor_i::generateGroupName(const std::string& thePrefix)
+std::string SMESH_MeshEditor_i::GenerateGroupName(const std::string& thePrefix)
{
SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
set<std::string> groupNames;
SMESH::long_array_var anIds = GetLastCreatedNodes();
if (anIds->length() > 0) {
std::string anUnindexedName (theNodes->GetName());
- std::string aNewName = generateGroupName(anUnindexedName + "_double");
+ std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
aNewGroup->Add(anIds);
pyDump << aNewGroup << " = ";
SMESH::long_array_var anIds = GetLastCreatedNodes();
if (anIds->length() > 0) {
std::string anUnindexedName (theNodes[0]->GetName());
- std::string aNewName = generateGroupName(anUnindexedName + "_double");
+ std::string aNewName = GenerateGroupName(anUnindexedName + "_double");
aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
aNewGroup->Add(anIds);
pyDump << aNewGroup << " = ";
{
// Create group with newly created elements
CORBA::String_var elemGroupName = theElems->GetName();
- std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
+ std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
{
SMESH::long_array_var anIds = GetLastCreatedElems();
{
// Create group with newly created elements
CORBA::String_var elemGroupName = theElems[0]->GetName();
- std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
+ std::string aNewName = GenerateGroupName( std::string(elemGroupName.in()) + "_double");
if ( !getEditor().GetLastCreatedElems().empty() && theElemGroupNeeded )
{
SMESH::long_array_var anIds = GetLastCreatedElems();
if ( ivol > 0 )
{
aNewVolumeGroup = myMesh_i->CreateGroup(SMESH::VOLUME,
- generateGroupName("affectedVolumes").c_str());
+ GenerateGroupName("affectedVolumes").c_str());
aNewVolumeGroup->Add(volumeIds);
aListOfGroups->length( nbGroups+1 );
aListOfGroups[ nbGroups++ ] = aNewVolumeGroup._retn();
if ( iface > 0 )
{
aNewFaceGroup = myMesh_i->CreateGroup(SMESH::FACE,
- generateGroupName("affectedFaces").c_str());
+ GenerateGroupName("affectedFaces").c_str());
aNewFaceGroup->Add(faceIds);
aListOfGroups->length( nbGroups+1 );
aListOfGroups[ nbGroups++ ] = aNewFaceGroup._retn();
if ( iedge > 0 )
{
aNewEdgeGroup = myMesh_i->CreateGroup(SMESH::EDGE,
- generateGroupName("affectedEdges").c_str());
+ GenerateGroupName("affectedEdges").c_str());
aNewEdgeGroup->Add(edgeIds);
aListOfGroups->length( nbGroups+1 );
aListOfGroups[ nbGroups++ ] = aNewEdgeGroup._retn();
segOut.myNode2[0] = meshDS->FindNode( segIn.node1ID2 );
segOut.myNode1[1] = meshDS->FindNode( segIn.node2ID1 );
segOut.myNode2[1] = meshDS->FindNode( segIn.node2ID2 );
+ segOut.myXYZ[0].SetCoord( segIn.xyz1.x,
+ segIn.xyz1.y,
+ segIn.xyz1.z);
+ segOut.myXYZ[1].SetCoord( segIn.xyz2.x,
+ segIn.xyz2.y,
+ segIn.xyz2.z);
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
static bool IsTemporaryIDSource( SMESH::SMESH_IDSource_ptr& idSource );
static CORBA::Long* GetTemporaryIDs( SMESH::SMESH_IDSource_ptr& idSource, int& nbIds );
+ /*!
+ * \brief Generates the unique group name
+ */
+ std::string GenerateGroupName(const std::string& thePrefix);
+
CORBA::Boolean RemoveElements(const SMESH::long_array & IDsOfElements)
throw (SALOME::SALOME_Exception);
CORBA::Boolean RemoveNodes (const SMESH::long_array & IDsOfNodes)
SMESH::ElementType type)
throw (SALOME::SALOME_Exception);
+ /*!
+ * Project a point to a mesh object.
+ * Return ID of an element of given type where the given point is projected
+ * and coordinates of the projection point.
+ * In the case if nothing found, return -1 and []
+ */
+ CORBA::Long ProjectPoint(CORBA::Double x,
+ CORBA::Double y,
+ CORBA::Double z,
+ SMESH::SMESH_IDSource_ptr meshObject,
+ SMESH::ElementType type,
+ SMESH::double_array_out projecton)
+ throw (SALOME::SALOME_Exception);
+
/*!
* Return point state in a closed 2D mesh in terms of TopAbs_State enumeration.
* TopAbs_UNKNOWN state means that either mesh is wrong or the analysis fails.
CORBA::Boolean IsCoherentOrientation2D()
throw (SALOME::SALOME_Exception);
+ /*!
+ * Return sharp edges of faces and non-manifold ones. Optionally adds existing edges.
+ */
+ SMESH::ListOfEdges* FindSharpEdges(CORBA::Double angle, CORBA::Boolean addExisting)
+ throw (SALOME::SALOME_Exception);
+
/*!
* Returns all or only closed FreeBorder's.
*/
void dumpGroupsList(SMESH::TPythonDump & theDumpPython,
const SMESH::ListOfGroups * theGroupList);
- std::string generateGroupName(const std::string& thePrefix);
-
void prepareIdSource(SMESH::SMESH_IDSource_ptr theObject);
using namespace std;
using SMESH::TPythonDump;
+using SMESH::TVar;
int SMESH_Mesh_i::_idGenerator = 0;
return aResGrp._retn();
}
+//================================================================================
+/*!
+ * \brief Distribute all faces of the mesh between groups using sharp edges and optionally
+ * existing 1D elements as group boundaries.
+ * \param [in] theSharpAngle - edge is considered sharp if an angle between normals of
+ * adjacent faces is more than \a sharpAngle in degrees.
+ * \param [in] theCreateEdges - to create 1D elements for detected sharp edges.
+ * \param [in] theUseExistingEdges - to use existing edges as group boundaries
+ * \return ListOfGroups - the created groups
+ */
+//================================================================================
+
+SMESH::ListOfGroups*
+SMESH_Mesh_i::FaceGroupsSeparatedByEdges( CORBA::Double theSharpAngle,
+ CORBA::Boolean theCreateEdges,
+ CORBA::Boolean theUseExistingEdges )
+ throw (SALOME::SALOME_Exception)
+{
+ if ( theSharpAngle < 0 || theSharpAngle > 180 )
+ THROW_SALOME_CORBA_EXCEPTION("Invalid sharp angle, it must be between 0 and 180 degrees",
+ SALOME::BAD_PARAM);
+
+ SMESH::ListOfGroups_var resultGroups = new SMESH::ListOfGroups;
+
+ TPythonDump pyDump;
+
+ SMESH_TRY;
+ if ( _preMeshInfo )
+ _preMeshInfo->FullLoadFromFile();
+
+ SMESHDS_Mesh* meshDS = _impl->GetMeshDS();
+
+ std::vector< SMESH_MeshAlgos::Edge > edges =
+ SMESH_MeshAlgos::FindSharpEdges( meshDS, theSharpAngle, theUseExistingEdges );
+
+ if ( theCreateEdges )
+ {
+ std::vector<const SMDS_MeshNode *> nodes(2);
+ for ( size_t i = 0; i < edges.size(); ++i )
+ {
+ nodes[0] = edges[i]._node1;
+ nodes[1] = edges[i]._node2;
+ if ( meshDS->FindElement( nodes, SMDSAbs_Edge ))
+ continue;
+ if ( edges[i]._medium )
+ meshDS->AddEdge( edges[i]._node1, edges[i]._node2, edges[i]._medium );
+ else
+ meshDS->AddEdge( edges[i]._node1, edges[i]._node2 );
+ }
+ }
+
+ std::vector< std::vector< const SMDS_MeshElement* > > faceGroups =
+ SMESH_MeshAlgos::SeparateFacesByEdges( meshDS, edges );
+
+ SMESH::SMESH_MeshEditor_var editor = GetMeshEditor(); // create _editor
+
+ resultGroups->length( faceGroups.size() );
+ for ( size_t iG = 0; iG < faceGroups.size(); ++iG )
+ {
+ SMESH::SMESH_Group_var group = CreateGroup( SMESH::FACE,
+ _editor->GenerateGroupName("Group").c_str());
+ resultGroups[iG] = SMESH::SMESH_Group::_duplicate( group );
+
+ SMESHDS_GroupBase* groupBaseDS =
+ SMESH::DownCast<SMESH_GroupBase_i*>( group )->GetGroupDS();
+ SMDS_MeshGroup& groupCore = static_cast< SMESHDS_Group* >( groupBaseDS )->SMDSGroup();
+
+ std::vector< const SMDS_MeshElement* >& faces = faceGroups[ iG ];
+ for ( size_t i = 0; i < faces.size(); ++i )
+ groupCore.Add( faces[i] );
+ }
+
+ pyDump << resultGroups << " = " << SMESH::SMESH_Mesh_var(_this())
+ << ".FaceGroupsSeparatedByEdges( "
+ << TVar( theSharpAngle ) << ", "
+ << theCreateEdges << ", "
+ << theUseExistingEdges << " )";
+
+ SMESH_CATCH( SMESH::throwCorbaException );
+ return resultGroups._retn();
+
+}
+
//================================================================================
/*!
* \brief Remember GEOM group data
CORBA::Boolean overwrite,
CORBA::Boolean autoDimension,
const GEOM::ListOfFields& fields,
- const char* geomAssocFields)
+ const char* geomAssocFields,
+ CORBA::Double ZTolerance)
throw (SALOME::SALOME_Exception)
{
MESSAGE("MED version: "<< version);
{
aMeshName = prepareMeshNameAndGroups(file, overwrite);
_impl->ExportMED( file, aMeshName.c_str(), auto_groups, version,
- 0, autoDimension, /*addODOnVertices=*/have0dField);
+ 0, autoDimension, /*addODOnVertices=*/have0dField,
+ ZTolerance);
meshDS = _impl->GetMeshDS();
}
else
SMESH_MeshPartDS* partDS = new SMESH_MeshPartDS( meshPart );
_impl->ExportMED( file, aMeshName.c_str(), auto_groups, version,
- partDS, autoDimension, /*addODOnVertices=*/have0dField);
+ partDS, autoDimension, /*addODOnVertices=*/have0dField, ZTolerance);
meshDS = tmpDSDeleter._obj = partDS;
}
<< overwrite << ", "
<< autoDimension << ", "
<< goList << ", '"
- << ( geomAssocFields ? geomAssocFields : "" ) << "'" << " )";
+ << ( geomAssocFields ? geomAssocFields : "" ) << "',"
+ << TVar( ZTolerance )
+ << " )";
SMESH_CATCH( SMESH::throwCorbaException );
}
CORBA::Boolean theUnderlyingOnly )
throw (SALOME::SALOME_Exception);
+ SMESH::ListOfGroups* FaceGroupsSeparatedByEdges( CORBA::Double theSharpAngle,
+ CORBA::Boolean theCreateEdges,
+ CORBA::Boolean theUseExistingEdges )
+ throw (SALOME::SALOME_Exception);
SMESH::SMESH_Group_ptr ConvertToStandalone( SMESH::SMESH_GroupBase_ptr theGroupOn )
throw (SALOME::SALOME_Exception);
CORBA::Boolean overwrite,
CORBA::Boolean autoDim,
const GEOM::ListOfFields& fields,
- const char* geomAssocFields) throw (SALOME::SALOME_Exception);
+ const char* geomAssocFields,
+ CORBA::Double ZTolerance) throw (SALOME::SALOME_Exception);
void ExportPartToDAT(SMESH::SMESH_IDSource_ptr meshPart,
const char* file) throw (SALOME::SALOME_Exception);
void ExportPartToUNV(SMESH::SMESH_IDSource_ptr meshPart,
aMeasurements.UnRegister()
return pointStruct.x, pointStruct.y, pointStruct.z
+ def GetAngle(self, p1, p2, p3 ):
+ """
+ Computes a radian measure of an angle defined by 3 points: <(p1,p2,p3)
+
+ Parameters:
+ p1,p2,p3: coordinates of 3 points defined by either SMESH.PointStruct
+ or list [x,y,z]
+
+ Returns:
+ Angle in radians
+ """
+ if isinstance( p1, list ): p1 = PointStruct(*p1)
+ if isinstance( p2, list ): p2 = PointStruct(*p2)
+ if isinstance( p3, list ): p3 = PointStruct(*p3)
+
+ aMeasurements = self.CreateMeasurements()
+ angle = aMeasurements.Angle(p1,p2,p3)
+ aMeasurements.UnRegister()
+
+ return angle
+
+
pass # end of class smeshBuilder
import omniORB
If *autoDimension* is *False*, the space dimension is always 3.
fields: list of GEOM fields defined on the shape to mesh.
geomAssocFields: each character of this string means a need to export a
- corresponding field; correspondence between fields and characters is following:
+ corresponding field; correspondence between fields and characters
+ is following:
- 'v' stands for "_vertices_" field;
- 'e' stands for "_edges_" field;
- 'f' stands for "_faces_" field;
- 's' stands for "_solids_" field.
+
+ zTolerance (float): tolerance in Z direction. If Z coordinate of a node is
+ close to zero within a given tolerance, the coordinate is set to zero.
+ If *ZTolerance* is negative (default), the node coordinates are kept as is.
"""
# process positional arguments
#args = [i for i in args if i not in [SMESH.MED_V2_1, SMESH.MED_V2_2]] # backward compatibility
autoDimension = args[5] if len(args) > 5 else True
fields = args[6] if len(args) > 6 else []
geomAssocFields = args[7] if len(args) > 7 else ''
+ z_tolerance = args[8] if len(args) > 8 else -1.
# process keywords arguments
auto_groups = kwargs.get("auto_groups", auto_groups)
minor = kwargs.get("minor", minor)
autoDimension = kwargs.get("autoDimension", autoDimension)
fields = kwargs.get("fields", fields)
geomAssocFields = kwargs.get("geomAssocFields", geomAssocFields)
+ z_tolerance = kwargs.get("zTolerance", z_tolerance)
+
# invoke engine's function
- if meshPart or fields or geomAssocFields:
+ if meshPart or fields or geomAssocFields or z_tolerance > 0:
unRegister = genObjUnRegister()
if isinstance( meshPart, list ):
meshPart = self.GetIDSource( meshPart, SMESH.ALL )
unRegister.set( meshPart )
+
+ z_tolerance,Parameters,hasVars = ParseParameters(z_tolerance)
+ self.mesh.SetParameters(Parameters)
+
self.mesh.ExportPartToMED( meshPart, fileName, auto_groups, minor, overwrite, autoDimension,
- fields, geomAssocFields)
+ fields, geomAssocFields, z_tolerance)
else:
self.mesh.ExportMED(fileName, auto_groups, minor, overwrite, autoDimension)
groups = [groups]
return self.mesh.CreateDimGroup(groups, elemType, name, nbCommonNodes, underlyingOnly)
+ def FaceGroupsSeparatedByEdges( self, sharpAngle, createEdges=False, useExistingEdges=False ):
+ """
+ Distribute all faces of the mesh among groups using sharp edges and optionally
+ existing 1D elements as group boundaries.
+
+ Parameters:
+ sharpAngle: edge is considered sharp if an angle between normals of
+ adjacent faces is more than \a sharpAngle in degrees.
+ createEdges (boolean): to create 1D elements for detected sharp edges.
+ useExistingEdges (boolean): to use existing edges as group boundaries
+ Returns:
+ ListOfGroups - the created :class:`groups <SMESH.SMESH_Group>`
+ """
+ sharpAngle,Parameters,hasVars = ParseParameters( sharpAngle )
+ self.mesh.SetParameters(Parameters)
+ return self.mesh.FaceGroupsSeparatedByEdges( sharpAngle, createEdges, useExistingEdges );
def ConvertToStandalone(self, group):
"""
else:
return self.editor.FindElementsByPoint(x, y, z, elementType)
+ def ProjectPoint(self, x,y,z, meshObject, elementType):
+ """
+ Project a point to a mesh object.
+ Return ID of an element of given type where the given point is projected
+ and coordinates of the projection point.
+ In the case if nothing found, return -1 and []
+ """
+ if ( isinstance( meshObject, Mesh )):
+ meshObject = meshObject.GetMesh()
+ return self.editor.ProjectPoint( x,y,z, meshObject, elementType )
+
def GetPointState(self, x, y, z):
"""
Return point state in a closed 2D mesh in terms of TopAbs_State enumeration:
return self.editor.IsCoherentOrientation2D()
+ def FindSharpEdges( self, angle, addExisting=False ):
+ """
+ Return sharp edges of faces and non-manifold ones.
+ Optionally add existing edges.
+
+ Parameters:
+ angle: angle (in degrees) between normals of adjacent faces to detect sharp edges
+ addExisting: to return existing edges (1D elements) as well
+
+ Returns:
+ list of FaceEdge structures
+ """
+ angle = ParseParameters( angle )[0]
+ return self.editor.FindSharpEdges( angle, addExisting )
+
def MeshToPassThroughAPoint(self, x, y, z):
"""
Find the node closest to a point and moves it to a point location
Parameters:
IDsOfElements: the faces to be splitted
- Diag13: is used to choose a diagonal for splitting.
+ Diag13 (boolean): is used to choose a diagonal for splitting.
Returns:
True in case of success, False otherwise.
Parameters:
theObject: the object from which the list of elements is taken,
this is :class:`mesh, sub-mesh, group or filter <SMESH.SMESH_IDSource>`
- Diag13: is used to choose a diagonal for splitting.
+ Diag13 (boolean): is used to choose a diagonal for splitting.
Returns:
True in case of success, False otherwise.
def MakePolyLine(self, segments, groupName='', isPreview=False ):
"""
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
+ the initial triangle mesh. Positions of new nodes are found by cutting the mesh by the
plane passing through pairs of points specified by each :class:`SMESH.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
The vector goes from the middle point to the projection point. In case of planar
mesh, the vector is normal to the mesh.
- *segments* [i].vector returns the used vector which goes from the middle point to its projection.
+ In preview mode, *segments* [i].vector returns the used vector which goes from the middle point to its projection.
- Parameters:
+ Parameters:
segments: list of :class:`SMESH.PolySegment` defining positions of cutting planes.
groupName: optional name of a group where created mesh segments will be added.
-
+
"""
editor = self.editor
if isPreview:
volume = self.FunctorValue(SMESH.FT_Volume3D, elemId)
return volume
+ def GetAngle(self, node1, node2, node3 ):
+ """
+ Computes a radian measure of an angle defined by 3 nodes: <(node1,node2,node3)
+
+ Parameters:
+ node1,node2,node3: IDs of the three nodes
+
+ Returns:
+ Angle in radians
+ """
+ return self.smeshpyD.GetAngle( self.GetNodeXYZ( node1 ),
+ self.GetNodeXYZ( node2 ),
+ self.GetNodeXYZ( node3 ))
+
def GetMaxElementLength(self, elemId):
"""
Get maximum element length.
if ( !myElemSearcher )
myElemSearcher = SMESH_MeshAlgos::GetElementSearcher( *meshDS );
- SMESH_ElementSearcher* searcher = const_cast<SMESH_ElementSearcher*>(myElemSearcher);
+ SMESH_ElementSearcher* searcher = const_cast<SMESH_ElementSearcher*>( myElemSearcher );
SMESHUtils::Deleter<SMESH_ElementSearcher>
volSearcher( SMESH_MeshAlgos::GetElementSearcher( *meshDS ));
vector< const SMDS_MeshElement* > suspectFaces, foundVolumes;
gp_Pnt PC;
gp_Vec VNorm;
const SMDS_MeshElement* volumes[2];
- int what = Preparation(face, PN, VN, FNodes, PC, VNorm, volumes);
+ int what = Preparation( face, PN, VN, FNodes, PC, VNorm, volumes );
if ( what == NOT_QUAD )
continue;
if ( volumes[0] && volumes[1] )
if ( toFindVolumes && 0 ) // non-conformal mesh is not suitable for any mesher so far
{
- // there are volumes in the mesh, in a non-conformal mesh an neighbor
+ // there are volumes in the mesh, in a non-conformal mesh a neighbor
// volume can be not found yet
for ( int isRev = 0; isRev < 2; ++isRev )
{
gp_Pnt intP;
for ( int isRev = 0; isRev < 2; ++isRev )
{
- if( !volumes[isRev] && HasIntersection(farPnt[isRev], PC, intP, aContour) )
+ if( !volumes[isRev] && HasIntersection( farPnt[isRev], PC, intP, aContour ))
{
double d = PC.Distance( intP );
if ( d < dist2int[isRev] )
myHelper = new SMESH_MesherHelper( aMesh );
myHelper->IsQuadraticSubMesh( aShape );
// to delete helper at exit from Compute()
- std::auto_ptr<SMESH_MesherHelper> helperDeleter( myHelper );
+ std::unique_ptr<SMESH_MesherHelper> helperDeleter( myHelper );
// get 2 shells
TopoDS_Solid solid = TopoDS::Solid( aShape );
#
import salome_pluginsmanager
import os
+from qtsalome import QIcon
try:
from spadderPlugin import runSpadderPlugin
try:
from meshcut_plugin import MeshCut
+ icon_file = os.path.join(os.getenv('SMESH_ROOT_DIR'),'share', 'salome', 'resources', 'smesh', 'mesh_plugins_meshcut.png')
salome_pluginsmanager.AddFunction('MeshCut',
'Cut a tetrahedron mesh by a plane',
- MeshCut)
+ MeshCut, icon=QIcon(icon_file))
except Exception as e:
salome_pluginsmanager.logger.info('ERROR: MeshCut plug-in is unavailable: {}'.format(e))