From: vsr Date: Fri, 10 Dec 2010 13:15:53 +0000 (+0000) Subject: Merge from PHASE_25_BR 09/12/2010 X-Git-Tag: RELIQUAT_5x_15112010 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=9150fb3db9f16daea68ed8b24447aaadc171b61e;p=modules%2Fsmesh.git Merge from PHASE_25_BR 09/12/2010 --- diff --git a/doc/salome/gui/SMESH/images/bare_border_faces_smpl.png b/doc/salome/gui/SMESH/images/bare_border_faces_smpl.png new file mode 100644 index 000000000..6b7ead85e Binary files /dev/null and b/doc/salome/gui/SMESH/images/bare_border_faces_smpl.png differ diff --git a/doc/salome/gui/SMESH/images/bare_border_volumes_smpl.png b/doc/salome/gui/SMESH/images/bare_border_volumes_smpl.png new file mode 100644 index 000000000..a1e799aa2 Binary files /dev/null and b/doc/salome/gui/SMESH/images/bare_border_volumes_smpl.png differ diff --git a/doc/salome/gui/SMESH/images/controls_popup.png b/doc/salome/gui/SMESH/images/controls_popup.png new file mode 100755 index 000000000..b0bd01fb9 Binary files /dev/null and b/doc/salome/gui/SMESH/images/controls_popup.png differ diff --git a/doc/salome/gui/SMESH/images/copy_mesh_dlg.png b/doc/salome/gui/SMESH/images/copy_mesh_dlg.png new file mode 100644 index 000000000..db9c929b5 Binary files /dev/null and b/doc/salome/gui/SMESH/images/copy_mesh_dlg.png differ diff --git a/doc/salome/gui/SMESH/images/copy_mesh_icon.png b/doc/salome/gui/SMESH/images/copy_mesh_icon.png new file mode 100644 index 000000000..263479f3b Binary files /dev/null and b/doc/salome/gui/SMESH/images/copy_mesh_icon.png differ diff --git a/doc/salome/gui/SMESH/images/over_constrained_faces.png b/doc/salome/gui/SMESH/images/over_constrained_faces.png new file mode 100644 index 000000000..9d584e8ac Binary files /dev/null and b/doc/salome/gui/SMESH/images/over_constrained_faces.png differ diff --git a/doc/salome/gui/SMESH/images/over_constrained_volumes.png b/doc/salome/gui/SMESH/images/over_constrained_volumes.png new file mode 100644 index 000000000..761144382 Binary files /dev/null and b/doc/salome/gui/SMESH/images/over_constrained_volumes.png differ diff --git a/doc/salome/gui/SMESH/images/scalar_bar_dlg.png b/doc/salome/gui/SMESH/images/scalar_bar_dlg.png new file mode 100755 index 000000000..59ca53065 Binary files /dev/null and b/doc/salome/gui/SMESH/images/scalar_bar_dlg.png differ diff --git a/doc/salome/gui/SMESH/input/about_meshes.doc b/doc/salome/gui/SMESH/input/about_meshes.doc index 8a81c7ea0..c79f26644 100644 --- a/doc/salome/gui/SMESH/input/about_meshes.doc +++ b/doc/salome/gui/SMESH/input/about_meshes.doc @@ -16,6 +16,9 @@ for example, a face. Several created meshes can be \subpage building_compounds_page "combined into mesh compounds". +The whole mesh or it's part can be \subpage copy_mesh_page "copied" +into another mesh. + All created meshes and submeshes can be \subpage editing_meshes_page "edited". Meshes can be also edited using the MESH functions destined for diff --git a/doc/salome/gui/SMESH/input/about_quality_controls.doc b/doc/salome/gui/SMESH/input/about_quality_controls.doc index 8f78c38c5..124867c9e 100644 --- a/doc/salome/gui/SMESH/input/about_quality_controls.doc +++ b/doc/salome/gui/SMESH/input/about_quality_controls.doc @@ -32,6 +32,8 @@ Edge quality controls: Face quality controls: +To manage the quality controls call pop-up in the VTK viewer and select "Controls" sub-menu +\image html controls_popup.png + + + + */ diff --git a/doc/salome/gui/SMESH/input/bare_border_face.doc b/doc/salome/gui/SMESH/input/bare_border_face.doc new file mode 100644 index 000000000..2115d3249 --- /dev/null +++ b/doc/salome/gui/SMESH/input/bare_border_face.doc @@ -0,0 +1,15 @@ +/*! + +\page bare_border_faces_page Bare border faces + +This mesh quality control highlights the faces having the border not +shared with other faces (free border) and missing an edge based on +nodes of the free border. The faces with bare border are shown with a +color different from the color of shared faces. + +\image html bare_border_faces_smpl.png + +\sa A sample TUI Script making a group of faces highlighted in the +picture is \ref tui_bare_border_faces "Bare border faces Control". + +*/ diff --git a/doc/salome/gui/SMESH/input/bare_border_volumes.doc b/doc/salome/gui/SMESH/input/bare_border_volumes.doc new file mode 100644 index 000000000..d0dd894ba --- /dev/null +++ b/doc/salome/gui/SMESH/input/bare_border_volumes.doc @@ -0,0 +1,15 @@ +/*! + +\page bare_border_volumes_page Bare border volumes + +This mesh quality control highlights the volumes having the border not +shared with other volumes (free border) and missing a face based on +nodes of the free border. The volumes with bare border are shown with a +color different from the color of shared volumes. + +\image html bare_border_volumes_smpl.png + +\sa A sample TUI Script making a group of volumes highlighted in the +picture is \ref tui_bare_border_volumes "Bare border volumes Control". + +*/ diff --git a/doc/salome/gui/SMESH/input/copy_mesh.doc b/doc/salome/gui/SMESH/input/copy_mesh.doc new file mode 100644 index 000000000..2c65ab8d0 --- /dev/null +++ b/doc/salome/gui/SMESH/input/copy_mesh.doc @@ -0,0 +1,56 @@ +/*! + +\page copy_mesh_page Copy Mesh + +\n A mesh can be created by copying a part of or the whole other mesh. + +To make a copy of a mesh: + +\par +From the \b Mesh menu select Copy Mesh or click "Copy Mesh" +button in the toolbar. + +\image html copy_mesh_icon.png +
"Copy Mesh" button
+ +\par +The following dialog box will appear: + +\image html copy_mesh_dlg.png + +\par +In the dialog: + + +See Also a sample +\ref tui_copy_mesh "TUI Example of mesh copying." +*/ diff --git a/doc/salome/gui/SMESH/input/over_constrained_faces.doc b/doc/salome/gui/SMESH/input/over_constrained_faces.doc new file mode 100644 index 000000000..26ad944f7 --- /dev/null +++ b/doc/salome/gui/SMESH/input/over_constrained_faces.doc @@ -0,0 +1,14 @@ +/*! + +\page over_constrained_faces_page Over-constrained faces + +\n This mesh quality control highlights faces sharing only one of its borders with other faces. + +\image html over_constrained_faces.png + +In this picture the over-constrained face is displayed in red. + +
See Also a sample TUI Script of a +\ref tui_over_constrained_faces "Over-constrained faces" filter. + +*/ diff --git a/doc/salome/gui/SMESH/input/over_constrained_volumes.doc b/doc/salome/gui/SMESH/input/over_constrained_volumes.doc new file mode 100644 index 000000000..1519e0ae6 --- /dev/null +++ b/doc/salome/gui/SMESH/input/over_constrained_volumes.doc @@ -0,0 +1,14 @@ +/*! + +\page over_constrained_volumes_page Over-constrained volumes + +\n This mesh quality control highlights volumes sharing only one of its borders with other volumes. + +\image html over_constrained_volumes.png + +In this picture the over-constrained volume is displayed in red. + +
See Also a sample TUI Script of a +\ref tui_over_constrained_volumes "Over-constrained volumes" filter. + +*/ \ No newline at end of file diff --git a/doc/salome/gui/SMESH/input/scalar_bar.doc b/doc/salome/gui/SMESH/input/scalar_bar.doc new file mode 100755 index 000000000..146a7fa78 --- /dev/null +++ b/doc/salome/gui/SMESH/input/scalar_bar.doc @@ -0,0 +1,40 @@ +/*! + +\page scalar_bar_dlg Scalar Bar properties + +In this dialog you can specify the properties of the scalar bar + +\image html scalar_bar_dlg.png + + + + +*/ diff --git a/doc/salome/gui/SMESH/input/selection_filter_library.doc b/doc/salome/gui/SMESH/input/selection_filter_library.doc index 1f612994f..9657f4c0d 100644 --- a/doc/salome/gui/SMESH/input/selection_filter_library.doc +++ b/doc/salome/gui/SMESH/input/selection_filter_library.doc @@ -144,7 +144,14 @@ Additional criteria to select mesh Faces are the following: one element of mesh only. See also a \ref free_edges_page "Free Edges quality control".
  • -Free faces selects 3D mesh elements wich belong to less than two volumes. +Free faces selects 2D mesh elements wich belong to less than two volumes. +
  • +Faces with bare border selects 2D mesh elements having a free border without an edge on it. +See also \ref bare_border_faces_page "Bare border faces quality control". +
  • +Over-constrained faces selects 2D mesh elements having only one border shared +with other 2D elements. +See also \ref over_constrained_faces_page "Over-constrained faces quality control".
  • Borders at Multi-Connections 2D selects cells consisting of edges belonging to several elements of mesh. The number of mesh elements should be more, less or equal @@ -187,6 +194,13 @@ diagonals with a value of length, which is more, less or equal
  • Bad oriented volume selects mesh volumes, which are incorrectly oriented from the point of view of MED convention. +
  • +Over-constrained volumes selects mesh volumes having only one border shared +with other volumes. +See also \ref over_constrained_volumes_page "Over-constrained volumes quality control". +
  • +Volumes with bare border selects 3D mesh elements having a free border without a face on it. +See also \ref bare_border_volumes_page "Bare border volumes quality control".
  • diff --git a/doc/salome/gui/SMESH/input/tui_creating_meshes.doc b/doc/salome/gui/SMESH/input/tui_creating_meshes.doc index 359ffd7d5..bad32ebf4 100644 --- a/doc/salome/gui/SMESH/input/tui_creating_meshes.doc +++ b/doc/salome/gui/SMESH/input/tui_creating_meshes.doc @@ -249,4 +249,48 @@ demonstrating the resulting mesh. \skipline import geompy \until #end +
    +\anchor tui_copy_mesh +

    Mesh Copying

    +\code +from smesh import * +SetCurrentStudy(salome.myStudy) + +# make geometry of a box +box = geompy.MakeBoxDXDYDZ(100,100,100) +face = geompy.SubShapeAllSorted(box, geompy.ShapeType["FACE"])[0] + +# generate 3D mesh +mesh = Mesh(box) +localAlgo = mesh.Triangle(face) +mesh.AutomaticHexahedralization() + +# objects to copy +fGroup = mesh.GroupOnGeom( face, "2D on face") +nGroup = mesh.GroupOnGeom( face, "nodes on face", NODE) +subMesh = localAlgo.GetSubMesh() + +# make a new mesh by copying different part of the mesh + +# 1. copy the whole mesh +newMesh = CopyMesh( mesh, "whole mesh copy") + +# 2. copy a group of 2D elements along with groups +newMesh = CopyMesh( fGroup, "face group copy with groups",toCopyGroups=True) + +# 3. copy a group of nodes with preseving their ids +newMesh = CopyMesh( nGroup, "node group copy", toKeepIDs=True) + +# 4. copy some faces +faceIds = fGroup.GetIDs()[-10:] +newMesh = CopyMesh( mesh.GetIDSource( faceIds, FACE ), "some faces copy") + +# 5. copy some nodes +nodeIds = nGroup.GetIDs()[-10:] +newMesh = CopyMesh( mesh.GetIDSource( nodeIds, NODE), "some nodes copy") + +# 6. copy a sub-mesh +newMesh = CopyMesh( subMesh, "submesh copy" ) +\endcode + */ diff --git a/doc/salome/gui/SMESH/input/tui_filters.doc b/doc/salome/gui/SMESH/input/tui_filters.doc index 6677b2ab5..aa3e1eb1c 100755 --- a/doc/salome/gui/SMESH/input/tui_filters.doc +++ b/doc/salome/gui/SMESH/input/tui_filters.doc @@ -90,7 +90,7 @@ Filter 2D mesh elements (faces) according to the minimum angle value: # create mesh from SMESH_mechanic import * # get faces with minimum angle > 75 -filter = smesh.GetFilter(smesh.FACE, smesh.FT_MinimumAngle, smesh.FT_MoreThan, 75) +filter = smesh.GetFilter(smesh.FACE, smesh.FT_MinimumAngle,">", 75) ids = mesh.GetIdsFromFilter(filter) print "Number of faces with minimum angle > 75:", len(ids) \endcode @@ -237,7 +237,7 @@ from SMESH_mechanic import * # add node mesh.AddNode(0,0,0) # get all free nodes -filter = smesh.GetFilter(smesh.EDGE, smesh.FT_FreeNodes) +filter = smesh.GetFilter(smesh.NODE, smesh.FT_FreeNodes) ids = mesh.GetIdsFromFilter(filter) print "Number of free nodes:", len(ids) \endcode @@ -255,13 +255,69 @@ Filter free faces: # create mesh from SMESH_mechanic import * # get all free faces -filter = smesh.GetFilter(smesh.EDGE, smesh.FT_FreeFaces) +filter = smesh.GetFilter(smesh.FACE, smesh.FT_FreeFaces) ids = mesh.GetIdsFromFilter(filter) print "Number of free faces:", len(ids) \endcode \sa \ref tui_free_faces +\section filter_bare_border_faces Bare border faces + +Filter faces with bare borders: +- element type is \a smesh.FACE +- functor type is \a smesh.FT_BareBorderFace +- threshold value is not required + +\code +# create mesh +from SMESH_mechanic import * +# remove some faces to have faces with bare borders +mesh.RemoveElements( mesh.GetElementsByType(FACE)[0:5] ) +# get all faces bare borders +filter = smesh.GetFilter(smesh.FACE, smesh.FT_BareBorderFace) +ids = mesh.GetIdsFromFilter(filter) +print "Faces with bare borders:", ids +\endcode + +\sa \ref tui_bare_border_faces + +\section filter_coplanar_faces Coplanar faces + +Filter faces with bare borders: +- element type is \a smesh.FACE +- functor type is \a smesh.FT_CoplanarFaces +- threshold value is the face ID +- tolerance is in degrees + +\code +# create mesh +from SMESH_mechanic import * +faceID = mesh.GetElementsByType(FACE)[0] +# get all faces co-planar to the first face with tolerance 5 degrees +filter = smesh.GetFilter(smesh.FACE, smesh.FT_CoplanarFaces,faceID,Tolerance=5.0) +ids = mesh.GetIdsFromFilter(filter) +print "Number of faces coplanar with the first one:", len(ids) +\endcode + +\section filter_over_constrained_faces Over-constrained faces + +Filter over-constrained faces: +- element type is \a smesh.FACE +- functor type is \a smesh.FT_OverConstrainedFace +- threshold value is not required + +\code +# create mesh +from SMESH_mechanic import * +# get all over-constrained faces +filter = smesh.GetFilter(smesh.FACE, smesh.FT_OverConstrainedFace) +ids = mesh.GetIdsFromFilter(filter) +print "Over-constrained faces:", ids +\endcode + +\sa \ref tui_over_constrained_faces + \section filter_borders_multiconnection Borders at multi-connection Filter border 1D mesh elements (edges) according to the specified number of @@ -377,6 +433,48 @@ print "Number of volumes with maximum element length > 10:", len(ids) \sa \ref tui_max_element_length_3d +\section filter_bare_border_volumes Bare border volumes + +Filter 3D mesh elements with bare borders: +- element type is \a smesh.VOLUME +- functor type is \a smesh.FT_BareBorderVolume +- threshold value is not required + +\code +# create mesh +from SMESH_mechanic import * +mesh.Tetrahedron() +mesh.Compute() +# remove some volumes to have volumes with bare borders +mesh.RemoveElements( mesh.GetElementsByType(VOLUME)[0:5] ) +# get all volumes with bare borders +filter = smesh.GetFilter(smesh.VOLUME, smesh.FT_BareBorderVolume) +ids = mesh.GetIdsFromFilter(filter) +print "Volumes with bare borders:", ids +\endcode + +\sa \ref tui_bare_border_volumes + +\section filter_over_constrained_volumes Over-constrained volumes + +Filter over-constrained volumes: +- element type is \a smesh.VOLUME +- functor type is \a smesh.FT_OverConstrainedVolume +- threshold value is not required + +\code +# create mesh +from SMESH_mechanic import * +mesh.Tetrahedron() +mesh.Compute() +# get all over-constrained volumes +filter = smesh.GetFilter(smesh.VOLUME, smesh.FT_OverConstrainedVolume) +ids = mesh.GetIdsFromFilter(filter) +print "Over-constrained volumes:", ids +\endcode + +\sa \ref tui_over_constrained_faces + \section filter_belong_to_geom Belong to Geom Filter mesh entities (nodes or elements) which all nodes lie on the diff --git a/doc/salome/gui/SMESH/input/tui_quality_controls.doc b/doc/salome/gui/SMESH/input/tui_quality_controls.doc index fc496dcde..420e507e1 100644 --- a/doc/salome/gui/SMESH/input/tui_quality_controls.doc +++ b/doc/salome/gui/SMESH/input/tui_quality_controls.doc @@ -309,6 +309,90 @@ aGroup.Add(aFaceIds) salome.sg.updateObjBrowser(1) \endcode +\section tui_bare_border_faces Bare border faces + +\code +from smesh import * +SetCurrentStudy(salome.myStudy) + +box = geompy.MakeBoxDXDYDZ(100, 100, 100) +geompy.addToStudy( box, "box" ) + +mesh = smesh.Mesh(box) +mesh.Segment().NumberOfSegments(3) +mesh.Quadrangle() +mesh.Compute() + +# remove 2 faces +allFaces = mesh.GetElementsByType(FACE) +mesh.RemoveElements( allFaces[0:2]) + +bareGroup = mesh.MakeGroup("bare faces", FACE, FT_BareBorderFace) +assert(bareGroup.Size() == 3) +\endcode + +\section tui_bare_border_volumes Bare border volumes + +\code +from smesh import * +SetCurrentStudy(salome.myStudy) + +box = geompy.MakeBoxDXDYDZ(100, 30, 10) +# the smallest face of the box +face = geompy.SubShapeAllSorted( box, geompy.ShapeType["FACE"])[0] + +geompy.addToStudy( box, "box" ) +geompy.addToStudyInFather( box, face, "face" ) + +mesh = Mesh(box) +mesh.AutomaticHexahedralization(); + +# remove half of mesh faces from the smallest face +faceFaces = mesh.GetSubMeshElementsId(face) +faceToRemove = faceFaces[: len(faceFaces)/2] +mesh.RemoveElements( faceToRemove ) + +# make a group of volumes missing the removed faces +bareGroup = mesh.MakeGroup("bare volumes", VOLUME, FT_BareBorderVolume) +assert(bareGroup.Size() == len( faceToRemove)) +\endcode + +\section tui_over_constrained_faces Over-constrained faces +\code +from smesh import * +SetCurrentStudy(salome.myStudy) + +mesh = Mesh() +faceFilter = GetFilter(FACE,FT_OverConstrainedFace) + +#make an edge +n1 = mesh.AddNode(0,0,0) +n2 = mesh.AddNode(10,0,0) +edge = mesh.AddEdge([n1,n2]) +assert( not mesh.GetIdsFromFilter( faceFilter )) + +# make faces +mesh.ExtrusionSweep([edge], MakeDirStruct(0,7,0), 5) +assert( 2 == len( mesh.GetIdsFromFilter( faceFilter ))) +\endcode + +\section tui_over_constrained_volumes Over-constrained volumes +\code +from smesh import * +SetCurrentStudy(salome.myStudy) + +mesh = Mesh() +volumeFilter = GetFilter(VOLUME,FT_OverConstrainedVolume) + +# make volumes by extrusion of one face +n1 = mesh.AddNode(0,0,0) +n2 = mesh.AddNode(10,0,0) +edge = mesh.AddEdge([n1,n2]) +mesh.ExtrusionSweep([edge], MakeDirStruct(0,7,0), 1) +mesh.ExtrusionSweep( mesh.GetElementsByType(FACE), MakeDirStruct(0,0,5), 7) +assert( 2 == len( mesh.GetIdsFromFilter( volumeFilter ))) +\endcode + \section tui_length_2d Length 2D \code diff --git a/idl/SMESH_Filter.idl b/idl/SMESH_Filter.idl index e12607bcd..087a0b48b 100644 --- a/idl/SMESH_Filter.idl +++ b/idl/SMESH_Filter.idl @@ -64,6 +64,10 @@ module SMESH FT_LyingOnGeom, FT_RangeOfIds, FT_BadOrientedVolume, + FT_BareBorderVolume, + FT_BareBorderFace, + FT_OverConstrainedVolume, + FT_OverConstrainedFace, FT_LinearOrQuadratic, FT_GroupColor, FT_ElemGeomType, @@ -88,6 +92,7 @@ module SMESH }; typedef sequence Histogram; + /*! * Base interface for all functors ( i.e. numerical functors and predicates ) */ @@ -98,8 +103,6 @@ module SMESH ElementType GetElementType(); }; - - /*! * Numerical functors are intended for calculating value by Id of mesh entity */ @@ -150,6 +153,7 @@ module SMESH Values GetValues(); }; + /*! * Predicates are intended for verification of criteria, * must return bool value by mesh id @@ -166,6 +170,29 @@ module SMESH */ interface BadOrientedVolume: Predicate {}; + /*! + * Logical functor (predicate) "Volumes with bare border". + * Verify whether a mesh volume has a free facet without a mesh face on it + */ + interface BareBorderVolume: Predicate {}; + /*! + * Logical functor (predicate) "Faces with bare border". + * Verify whether a mesh face has a side not shared with another face + * and without a mesh edge on it + */ + interface BareBorderFace: Predicate {}; + + /*! + * Logical functor (predicate) "Over-constrained Volume" + * Verify whether a mesh volume has only one facet shared with other volumes + */ + interface OverConstrainedVolume: Predicate {}; + /*! + * Logical functor (predicate) "Over-constrained Face". + * Verify whether a mesh face has only one border shared with other faces + */ + interface OverConstrainedFace: Predicate {}; + /*! * Logical functor (predicate) "Belong To Geometry". * Verify whether mesh element or node belong to pointed Geom Object @@ -503,6 +530,10 @@ module SMESH RangeOfIds CreateRangeOfIds(); BadOrientedVolume CreateBadOrientedVolume(); + BareBorderVolume CreateBareBorderVolume(); + BareBorderFace CreateBareBorderFace(); + OverConstrainedVolume CreateOverConstrainedVolume(); + OverConstrainedFace CreateOverConstrainedFace(); LinearOrQuadratic CreateLinearOrQuadratic(); GroupColor CreateGroupColor(); diff --git a/idl/SMESH_Gen.idl b/idl/SMESH_Gen.idl index 3c375e625..d958719e3 100644 --- a/idl/SMESH_Gen.idl +++ b/idl/SMESH_Gen.idl @@ -221,10 +221,45 @@ module SMESH raises ( SALOME::SALOME_Exception ); /*! - * Create a Mesh object, without a geometry shape reference + * Create a mesh by copying a part of another mesh + * \param meshPart - a part of mesh to copy + * \param meshName - a name of the new mesh + * \param toCopyGroups - to create in the new mesh groups + * the copied elements belongs to + * \param toKeepIDs - to preserve IDs of the copied elements or not */ -// SMESH_Mesh NewEmpty() -// raises ( SALOME::SALOME_Exception ); + SMESH_Mesh CopyMesh(in SMESH_IDSource meshPart, + in string meshName, + in boolean toCopyGroups, + in boolean toKeepIDs) + raises ( SALOME::SALOME_Exception ); + + /*! + * Concatenate the given meshes into one mesh. + * Union groups with the same name and type if + * theUniteIdenticalGroups flag is true. + * Merge coincident nodes and elements if + * theMergeNodesAndElements flag is true. + */ + SMESH_Mesh Concatenate(in mesh_array theMeshesArray, + in boolean theUniteIdenticalGroups, + in boolean theMergeNodesAndElements, + in double theMergeTolerance) + raises ( SALOME::SALOME_Exception ); + + /*! + * Concatenate the given meshes into one mesh. + * Union groups with the same name and type if + * theUniteIdenticalGroups flag is true. + * Merge coincident nodes and elements if + * theMergeNodesAndElements flag is true. + * Create the groups of all elements from initial meshes. + */ + SMESH_Mesh ConcatenateWithGroups(in mesh_array theMeshesArray, + in boolean theUniteIdenticalGroups, + in boolean theMergeNodesAndElements, + in double theMergeTolerance) + raises ( SALOME::SALOME_Exception ); /*! * Mesh a subShape. @@ -309,33 +344,6 @@ module SMESH in long theElementID) raises ( SALOME::SALOME_Exception ); - /*! - * Concatenate the given meshes into one mesh. - * Union groups with the same name and type if - * theUniteIdenticalGroups flag is true. - * Merge coincident nodes and elements if - * theMergeNodesAndElements flag is true. - */ - SMESH_Mesh Concatenate(in mesh_array theMeshesArray, - in boolean theUniteIdenticalGroups, - in boolean theMergeNodesAndElements, - in double theMergeTolerance) - raises ( SALOME::SALOME_Exception ); - - /*! - * Concatenate the given meshes into one mesh. - * Union groups with the same name and type if - * theUniteIdenticalGroups flag is true. - * Merge coincident nodes and elements if - * theMergeNodesAndElements flag is true. - * Create the groups of all elements from initial meshes. - */ - SMESH_Mesh ConcatenateWithGroups(in mesh_array theMeshesArray, - in boolean theUniteIdenticalGroups, - in boolean theMergeNodesAndElements, - in double theMergeTolerance) - raises ( SALOME::SALOME_Exception ); - /*! * \brief Return id of object, registered in current study context * diff --git a/resources/Makefile.am b/resources/Makefile.am index cc7d5a885..623d04ff1 100644 --- a/resources/Makefile.am +++ b/resources/Makefile.am @@ -107,6 +107,10 @@ dist_salomeres_DATA = \ mesh_vertex_n.png \ mesh_vertex.png \ mesh_volume_3d.png \ + bare_border_volume.png \ + bare_border_face.png \ + over_constrained_volume.png \ + over_constrained_face.png \ mesh_wireframe.png \ mesh_points.png \ mesh_wrap.png \ @@ -173,6 +177,7 @@ dist_salomeres_DATA = \ mesh_tree_hypo_projection_3d.png \ mesh_tree_hypo_projection_2d.png \ mesh_build_compound.png \ + copy_mesh.png \ mesh_node_to_point.png \ mesh_tree_mesh_partial.png \ mesh_extractGroup.png \ diff --git a/resources/bare_border_face.png b/resources/bare_border_face.png new file mode 100644 index 000000000..1993f2087 Binary files /dev/null and b/resources/bare_border_face.png differ diff --git a/resources/bare_border_volume.png b/resources/bare_border_volume.png new file mode 100644 index 000000000..3ef6e6a46 Binary files /dev/null and b/resources/bare_border_volume.png differ diff --git a/resources/copy_mesh.png b/resources/copy_mesh.png new file mode 100644 index 000000000..263479f3b Binary files /dev/null and b/resources/copy_mesh.png differ diff --git a/resources/over_constrained_face.png b/resources/over_constrained_face.png new file mode 100644 index 000000000..22b61bbed Binary files /dev/null and b/resources/over_constrained_face.png differ diff --git a/resources/over_constrained_volume.png b/resources/over_constrained_volume.png new file mode 100644 index 000000000..0e2da263f Binary files /dev/null and b/resources/over_constrained_volume.png differ diff --git a/src/Controls/SMESH_Controls.cxx b/src/Controls/SMESH_Controls.cxx index 5238b982f..cac5d5180 100644 --- a/src/Controls/SMESH_Controls.cxx +++ b/src/Controls/SMESH_Controls.cxx @@ -310,12 +310,16 @@ double NumericalFunctor::GetValue( long theId ) * \param nbIntervals - number of intervals * \param nbEvents - number of mesh elements having values within i-th interval * \param funValues - boundaries of intervals + * \param elements - elements to check vulue of; empty list means "of all" + * \param minmax - boundaries of diapason of values to divide into intervals */ //================================================================================ void NumericalFunctor::GetHistogram(int nbIntervals, std::vector& nbEvents, - std::vector& funValues) + std::vector& funValues, + const vector& elements, + const double* minmax) { if ( nbIntervals < 1 || !myMesh || @@ -326,13 +330,30 @@ void NumericalFunctor::GetHistogram(int nbIntervals, // get all values sorted std::multiset< double > values; - SMDS_ElemIteratorPtr elemIt = myMesh->elementsIterator(GetType()); - while ( elemIt->more() ) - values.insert( GetValue( elemIt->next()->GetID() )); + if ( elements.empty() ) + { + SMDS_ElemIteratorPtr elemIt = myMesh->elementsIterator(GetType()); + while ( elemIt->more() ) + values.insert( GetValue( elemIt->next()->GetID() )); + } + else + { + vector::const_iterator id = elements.begin(); + for ( ; id != elements.end(); ++id ) + values.insert( GetValue( *id )); + } + if ( minmax ) + { + funValues[0] = minmax[0]; + funValues[nbIntervals] = minmax[1]; + } + else + { + funValues[0] = *values.begin(); + funValues[nbIntervals] = *values.rbegin(); + } // case nbIntervals == 1 - funValues[0] = *values.begin(); - funValues[nbIntervals] = *values.rbegin(); if ( nbIntervals == 1 ) { nbEvents[0] = values.size(); @@ -350,15 +371,21 @@ void NumericalFunctor::GetHistogram(int nbIntervals, std::multiset< double >::iterator min = values.begin(), max; for ( int i = 0; i < nbIntervals; ++i ) { + // find end value of i-th interval double r = (i+1) / double( nbIntervals ); funValues[i+1] = funValues.front() * (1-r) + funValues.back() * r; + + // count values in the i-th interval if there are any if ( min != values.end() && *min <= funValues[i+1] ) { - max = values.upper_bound( funValues[i+1] ); // greater than funValues[i+1], or end() + // find the first value out of the interval + max = values.upper_bound( funValues[i+1] ); // max is greater than funValues[i+1], or end() nbEvents[i] = std::distance( min, max ); min = max; } } + // add values larger than minmax[1] + nbEvents.back() += std::distance( min, values.end() ); } //======================================================================= @@ -1902,7 +1929,115 @@ SMDSAbs_ElementType BadOrientedVolume::GetType() const return SMDSAbs_Volume; } +/* + Class : BareBorderVolume +*/ + +bool BareBorderVolume::IsSatisfy(long theElementId ) +{ + SMDS_VolumeTool myTool; + if ( myTool.Set( myMesh->FindElement(theElementId))) + { + for ( int iF = 0; iF < myTool.NbFaces(); ++iF ) + if ( myTool.IsFreeFace( iF )) + { + const SMDS_MeshNode** n = myTool.GetFaceNodes(iF); + vector< const SMDS_MeshNode*> nodes( n, n+myTool.NbFaceNodes(iF)); + if ( !myMesh->FindElement( nodes, SMDSAbs_Face, /*Nomedium=*/false)) + return true; + } + } + return false; +} + +/* + Class : BareBorderFace +*/ + +bool BareBorderFace::IsSatisfy(long theElementId ) +{ + if ( const SMDS_MeshElement* face = myMesh->FindElement(theElementId)) + if ( face->GetType() == SMDSAbs_Face ) + { + int nbN = face->NbCornerNodes(); + for ( int i = 0; i < nbN; ++i ) + { + // check if a link is shared by another face + const SMDS_MeshNode* n1 = face->GetNode( i ); + const SMDS_MeshNode* n2 = face->GetNode( (i+1)%nbN ); + SMDS_ElemIteratorPtr fIt = n1->GetInverseElementIterator( SMDSAbs_Face ); + bool isShared = false; + while ( !isShared && fIt->more() ) + { + const SMDS_MeshElement* f = fIt->next(); + isShared = ( f != face && f->GetNodeIndex(n2) != -1 ); + } + if ( !isShared ) + { + myLinkNodes.resize( 2 + face->IsQuadratic()); + myLinkNodes[0] = n1; + myLinkNodes[1] = n2; + if ( face->IsQuadratic() ) + myLinkNodes[2] = face->GetNode( i+nbN ); + return !myMesh->FindElement( myLinkNodes, SMDSAbs_Edge, /*noMedium=*/false); + } + } + } + return false; +} + +/* + Class : OverConstrainedVolume +*/ +bool OverConstrainedVolume::IsSatisfy(long theElementId ) +{ + // An element is over-constrained if it has N-1 free borders where + // N is the number of edges/faces for a 2D/3D element. + SMDS_VolumeTool myTool; + if ( myTool.Set( myMesh->FindElement(theElementId))) + { + int nbSharedFaces = 0; + for ( int iF = 0; iF < myTool.NbFaces(); ++iF ) + if ( !myTool.IsFreeFace( iF ) && ++nbSharedFaces > 1 ) + break; + return ( nbSharedFaces == 1 ); + } + return false; +} + +/* + Class : OverConstrainedFace +*/ + +bool OverConstrainedFace::IsSatisfy(long theElementId ) +{ + // An element is over-constrained if it has N-1 free borders where + // N is the number of edges/faces for a 2D/3D element. + if ( const SMDS_MeshElement* face = myMesh->FindElement(theElementId)) + if ( face->GetType() == SMDSAbs_Face ) + { + int nbSharedBorders = 0; + int nbN = face->NbCornerNodes(); + for ( int i = 0; i < nbN; ++i ) + { + // check if a link is shared by another face + const SMDS_MeshNode* n1 = face->GetNode( i ); + const SMDS_MeshNode* n2 = face->GetNode( (i+1)%nbN ); + SMDS_ElemIteratorPtr fIt = n1->GetInverseElementIterator( SMDSAbs_Face ); + bool isShared = false; + while ( !isShared && fIt->more() ) + { + const SMDS_MeshElement* f = fIt->next(); + isShared = ( f != face && f->GetNodeIndex(n2) != -1 ); + } + if ( isShared && ++nbSharedBorders > 1 ) + break; + } + return ( nbSharedBorders == 1 ); + } + return false; +} /* Class : FreeBorders diff --git a/src/Controls/SMESH_ControlsDef.hxx b/src/Controls/SMESH_ControlsDef.hxx index 915bd9f4b..0a71438d7 100644 --- a/src/Controls/SMESH_ControlsDef.hxx +++ b/src/Controls/SMESH_ControlsDef.hxx @@ -127,9 +127,11 @@ namespace SMESH{ virtual void SetMesh( const SMDS_Mesh* theMesh ); virtual double GetValue( long theElementId ); virtual double GetValue(const TSequenceOfXYZ& thePoints) { return -1.0;}; - void GetHistogram(int nbIntervals, - std::vector& nbEvents, - std::vector& funValues); + void GetHistogram(int nbIntervals, + std::vector& nbEvents, + std::vector& funValues, + const std::vector& elements, + const double* minmax=0); virtual SMDSAbs_ElementType GetType() const = 0; virtual double GetBadRate( double Value, int nbNodes ) const = 0; long GetPrecision() const; @@ -373,11 +375,72 @@ namespace SMESH{ virtual void SetMesh( const SMDS_Mesh* theMesh ); virtual bool IsSatisfy( long theElementId ); virtual SMDSAbs_ElementType GetType() const; - + protected: const SMDS_Mesh* myMesh; }; - + + /* + BareBorderVolume + */ + class SMESHCONTROLS_EXPORT BareBorderVolume: public Predicate + { + public: + BareBorderVolume():myMesh(0) {} + virtual void SetMesh( const SMDS_Mesh* theMesh ) { myMesh = theMesh; } + virtual SMDSAbs_ElementType GetType() const { return SMDSAbs_Volume; } + virtual bool IsSatisfy( long theElementId ); + protected: + const SMDS_Mesh* myMesh; + }; + typedef boost::shared_ptr BareBorderVolumePtr; + + /* + BareBorderFace + */ + class SMESHCONTROLS_EXPORT BareBorderFace: public Predicate + { + public: + BareBorderFace():myMesh(0) {} + virtual void SetMesh( const SMDS_Mesh* theMesh ) { myMesh = theMesh; } + virtual SMDSAbs_ElementType GetType() const { return SMDSAbs_Face; } + virtual bool IsSatisfy( long theElementId ); + protected: + const SMDS_Mesh* myMesh; + std::vector< const SMDS_MeshNode* > myLinkNodes; + }; + typedef boost::shared_ptr BareBorderFacePtr; + + /* + OverConstrainedVolume + */ + class SMESHCONTROLS_EXPORT OverConstrainedVolume: public Predicate + { + public: + OverConstrainedVolume():myMesh(0) {} + virtual void SetMesh( const SMDS_Mesh* theMesh ) { myMesh = theMesh; } + virtual SMDSAbs_ElementType GetType() const { return SMDSAbs_Volume; } + virtual bool IsSatisfy( long theElementId ); + protected: + const SMDS_Mesh* myMesh; + }; + typedef boost::shared_ptr OverConstrainedVolumePtr; + + /* + OverConstrainedFace + */ + class SMESHCONTROLS_EXPORT OverConstrainedFace: public Predicate + { + public: + OverConstrainedFace():myMesh(0) {} + virtual void SetMesh( const SMDS_Mesh* theMesh ) { myMesh = theMesh; } + virtual SMDSAbs_ElementType GetType() const { return SMDSAbs_Face; } + virtual bool IsSatisfy( long theElementId ); + protected: + const SMDS_Mesh* myMesh; + std::vector< const SMDS_MeshNode* > myLinkNodes; + }; + typedef boost::shared_ptr OverConstrainedFacePtr; /* Class : FreeEdges @@ -399,7 +462,7 @@ namespace SMESH{ }; typedef std::set TBorders; void GetBoreders(TBorders& theBorders); - + protected: const SMDS_Mesh* myMesh; }; diff --git a/src/OBJECT/SMESH_Actor.cxx b/src/OBJECT/SMESH_Actor.cxx index 4afc7f4ca..bba1f3b32 100644 --- a/src/OBJECT/SMESH_Actor.cxx +++ b/src/OBJECT/SMESH_Actor.cxx @@ -199,6 +199,25 @@ SMESH_ActorDef::SMESH_ActorDef() aFilter->RegisterCellsWithType(VTK_QUADRATIC_PYRAMID); aFilter->RegisterCellsWithType(VTK_CONVEX_POINT_SET); + my3DExtActor = SMESH_DeviceActor::New(); + my3DExtActor->SetUserMatrix(aMatrix); + my3DExtActor->PickableOff(); + my3DExtActor->SetProperty(my2DExtProp); + my3DExtActor->SetBackfaceProperty(my2DExtProp); + my3DExtActor->SetRepresentation(SMESH_DeviceActor::eSurface); + aFilter = my3DExtActor->GetExtractUnstructuredGrid(); + aFilter->SetModeOfChanging(VTKViewer_ExtractUnstructuredGrid::eAdding); + aFilter->RegisterCellsWithType(VTK_TETRA); + aFilter->RegisterCellsWithType(VTK_VOXEL); + aFilter->RegisterCellsWithType(VTK_HEXAHEDRON); + aFilter->RegisterCellsWithType(VTK_WEDGE); + aFilter->RegisterCellsWithType(VTK_PYRAMID); + aFilter->RegisterCellsWithType(VTK_QUADRATIC_TETRA); + aFilter->RegisterCellsWithType(VTK_QUADRATIC_HEXAHEDRON); + aFilter->RegisterCellsWithType(VTK_QUADRATIC_WEDGE); + aFilter->RegisterCellsWithType(VTK_QUADRATIC_PYRAMID); + aFilter->RegisterCellsWithType(VTK_CONVEX_POINT_SET); + //Definition 1D device of the actor //--------------------------------- myEdgeProp = vtkProperty::New(); @@ -532,6 +551,7 @@ SMESH_ActorDef::~SMESH_ActorDef() my2DExtProp->Delete(); my2DExtActor->Delete(); my3DActor->Delete(); + my3DExtActor->Delete(); myNodeActor->Delete(); myBaseActor->Delete(); @@ -723,8 +743,8 @@ SetControlMode(eControl theMode, bool anIsScalarVisible = theMode > eNone; - if(anIsScalarVisible){ - switch(theMode){ + if(anIsScalarVisible) { + switch(theMode) { case eLength: { SMESH::Controls::Length* aControl = new SMESH::Controls::Length(); @@ -755,6 +775,14 @@ SetControlMode(eControl theMode, myFunctor.reset(new SMESH::Controls::FreeFaces()); myControlActor = my2DActor; break; + case eBareBorderFace: + myFunctor.reset(new SMESH::Controls::BareBorderFace()); + myControlActor = my2DActor; + break; + case eOverConstrainedFace: + myFunctor.reset(new SMESH::Controls::OverConstrainedFace()); + myControlActor = my2DActor; + break; case eMultiConnection: myFunctor.reset(new SMESH::Controls::MultiConnection()); myControlActor = my1DActor; @@ -819,6 +847,18 @@ SetControlMode(eControl theMode, myControlActor = my3DActor; break; } + case eBareBorderVolume: + { + myFunctor.reset(new SMESH::Controls::BareBorderVolume()); + myControlActor = my3DActor; + break; + } + case eOverConstrainedVolume: + { + myFunctor.reset(new SMESH::Controls::OverConstrainedVolume()); + myControlActor = my3DActor; + break; + } case eMinimumAngle: { SMESH::Controls::MinimumAngle* aControl = new SMESH::Controls::MinimumAngle(); @@ -860,14 +900,22 @@ SetControlMode(eControl theMode, my1DExtActor->SetExtControlMode(myFunctor); break; case eFreeFaces: + case eBareBorderFace: + case eOverConstrainedFace: my2DExtActor->SetExtControlMode(myFunctor); break; + case eBareBorderVolume: + case eOverConstrainedVolume: + my3DExtActor->SetExtControlMode(myFunctor); + break; case eLength2D: case eMultiConnection2D: my1DExtActor->SetExtControlMode(myFunctor,myScalarBarActor,myLookupTable); + UpdateDistribution(); break; default: myControlActor->SetControlMode(myFunctor,myScalarBarActor,myLookupTable); + UpdateDistribution(); } } @@ -911,6 +959,7 @@ void SMESH_ActorDef::AddToRender(vtkRenderer* theRenderer){ theRenderer->AddActor(myNodeExtActor); my3DActor->AddToRender(theRenderer); + my3DExtActor->AddToRender(theRenderer); my2DActor->AddToRender(theRenderer); my2DExtActor->AddToRender(theRenderer); @@ -954,6 +1003,7 @@ void SMESH_ActorDef::RemoveFromRender(vtkRenderer* theRenderer){ my2DActor->RemoveFromRender(theRenderer); my2DExtActor->RemoveFromRender(theRenderer); my3DActor->RemoveFromRender(theRenderer); + my3DExtActor->RemoveFromRender(theRenderer); theRenderer->RemoveActor(myScalarBarActor); theRenderer->RemoveActor(myPointLabels); @@ -989,6 +1039,7 @@ bool SMESH_ActorDef::Init(TVisualObjPtr theVisualObj, my2DActor->Init(myVisualObj,myImplicitBoolean); my2DExtActor->Init(myVisualObj,myImplicitBoolean); my3DActor->Init(myVisualObj,myImplicitBoolean); + my3DExtActor->Init(myVisualObj,myImplicitBoolean); my0DActor->GetMapper()->SetLookupTable(myLookupTable); //my0DExtActor->GetMapper()->SetLookupTable(myLookupTable); @@ -999,6 +1050,7 @@ bool SMESH_ActorDef::Init(TVisualObjPtr theVisualObj, my2DActor->GetMapper()->SetLookupTable(myLookupTable); my2DExtActor->GetMapper()->SetLookupTable(myLookupTable); my3DActor->GetMapper()->SetLookupTable(myLookupTable); + my3DExtActor->GetMapper()->SetLookupTable(myLookupTable); vtkFloatingPointType aFactor, aUnits; my2DActor->GetPolygonOffsetParameters(aFactor,aUnits); @@ -1071,6 +1123,7 @@ void SMESH_ActorDef::SetTransform(VTKViewer_Transform* theTransform){ my2DActor->SetTransform(theTransform); my2DExtActor->SetTransform(theTransform); my3DActor->SetTransform(theTransform); + my3DExtActor->SetTransform(theTransform); Modified(); } @@ -1126,6 +1179,7 @@ void SMESH_ActorDef::SetShrinkFactor(vtkFloatingPointType theValue){ my2DActor->SetShrinkFactor(theValue); my2DExtActor->SetShrinkFactor(theValue); my3DActor->SetShrinkFactor(theValue); + my3DExtActor->SetShrinkFactor(theValue); Modified(); } @@ -1141,6 +1195,7 @@ void SMESH_ActorDef::SetShrink(){ my2DActor->SetShrink(); my2DExtActor->SetShrink(); my3DActor->SetShrink(); + my3DExtActor->SetShrink(); myIsShrunk = true; Modified(); @@ -1157,6 +1212,7 @@ void SMESH_ActorDef::UnShrink(){ my2DActor->UnShrink(); my2DExtActor->UnShrink(); my3DActor->UnShrink(); + my3DExtActor->UnShrink(); myIsShrunk = false; Modified(); @@ -1203,6 +1259,7 @@ void SMESH_ActorDef::SetVisibility(int theMode, bool theIsUpdateRepersentation){ my2DActor->VisibilityOff(); my2DExtActor->VisibilityOff(); my3DActor->VisibilityOff(); + my3DExtActor->VisibilityOff(); myScalarBarActor->VisibilityOff(); myPointLabels->VisibilityOff(); @@ -1222,8 +1279,14 @@ void SMESH_ActorDef::SetVisibility(int theMode, bool theIsUpdateRepersentation){ my1DExtActor->VisibilityOn(); break; case eFreeFaces: + case eBareBorderFace: + case eOverConstrainedFace: my2DExtActor->VisibilityOn(); break; + case eBareBorderVolume: + case eOverConstrainedVolume: + my3DExtActor->VisibilityOn(); + break; case eLength2D: case eMultiConnection2D: my1DExtActor->VisibilityOn(); @@ -1456,6 +1519,7 @@ void SMESH_ActorDef::SetRepresentation (int theMode) //my0DExtActor->SetVisibility(false); my1DExtActor->SetVisibility(false); my2DExtActor->SetVisibility(false); + my3DExtActor->SetVisibility(false); // ??? //my0DActor->SetProperty(aProp); @@ -1786,6 +1850,7 @@ SMESH_ActorDef::SetImplicitFunctionUsed(bool theIsImplicitFunctionUsed) my2DActor->SetImplicitFunctionUsed(theIsImplicitFunctionUsed); my2DExtActor->SetImplicitFunctionUsed(theIsImplicitFunctionUsed); my3DActor->SetImplicitFunctionUsed(theIsImplicitFunctionUsed); + my3DExtActor->SetImplicitFunctionUsed(theIsImplicitFunctionUsed); } vtkIdType @@ -1947,7 +2012,7 @@ void SMESH_ActorDef::UpdateScalarBar() myScalarBarActor->SetDistributionColoringType(coloringType); QColor distributionColor = mgr->colorValue("SMESH", "distribution_color", - QColor(255, 255, 255)); + QColor(255, 255, 255)); double rgb[3]; rgb[0]= distributionColor.red()/255.; rgb[1]= distributionColor.green()/255.; @@ -1957,6 +2022,27 @@ void SMESH_ActorDef::UpdateScalarBar() } +void SMESH_ActorDef::UpdateDistribution() +{ + if(SMESH::Controls::NumericalFunctor* fun = + dynamic_cast(myFunctor.get())) + { + int nbIntervals = myScalarBarActor->GetMaximumNumberOfColors(); + std::vector nbEvents; + std::vector funValues; + SMESH_VisualObjDef::TEntityList elems; + if ( ! dynamic_cast(myVisualObj.get())) + dynamic_cast(myVisualObj.get())->GetEntities( fun->GetType(), elems ); + std::vector elemIds; + for ( SMESH_VisualObjDef::TEntityList::iterator e = elems.begin(); e != elems.end(); ++e) + elemIds.push_back( (*e)->GetID()); + vtkLookupTable* lookupTable = static_cast(myScalarBarActor->GetLookupTable()); + double * range = lookupTable->GetRange(); + fun->GetHistogram(nbIntervals, nbEvents, funValues, elemIds, range); + myScalarBarActor->SetDistribution(nbEvents); + } +} + void SMESH_ActorDef::SetQuadratic2DRepresentation(EQuadratic2DRepresentation theMode) { switch(theMode) { diff --git a/src/OBJECT/SMESH_Actor.h b/src/OBJECT/SMESH_Actor.h index 24a57a00a..744571e41 100644 --- a/src/OBJECT/SMESH_Actor.h +++ b/src/OBJECT/SMESH_Actor.h @@ -123,7 +123,8 @@ class SMESHOBJECT_EXPORT SMESH_Actor: public SALOME_Actor enum eControl{eNone, eLength, eLength2D, eFreeBorders, eFreeEdges, eFreeNodes, eFreeFaces, eMultiConnection, eArea, eTaper, eAspectRatio, eMinimumAngle, eWarping, eSkew, eAspectRatio3D, eMultiConnection2D, eVolume3D, - eMaxElementLength2D, eMaxElementLength3D}; + eMaxElementLength2D, eMaxElementLength3D, eBareBorderFace, eBareBorderVolume, + eOverConstrainedFace, eOverConstrainedVolume}; virtual void SetControlMode(eControl theMode) = 0; virtual eControl GetControlMode() = 0; virtual SMESH::Controls::FunctorPtr GetFunctor() = 0; @@ -141,6 +142,7 @@ class SMESHOBJECT_EXPORT SMESH_Actor: public SALOME_Actor virtual long GetControlsPrecision() const = 0; virtual void UpdateScalarBar() = 0; + virtual void UpdateDistribution() = 0; }; diff --git a/src/OBJECT/SMESH_ActorDef.h b/src/OBJECT/SMESH_ActorDef.h index 09b2232f0..53001f4ef 100644 --- a/src/OBJECT/SMESH_ActorDef.h +++ b/src/OBJECT/SMESH_ActorDef.h @@ -196,6 +196,7 @@ class SMESH_ActorDef : public SMESH_Actor virtual long GetControlsPrecision() const { return myControlsPrecision; } virtual void UpdateScalarBar(); + virtual void UpdateDistribution(); virtual void SetQuadratic2DRepresentation(EQuadratic2DRepresentation); @@ -234,6 +235,7 @@ class SMESH_ActorDef : public SMESH_Actor SMESH_DeviceActor* my2DActor; SMESH_DeviceActor* my2DExtActor; SMESH_DeviceActor* my3DActor; + SMESH_DeviceActor* my3DExtActor; SMESH_DeviceActor* myControlActor; vtkProperty* myNodeExtProp; diff --git a/src/OBJECT/SMESH_DeviceActor.cxx b/src/OBJECT/SMESH_DeviceActor.cxx index 600a4987c..d4a04203b 100644 --- a/src/OBJECT/SMESH_DeviceActor.cxx +++ b/src/OBJECT/SMESH_DeviceActor.cxx @@ -310,12 +310,6 @@ SMESH_DeviceActor double aValue = aNumericalFunctor->GetValue(anObjId); aScalars->SetValue(i,aValue); } - int nbIntervals = theScalarBarActor->GetMaximumNumberOfColors(); - std::vector nbEvents; - std::vector funValues; - aNumericalFunctor->GetHistogram(nbIntervals, nbEvents, funValues); - theScalarBarActor->SetDistribution(nbEvents); - }else if(Predicate* aPredicate = dynamic_cast(theFunctor.get())){ for(vtkIdType i = 0; i < aNbCells; i++){ vtkIdType anId = myExtractUnstructuredGrid->GetInputId(i); @@ -475,16 +469,6 @@ SMESH_DeviceActor myMergeFilter->SetScalars(aDataSet); aDataSet->Delete(); } - - //Set Distribution - if(NumericalFunctor* aNumericalFunctor = dynamic_cast(theFunctor.get())){ - int nbIntervals = theScalarBarActor->GetMaximumNumberOfColors(); - std::vector nbEvents; - std::vector funValues; - aNumericalFunctor->GetHistogram(nbIntervals, nbEvents, funValues); - theScalarBarActor->SetDistribution(nbEvents); - } - } GetMapper()->SetScalarVisibility(anIsInitialized); theScalarBarActor->SetVisibility(anIsInitialized); @@ -500,8 +484,13 @@ SMESH_DeviceActor myVisualObj->UpdateFunctor(theFunctor); using namespace SMESH::Controls; - if ( dynamic_cast(theFunctor.get()) || - dynamic_cast(theFunctor.get()) ) { + if ( dynamic_cast(theFunctor.get()) || + dynamic_cast(theFunctor.get()) || + dynamic_cast(theFunctor.get()) || + dynamic_cast(theFunctor.get()) || + dynamic_cast(theFunctor.get()) || + dynamic_cast(theFunctor.get())) + { Predicate* aFreePredicate = dynamic_cast(theFunctor.get()); myExtractUnstructuredGrid->SetModeOfChanging(VTKViewer_ExtractUnstructuredGrid::eAdding); vtkUnstructuredGrid* aGrid = myVisualObj->GetUnstructuredGrid(); @@ -514,7 +503,9 @@ SMESH_DeviceActor if(!myExtractUnstructuredGrid->IsCellsRegistered()) myExtractUnstructuredGrid->RegisterCell(-1); SetUnstructuredGrid(myVisualObj->GetUnstructuredGrid()); - }else if(FreeEdges* aFreeEdges = dynamic_cast(theFunctor.get())){ + } + else if(FreeEdges* aFreeEdges = dynamic_cast(theFunctor.get())) + { SMESH::Controls::FreeEdges::TBorders aBorders; aFreeEdges->GetBoreders(aBorders); vtkUnstructuredGrid* aDataSet = vtkUnstructuredGrid::New(); @@ -561,7 +552,9 @@ SMESH_DeviceActor SetUnstructuredGrid(aDataSet); aDataSet->Delete(); - }else if(FreeNodes* aFreeNodes = dynamic_cast(theFunctor.get())){ + } + else if(FreeNodes* aFreeNodes = dynamic_cast(theFunctor.get())) + { myExtractUnstructuredGrid->SetModeOfChanging(VTKViewer_ExtractUnstructuredGrid::eAdding); vtkIdType aNbNodes = myVisualObj->GetNbEntities(SMDSAbs_Node); for( vtkIdType i = 0; i < aNbNodes; i++ ){ diff --git a/src/SMESH/SMESH_Mesh.cxx b/src/SMESH/SMESH_Mesh.cxx index 39c2ca976..a85e23e23 100644 --- a/src/SMESH/SMESH_Mesh.cxx +++ b/src/SMESH/SMESH_Mesh.cxx @@ -265,14 +265,12 @@ void SMESH_Mesh::Clear() _myMeshDS->ClearMesh(); // update compute state of submeshes - if ( SMESH_subMesh *sm = GetSubMeshContaining( GetShapeToMesh() ) ) { - SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true, - /*complexShapeFirst=*/false); - while ( smIt->more() ) { - sm = smIt->next(); - sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); - sm->ComputeStateEngine( SMESH_subMesh::CLEAN ); // for event listeners (issue 0020918) - } + if ( SMESH_subMesh *sm = GetSubMeshContaining( GetShapeToMesh() ) ) + { + sm->ComputeStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); + sm->ComputeSubMeshStateEngine( SMESH_subMesh::CHECK_COMPUTE_STATE ); + sm->ComputeStateEngine( SMESH_subMesh::CLEAN ); // for event listeners (issue 0020918) + sm->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN ); } _isModified = false; } diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index f26db9a0c..48c10820f 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -128,19 +128,7 @@ SMESH_MeshEditor::AddElement(const vector & node, int nbnode = node.size(); SMESHDS_Mesh* mesh = GetMeshDS(); switch ( type ) { - case SMDSAbs_0DElement: - if ( nbnode == 1 ) - if ( ID ) e = mesh->Add0DElementWithID(node[0], ID); - else e = mesh->Add0DElement (node[0] ); - break; - case SMDSAbs_Edge: - if ( nbnode == 2 ) - if ( ID ) e = mesh->AddEdgeWithID(node[0], node[1], ID); - else e = mesh->AddEdge (node[0], node[1] ); - else if ( nbnode == 3 ) - if ( ID ) e = mesh->AddEdgeWithID(node[0], node[1], node[2], ID); - else e = mesh->AddEdge (node[0], node[1], node[2] ); - break; + case SMDSAbs_Face: if ( !isPoly ) { if (nbnode == 3) @@ -164,6 +152,7 @@ SMESH_MeshEditor::AddElement(const vector & node, else e = mesh->AddPolygonalFace (node ); } break; + case SMDSAbs_Volume: if ( !isPoly ) { if (nbnode == 4) @@ -221,6 +210,29 @@ SMESH_MeshEditor::AddElement(const vector & node, node[12],node[13],node[14],node[15], node[16],node[17],node[18],node[19] ); } + break; + + case SMDSAbs_Edge: + if ( nbnode == 2 ) + if ( ID ) e = mesh->AddEdgeWithID(node[0], node[1], ID); + else e = mesh->AddEdge (node[0], node[1] ); + else if ( nbnode == 3 ) + if ( ID ) e = mesh->AddEdgeWithID(node[0], node[1], node[2], ID); + else e = mesh->AddEdge (node[0], node[1], node[2] ); + break; + + case SMDSAbs_0DElement: + if ( nbnode == 1 ) + if ( ID ) e = mesh->Add0DElementWithID(node[0], ID); + else e = mesh->Add0DElement (node[0] ); + break; + + case SMDSAbs_Node: + if ( ID ) e = mesh->AddNodeWithID(node[0]->X(), node[0]->Y(), node[0]->Z(), ID); + else e = mesh->AddNode (node[0]->X(), node[0]->Y(), node[0]->Z()); + break; + + default:; } if ( e ) myLastCreatedElems.Append( e ); return e; diff --git a/src/SMESH/SMESH_subMesh.cxx b/src/SMESH/SMESH_subMesh.cxx index 69b33a94c..76418c59f 100644 --- a/src/SMESH/SMESH_subMesh.cxx +++ b/src/SMESH/SMESH_subMesh.cxx @@ -1699,7 +1699,7 @@ bool SMESH_subMesh::CheckComputeError(SMESH_Algo* theAlgo, const TopoDS_Shape& t // Check my state if ( !_computeError || _computeError->IsOK() ) { - _computeState = COMPUTE_OK; + _computeState = IsMeshComputed() ? COMPUTE_OK : FAILED_TO_COMPUTE; } else { diff --git a/src/SMESH/SMESH_subMesh.hxx b/src/SMESH/SMESH_subMesh.hxx index 2929c023f..05c1d7f82 100644 --- a/src/SMESH/SMESH_subMesh.hxx +++ b/src/SMESH/SMESH_subMesh.hxx @@ -192,6 +192,7 @@ public: void DumpAlgoState(bool isMain); bool ComputeStateEngine(int event); + void ComputeSubMeshStateEngine(int event); bool Evaluate(MapShapeNbElems& aResMap); @@ -249,7 +250,6 @@ protected: void RemoveSubMeshElementsAndNodes(); void UpdateDependantsState(const compute_event theEvent); void UpdateSubMeshState(const compute_state theState); - void ComputeSubMeshStateEngine(int event); void CleanDependants(); void CleanDependsOn(); void SetAlgoState(int state); diff --git a/src/SMESHFiltersSelection/SMESH_Type.h b/src/SMESHFiltersSelection/SMESH_Type.h index 89857d89c..ee962f22e 100644 --- a/src/SMESHFiltersSelection/SMESH_Type.h +++ b/src/SMESHFiltersSelection/SMESH_Type.h @@ -25,7 +25,6 @@ // Author : Nicolas REJNERI // Project : SALOME // Module : SMESH -// $Header$ // #ifndef SMESH_TYPE_HEADER #define SMESH_TYPE_HEADER @@ -57,7 +56,8 @@ enum MeshObjectType { GROUP_FACE, GROUP_VOLUME, GROUP_0D, - COMPONENT + COMPONENT, + IDSOURCE }; #endif diff --git a/src/SMESHFiltersSelection/SMESH_TypeFilter.cxx b/src/SMESHFiltersSelection/SMESH_TypeFilter.cxx index 1fbb37516..a684d7023 100644 --- a/src/SMESHFiltersSelection/SMESH_TypeFilter.cxx +++ b/src/SMESHFiltersSelection/SMESH_TypeFilter.cxx @@ -203,6 +203,12 @@ bool SMESH_TypeFilter::isOk (const SUIT_DataOwner* theDataOwner) const Ok = true; break; } + case IDSOURCE: + { + Ok = ( SMESH_TypeFilter(MESHorSUBMESH).isOk( theDataOwner ) || + SMESH_TypeFilter(GROUP) .isOk( theDataOwner )); + break; + } } } return Ok; diff --git a/src/SMESHGUI/Makefile.am b/src/SMESHGUI/Makefile.am index 7e7448f59..6da5d4076 100644 --- a/src/SMESHGUI/Makefile.am +++ b/src/SMESHGUI/Makefile.am @@ -94,6 +94,7 @@ salomeinclude_HEADERS = \ SMESHGUI_MeshOrderDlg.h \ SMESHGUI_MeshOrderOp.h \ SMESHGUI_FileValidator.h \ + SMESHGUI_CopyMeshDlg.h \ SMESH_SMESHGUI.hxx # Libraries targets @@ -167,6 +168,7 @@ dist_libSMESH_la_SOURCES = \ SMESHGUI_FindElemByPointDlg.cxx \ SMESHGUI_MeshOrderDlg.cxx \ SMESHGUI_MeshOrderOp.cxx \ + SMESHGUI_CopyMeshDlg.cxx \ SMESHGUI_FileValidator.cxx MOC_FILES = \ @@ -224,6 +226,7 @@ MOC_FILES = \ SMESHGUI_Make2DFrom3DOp_moc.cxx \ SMESHGUI_FindElemByPointDlg_moc.cxx \ SMESHGUI_MeshOrderDlg_moc.cxx \ + SMESHGUI_CopyMeshDlg_moc.cxx \ SMESHGUI_MeshOrderOp_moc.cxx nodist_libSMESH_la_SOURCES= \ diff --git a/src/SMESHGUI/SMESHGUI.cxx b/src/SMESHGUI/SMESHGUI.cxx index e684d705d..1ae0a94a5 100644 --- a/src/SMESHGUI/SMESHGUI.cxx +++ b/src/SMESHGUI/SMESHGUI.cxx @@ -76,6 +76,7 @@ #include "SMESHGUI_TransparencyDlg.h" //#include "SMESHGUI_WhatIsDlg.h" #include "SMESHGUI_DuplicateNodesDlg.h" +#include "SMESHGUI_CopyMeshDlg.h" #include "SMESHGUI_Utils.h" #include "SMESHGUI_MeshUtils.h" @@ -141,6 +142,7 @@ #include #include #include +#include // SALOME KERNEL includes #include @@ -759,6 +761,14 @@ type = QObject::tr( "FREE_BORDERS" ); else if ( dynamic_cast< SMESH::Controls::FreeFaces* >( f.get() ) ) type = QObject::tr( "FREE_FACES" ); + else if ( dynamic_cast< SMESH::Controls::BareBorderVolume* >( f.get() ) ) + type = QObject::tr( "BARE_BORDER_VOLUME" ); + else if ( dynamic_cast< SMESH::Controls::BareBorderFace* >( f.get() ) ) + type = QObject::tr( "BARE_BORDER_FACE" ); + else if ( dynamic_cast< SMESH::Controls::OverConstrainedVolume* >( f.get() ) ) + type = QObject::tr( "OVER_CONSTRAINED_VOLUME" ); + else if ( dynamic_cast< SMESH::Controls::OverConstrainedFace* >( f.get() ) ) + type = QObject::tr( "OVER_CONSTRAINED_FACE" ); return type; } @@ -779,10 +789,26 @@ if ( aScalarBarActor && aFunctor ) { SMESH::Controls::NumericalFunctor* aNumFun = dynamic_cast( aFunctor.get() ); if ( aNumFun ) { - int nbRanges = aScalarBarActor->GetMaximumNumberOfColors(); + std::vector elements; + SMESH::SMESH_Mesh_var mesh = SMESH::IObjectToInterface(anIO); + if ( mesh->_is_nil() ) { + SMESH::SMESH_IDSource_var idSource = + SMESH::IObjectToInterface(anIO); + if ( !idSource->_is_nil() ) + { + SMESH::long_array_var ids = idSource->GetIDs(); + elements.resize( ids->length() ); + for ( unsigned i = 0; i < elements.size(); ++i ) + elements[i] = ids[i]; + } + } + int nbIntervals = aScalarBarActor->GetMaximumNumberOfColors(); + vtkLookupTable* lookupTable = + static_cast(aScalarBarActor->GetLookupTable()); + double * minmax = lookupTable->GetRange(); std::vector nbEvents; std::vector funValues; - aNumFun->GetHistogram( nbRanges, nbEvents, funValues ); + aNumFun->GetHistogram( nbIntervals, nbEvents, funValues, elements, minmax ); QString anInitialPath = ""; if ( SUIT_FileDlg::getLastVisitedPath().isEmpty() ) anInitialPath = QDir::currentPath(); @@ -1178,6 +1204,18 @@ case 6023: aControl = SMESH_Actor::eMaxElementLength3D; break; + case 6024: + aControl = SMESH_Actor::eBareBorderVolume; + break; + case 6025: + aControl = SMESH_Actor::eBareBorderFace; + break; + case 6026: + aControl = SMESH_Actor::eOverConstrainedVolume; + break; + case 6027: + aControl = SMESH_Actor::eOverConstrainedFace; + break; } anActor->SetControlMode(aControl); anActor->GetScalarBarActor()->SetTitle( functorToString( anActor->GetFunctor() ).toLatin1().constData() ); @@ -2013,6 +2051,13 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) case 704: // Edit mesh/sub-mesh startOperation( theCommandID ); break; + case 705: // copy mesh + { + if (checkLock(aStudy)) break; + EmitSignalDeactivateDialog(); + ( new SMESHGUI_CopyMeshDlg( this ) )->show(); + } + break; case 710: // Build compound mesh { if (checkLock(aStudy)) break; @@ -2962,6 +3007,10 @@ bool SMESHGUI::OnGUIEvent( int theCommandID ) case 6021: case 6022: case 6023: + case 6024: + case 6025: + case 6026: + case 6027: if ( vtkwnd ) { LightApp_SelectionMgr* mgr = selectionMgr(); @@ -3178,6 +3227,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createSMESHAction( 702, "CREATE_MESH", "ICON_DLG_INIT_MESH" ); createSMESHAction( 703, "CREATE_SUBMESH", "ICON_DLG_ADD_SUBMESH" ); createSMESHAction( 704, "EDIT_MESHSUBMESH","ICON_DLG_EDIT_MESH" ); + createSMESHAction( 705, "COPY_MESH", "ICON_COPY_MESH" ); createSMESHAction( 710, "BUILD_COMPOUND", "ICON_BUILD_COMPOUND" ); createSMESHAction( 711, "PRECOMPUTE", "ICON_PRECOMPUTE" ); createSMESHAction( 712, "EVALUATE", "ICON_COMPUTE" ); @@ -3203,6 +3253,10 @@ void SMESHGUI::initialize( CAM_Application* app ) createSMESHAction( 6021, "FREE_FACES", "ICON_FREE_FACES", 0, true ); createSMESHAction( 6022, "MAX_ELEMENT_LENGTH_2D", "ICON_MAX_ELEMENT_LENGTH_2D", 0, true ); createSMESHAction( 6023, "MAX_ELEMENT_LENGTH_3D", "ICON_MAX_ELEMENT_LENGTH_3D", 0, true ); + createSMESHAction( 6024, "BARE_BORDER_VOLUME","ICON_BARE_BORDER_VOLUME", 0, true ); + createSMESHAction( 6025, "BARE_BORDER_FACE","ICON_BARE_BORDER_FACE", 0, true ); + createSMESHAction( 6026, "OVER_CONSTRAINED_VOLUME","ICON_OVER_CONSTRAINED_VOLUME", 0, true ); + createSMESHAction( 6027, "OVER_CONSTRAINED_FACE","ICON_OVER_CONSTRAINED_FACE", 0, true ); createSMESHAction( 6003, "FREE_BORDER", "ICON_FREE_EDGE_2D", 0, true ); createSMESHAction( 6004, "CONNECTION", "ICON_CONNECTION", 0, true ); createSMESHAction( 6005, "FREE_NODE", "ICON_FREE_NODE", 0, true ); @@ -3342,6 +3396,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createMenu( 703, meshId, -1 ); createMenu( 704, meshId, -1 ); createMenu( 710, meshId, -1 ); + createMenu( 705, meshId, -1 ); createMenu( separator(), meshId, -1 ); createMenu( 701, meshId, -1 ); createMenu( 711, meshId, -1 ); @@ -3372,6 +3427,8 @@ void SMESHGUI::initialize( CAM_Application* app ) createMenu( 6001, edgeId, -1 ); createMenu( 6004, edgeId, -1 ); createMenu( 6021, faceId, -1 ); + createMenu( 6025, faceId, -1 ); + createMenu( 6027, faceId, -1 ); createMenu( 6018, faceId, -1 ); createMenu( 6019, faceId, -1 ); createMenu( 6011, faceId, -1 ); @@ -3384,6 +3441,8 @@ void SMESHGUI::initialize( CAM_Application* app ) createMenu( 6017, volumeId, -1 ); createMenu( 6009, volumeId, -1 ); createMenu( 6023, volumeId, -1 ); + createMenu( 6024, volumeId, -1 ); + createMenu( 6026, volumeId, -1 ); createMenu( 4000, addId, -1 ); createMenu( 4009, addId, -1 ); @@ -3453,6 +3512,7 @@ void SMESHGUI::initialize( CAM_Application* app ) createTool( 703, meshTb ); createTool( 704, meshTb ); createTool( 710, meshTb ); + createTool( 705, meshTb ); createTool( separator(), meshTb ); createTool( 701, meshTb ); createTool( 711, meshTb ); @@ -3479,6 +3539,8 @@ void SMESHGUI::initialize( CAM_Application* app ) createTool( 6004, ctrlTb ); createTool( separator(), ctrlTb ); createTool( 6021, ctrlTb ); + createTool( 6025, ctrlTb ); + createTool( 6027, ctrlTb ); createTool( 6018, ctrlTb ); createTool( 6019, ctrlTb ); createTool( 6011, ctrlTb ); @@ -3492,6 +3554,8 @@ void SMESHGUI::initialize( CAM_Application* app ) createTool( 6017, ctrlTb ); createTool( 6009, ctrlTb ); createTool( 6023, ctrlTb ); + createTool( 6024, ctrlTb ); + createTool( 6026, ctrlTb ); createTool( separator(), ctrlTb ); createTool( 4000, addRemTb ); @@ -3794,50 +3858,58 @@ void SMESHGUI::initialize( CAM_Application* app ) aSubId = popupMgr()->insert( tr( "MEN_FACE_CTRL" ), anId, -1 ); // FACE CONTROLS - popupMgr()->insert( action( 6021 ), aSubId, -1 ); // FREE_FACE + popupMgr()->insert ( action( 6021 ), aSubId, -1 ); // FREE_FACE popupMgr()->setRule( action( 6021 ), aMeshInVtkHasFaces /*aMeshInVtkHasVolumes*/, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6021 ), "controlMode = 'eFreeFaces'", QtxPopupMgr::ToggleRule ); - popupMgr()->insert( action( 6018 ), aSubId, -1 ); // LENGTH_2D + popupMgr()->insert ( action( 6018 ), aSubId, -1 ); // LENGTH_2D popupMgr()->setRule( action( 6018 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6018 ), "controlMode = 'eLength2D'", QtxPopupMgr::ToggleRule ); - popupMgr()->insert( action( 6019 ), aSubId, -1 ); // CONNECTION_2D + popupMgr()->insert ( action( 6019 ), aSubId, -1 ); // CONNECTION_2D popupMgr()->setRule( action( 6019 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6019 ), "controlMode = 'eMultiConnection2D'", QtxPopupMgr::ToggleRule ); - popupMgr()->insert( action( 6011 ), aSubId, -1 ); // AREA + popupMgr()->insert ( action( 6011 ), aSubId, -1 ); // AREA popupMgr()->setRule( action( 6011 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6011 ), "controlMode = 'eArea'", QtxPopupMgr::ToggleRule ); - popupMgr()->insert( action( 6012 ), aSubId, -1 ); // TAPER + popupMgr()->insert ( action( 6012 ), aSubId, -1 ); // TAPER popupMgr()->setRule( action( 6012 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6012 ), "controlMode = 'eTaper'", QtxPopupMgr::ToggleRule ); - popupMgr()->insert( action( 6013 ), aSubId, -1 ); // ASPECT + popupMgr()->insert ( action( 6013 ), aSubId, -1 ); // ASPECT popupMgr()->setRule( action( 6013 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6013 ), "controlMode = 'eAspectRatio'", QtxPopupMgr::ToggleRule ); - popupMgr()->insert( action( 6014 ), aSubId, -1 ); // MIN_ANG + popupMgr()->insert ( action( 6014 ), aSubId, -1 ); // MIN_ANG popupMgr()->setRule( action( 6014 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6014 ), "controlMode = 'eMinimumAngle'", QtxPopupMgr::ToggleRule ); - popupMgr()->insert( action( 6015 ), aSubId, -1 ); // WARP + popupMgr()->insert ( action( 6015 ), aSubId, -1 ); // WARP popupMgr()->setRule( action( 6015 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6015 ), "controlMode = 'eWarping'", QtxPopupMgr::ToggleRule ); - popupMgr()->insert( action( 6016 ), aSubId, -1 ); // SKEW + popupMgr()->insert ( action( 6016 ), aSubId, -1 ); // SKEW popupMgr()->setRule( action( 6016 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6016 ), "controlMode = 'eSkew'", QtxPopupMgr::ToggleRule ); - popupMgr()->insert( action( 6022 ), aSubId, -1 ); // MAX_ELEMENT_LENGTH_2D + popupMgr()->insert ( action( 6022 ), aSubId, -1 ); // MAX_ELEMENT_LENGTH_2D popupMgr()->setRule( action( 6022 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6022 ), "controlMode = 'eMaxElementLength2D'", QtxPopupMgr::ToggleRule ); + popupMgr()->insert ( action( 6025 ), aSubId, -1 ); // BARE_BORDER_FACE + popupMgr()->setRule( action( 6025 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); + popupMgr()->setRule( action( 6025 ), "controlMode = 'eBareBorderFace'", QtxPopupMgr::ToggleRule ); + + popupMgr()->insert ( action( 6027 ), aSubId, -1 ); // OVER_CONSTRAINED_FACE + popupMgr()->setRule( action( 6027 ), aMeshInVtkHasFaces, QtxPopupMgr::VisibleRule ); + popupMgr()->setRule( action( 6027 ), "controlMode = 'eOverConstrainedFace'", QtxPopupMgr::ToggleRule ); + aSubId = popupMgr()->insert( tr( "MEN_VOLUME_CTRL" ), anId, -1 ); // VOLUME CONTROLS - popupMgr()->insert( action( 6017 ), aSubId, -1 ); // ASPECT_3D + popupMgr()->insert ( action( 6017 ), aSubId, -1 ); // ASPECT_3D popupMgr()->setRule( action( 6017 ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6017 ), "controlMode = 'eAspectRatio3D'", QtxPopupMgr::ToggleRule ); @@ -3845,10 +3917,18 @@ void SMESHGUI::initialize( CAM_Application* app ) popupMgr()->setRule( action( 6009 ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6009 ), "controlMode = 'eVolume3D'", QtxPopupMgr::ToggleRule ); - popupMgr()->insert( action( 6023 ), aSubId, -1 ); // MAX_ELEMENT_LENGTH_3D + popupMgr()->insert ( action( 6023 ), aSubId, -1 ); // MAX_ELEMENT_LENGTH_3D popupMgr()->setRule( action( 6023 ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule ); popupMgr()->setRule( action( 6023 ), "controlMode = 'eMaxElementLength3D'", QtxPopupMgr::ToggleRule ); + popupMgr()->insert ( action( 6024 ), aSubId, -1 ); // BARE_BORDER_VOLUME + popupMgr()->setRule( action( 6024 ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule ); + popupMgr()->setRule( action( 6024 ), "controlMode = 'eBareBorderVolume'", QtxPopupMgr::ToggleRule ); + + popupMgr()->insert ( action( 6026 ), aSubId, -1 ); // OVER_CONSTRAINED_VOLUME + popupMgr()->setRule( action( 6026 ), aMeshInVtkHasVolumes, QtxPopupMgr::VisibleRule ); + popupMgr()->setRule( action( 6026 ), "controlMode = 'eOverConstrainedVolume'", QtxPopupMgr::ToggleRule ); + popupMgr()->insert( separator(), anId, -1 ); popupMgr()->insert( action( 201 ), anId, -1 ); // SCALAR_BAR_PROP diff --git a/src/SMESHGUI/SMESHGUI_CopyMeshDlg.cxx b/src/SMESHGUI/SMESHGUI_CopyMeshDlg.cxx new file mode 100644 index 000000000..f4b6950bf --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_CopyMeshDlg.cxx @@ -0,0 +1,667 @@ +// Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 +// +// SMESH SMESHGUI : GUI for SMESH component +// File : SMESHGUI_CopyMeshDlg.cxx + +#include "SMESHGUI_CopyMeshDlg.h" + +#include "SMESHGUI.h" +#include "SMESHGUI_SpinBox.h" +#include "SMESHGUI_Utils.h" +#include "SMESHGUI_VTKUtils.h" +#include "SMESHGUI_MeshUtils.h" +#include "SMESHGUI_IdValidator.h" +#include "SMESHGUI_FilterDlg.h" + +#include +#include +#include + +// SALOME GUI includes +#include +#include +#include +#include +#include + +#include +#include + +#include +#include +#include + +// SALOME KERNEL includes +#include + +// OCCT includes +#include + +// Qt includes +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// IDL includes +#include +#include CORBA_SERVER_HEADER(SMESH_Group) +#include CORBA_SERVER_HEADER(SMESH_MeshEditor) + +/*! + \class BusyLocker + \brief Simple 'busy state' flag locker. + \internal +*/ + +namespace +{ + class BusyLocker + { + public: + //! Constructor. Sets passed boolean flag to \c true. + BusyLocker( bool& busy ) : myBusy( busy ) { myBusy = true; } + //! Destructor. Clear external boolean flag passed as parameter to the constructor to \c false. + ~BusyLocker() { myBusy = false; } + private: + bool& myBusy; //! External 'busy state' boolean flag + }; +} + +#define SPACING 6 +#define MARGIN 11 + +//To disable automatic genericobj management, the following line should be commented. +//Otherwise, it should be uncommented. Refer to KERNEL_SRC/src/SALOMEDSImpl/SALOMEDSImpl_AttributeIOR.cxx +#define WITHGENERICOBJ + + +//================================================================================ +/*! + * \brief Constructor + */ +//================================================================================ + +SMESHGUI_CopyMeshDlg::SMESHGUI_CopyMeshDlg( SMESHGUI* theModule ) + : QDialog( SMESH::GetDesktop( theModule ) ), + mySMESHGUI( theModule ), + mySelectionMgr( SMESH::GetSelectionMgr( theModule ) ), + myFilterDlg(0), + mySelectedObject(SMESH::SMESH_IDSource::_nil()) +{ + QPixmap image (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_COPY_MESH"))); + + setModal(false); + setAttribute(Qt::WA_DeleteOnClose, true); + setWindowTitle(tr("SMESH_COPY_MESH_TITLE")); + setSizeGripEnabled(true); + + QVBoxLayout* SMESHGUI_CopyMeshDlgLayout = new QVBoxLayout(this); + SMESHGUI_CopyMeshDlgLayout->setSpacing(SPACING); + SMESHGUI_CopyMeshDlgLayout->setMargin(MARGIN); + + /***************************************************************/ + ConstructorsBox = new QGroupBox(tr("SMESH_COPY_MESH_TITLE"), this); + QButtonGroup* GroupConstructors = new QButtonGroup(this); + QHBoxLayout* ConstructorsBoxLayout = new QHBoxLayout(ConstructorsBox); + ConstructorsBoxLayout->setSpacing(SPACING); + ConstructorsBoxLayout->setMargin(MARGIN); + + QRadioButton* RadioButton1= new QRadioButton(ConstructorsBox); + RadioButton1->setIcon(image); + GroupConstructors->addButton(RadioButton1, 0); + + ConstructorsBoxLayout->addWidget(RadioButton1); + RadioButton1->setChecked(true); + GroupConstructors->addButton(RadioButton1, 0); + + /***************************************************************/ + GroupArguments = new QGroupBox(tr("SMESH_ARGUMENTS"), this); + QGridLayout* GroupArgumentsLayout = new QGridLayout(GroupArguments); + GroupArgumentsLayout->setSpacing(SPACING); + GroupArgumentsLayout->setMargin(MARGIN); + + myIdValidator = new SMESHGUI_IdValidator(this); + + // Controls for idSource/elements selection + myTextLabelElements = new QLabel(tr("OBJECT_NAME"), GroupArguments); + myLineEditElements = new QLineEdit(GroupArguments); + myLineEditElements->setValidator(myIdValidator); + myLineEditElements->setMaxLength(-1); + myFilterBtn = new QPushButton( tr( "SMESH_BUT_FILTER" ), GroupArguments ); + connect(myFilterBtn, SIGNAL(clicked()), this, SLOT(setFilters())); + + // Control for the mesh objects selection + myIdSourceCheck = new QCheckBox(tr("SMESH_SELECT_WHOLE_MESH"), GroupArguments); + + // Name of a mesh to create + QLabel* meshNameLabel = new QLabel(tr("NEW_NAME"), GroupArguments); + myMeshNameEdit = new QLineEdit(GroupArguments); + + // CheckBox for copying groups + myCopyGroupsCheck = new QCheckBox(tr("SMESH_MAKE_GROUPS"), GroupArguments); + myCopyGroupsCheck->setChecked(false); + + // CheckBox for keeping ids + myKeepIdsCheck = new QCheckBox(tr("SMESH_KEEP_IDS"), GroupArguments); + myKeepIdsCheck->setChecked(true); + + // layout + GroupArgumentsLayout->addWidget(myTextLabelElements, 0, 0); + GroupArgumentsLayout->addWidget(myLineEditElements, 0, 1, 1, 5); + GroupArgumentsLayout->addWidget(myFilterBtn, 0, 6); + GroupArgumentsLayout->addWidget(myIdSourceCheck, 1, 0, 1, 6); + GroupArgumentsLayout->addWidget(meshNameLabel, 2, 0); + GroupArgumentsLayout->addWidget(myMeshNameEdit, 2, 1, 1, 5); + GroupArgumentsLayout->addWidget(myCopyGroupsCheck, 3, 0, 1, 6); + GroupArgumentsLayout->addWidget(myKeepIdsCheck, 4, 0, 1, 6); + + /***************************************************************/ + 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); + + /***************************************************************/ + SMESHGUI_CopyMeshDlgLayout->addWidget(ConstructorsBox); + SMESHGUI_CopyMeshDlgLayout->addWidget(GroupArguments); + SMESHGUI_CopyMeshDlgLayout->addWidget(GroupButtons); + + /* Initialisations */ + mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector(); + + mySMESHGUI->SetActiveDialogBox((QDialog*)this); + + // Selection filter + myIdSourceFilter = new SMESH_TypeFilter( IDSOURCE ); + + myHelpFileName = "copy_mesh_page.html"; + + Init(); + + /* signals and slots connections */ + connect(buttonOk, SIGNAL(clicked()), this, SLOT(ClickOnOk())); + connect(buttonCancel, SIGNAL(clicked()), this, SLOT(ClickOnCancel())); + 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())); + connect(mySMESHGUI, SIGNAL (SignalCloseAllDialogs()),/* to close dialog if study change */ + this, SLOT (ClickOnCancel())); + + connect(myLineEditElements, SIGNAL(textChanged(const QString&)), + this, SLOT (onTextChange(const QString&))); + connect(myIdSourceCheck, SIGNAL(toggled(bool)), + this, SLOT (onSelectIdSource(bool))); + + SelectionIntoArgument(); +} + +//================================================================================= +// function : ~SMESHGUI_CopyMeshDlg() +// purpose : Destroys the object and frees any allocated resources +//================================================================================= + +SMESHGUI_CopyMeshDlg::~SMESHGUI_CopyMeshDlg() +{ + if ( myFilterDlg ) + { + myFilterDlg->setParent( 0 ); + delete myFilterDlg; myFilterDlg = 0; + } + if ( myIdSourceFilter ) + { + if ( mySelectionMgr ) + mySelectionMgr->removeFilter( myIdSourceFilter ); + delete myIdSourceFilter; myIdSourceFilter=0; + } +} + +//================================================================================= +// function : Init() +// purpose : +//================================================================================= +void SMESHGUI_CopyMeshDlg::Init (bool ResetControls) +{ + myBusy = false; + + myMeshNameEdit->setText( SMESH::UniqueMeshName("Mesh")); + if ( ResetControls ) + { + myLineEditElements->clear(); + //myElementsId = ""; + myNbOkElements = 0; + + buttonOk->setEnabled(false); + buttonApply->setEnabled(false); + + myActor = 0; + myMesh = SMESH::SMESH_Mesh::_nil(); + + myIdSourceCheck->setChecked(true); + myCopyGroupsCheck->setChecked(false); + myKeepIdsCheck->setChecked(false); + + onSelectIdSource( myIdSourceCheck->isChecked() ); + } +} + +//================================================================================= +// function : ClickOnApply() +// purpose : +//================================================================================= + +bool SMESHGUI_CopyMeshDlg::ClickOnApply() +{ + if (mySMESHGUI->isActiveStudyLocked()) + return false; + + if( !isValid() ) + return false; + + try + { + SUIT_OverrideCursor aWaitCursor; + SMESH::SMESH_IDSource_var aPartToCopy; + if ( myIdSourceCheck->isChecked()) + { + aPartToCopy = mySelectedObject; + } + else + { + QStringList aListElementsId = myLineEditElements->text().split(" ", QString::SkipEmptyParts); + SMESH::long_array_var anElementsId = new SMESH::long_array; + anElementsId->length(aListElementsId.count()); + for (int i = 0; i < aListElementsId.count(); i++) + anElementsId[i] = aListElementsId[i].toInt(); + + SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor(); + aPartToCopy = aMeshEditor->MakeIDSource( anElementsId, SMESH::ALL ); + } + QByteArray meshName = myMeshNameEdit->text().toLatin1(); + bool toCopyGroups = ( myCopyGroupsCheck->isChecked() ); + bool toKeepIDs = ( myKeepIdsCheck->isChecked() ); + + SMESH::SMESH_Gen_var gen = SMESHGUI::GetSMESHGen(); + SMESH::SMESH_Mesh_var newMesh = + gen->CopyMesh(aPartToCopy, meshName.constData(), toCopyGroups, toKeepIDs); +#ifdef WITHGENERICOBJ + // obj has been published in study. Its refcount has been incremented. + // It is safe to decrement its refcount + // so that it will be destroyed when the entry in study will be removed + newMesh->Destroy(); +#endif + } catch (...) { + } + + mySMESHGUI->updateObjBrowser(true); + SMESHGUI::Modified(); + + Init(false); + mySelectedObject = SMESH::SMESH_IDSource::_nil(); + SelectionIntoArgument(); + + return true; +} + +//================================================================================= +// function : ClickOnOk() +// purpose : +//================================================================================= +void SMESHGUI_CopyMeshDlg::ClickOnOk() +{ + if( ClickOnApply() ) + ClickOnCancel(); +} + +//================================================================================= +// function : ClickOnCancel() +// purpose : +//================================================================================= +void SMESHGUI_CopyMeshDlg::ClickOnCancel() +{ + disconnect(mySelectionMgr, 0, this, 0); + if ( mySelectionMgr ) + mySelectionMgr->removeFilter( myIdSourceFilter ); + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) + aViewWindow->SetSelectionMode( ActorSelection ); + mySMESHGUI->ResetState(); + reject(); +} + +//================================================================================= +// function : ClickOnHelp() +// purpose : +//================================================================================= +void SMESHGUI_CopyMeshDlg::ClickOnHelp() +{ + 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 : onTextChange() +// purpose : +//======================================================================= + +void SMESHGUI_CopyMeshDlg::onTextChange (const QString& theNewText) +{ + QLineEdit* send = (QLineEdit*)sender(); + + if (myBusy) return; + BusyLocker lock( myBusy ); + + //if (send == myLineEditElements) + myNbOkElements = 0; + + buttonOk->setEnabled(false); + buttonApply->setEnabled(false); + + // hilight entered elements + SMDS_Mesh* aMesh = 0; + if (myActor) + aMesh = myActor->GetObject()->GetMesh(); + + QStringList aListId = theNewText.split(" ", QString::SkipEmptyParts); + if (myActor && aMesh) + { + TColStd_MapOfInteger newIndices; + if (send == myLineEditElements) { + for (int i = 0; i < aListId.count(); i++) + if ( const SMDS_MeshElement * e = aMesh->FindElement(aListId[ i ].toInt())) + { + newIndices.Add(e->GetID()); + } + } + myNbOkElements = newIndices.Extent(); + + Handle(SALOME_InteractiveObject) anIO = myActor->getIO(); + mySelector->AddOrRemoveIndex( anIO, newIndices, false ); + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) + aViewWindow->highlight( anIO, true, true ); + } + else + { + myNbOkElements = aListId.count(); + } + + if (myNbOkElements) { + buttonOk->setEnabled(true); + buttonApply->setEnabled(true); + } +} + +//================================================================================= +// function : SelectionIntoArgument() +// purpose : Called when selection as changed or other case +//================================================================================= + +void SMESHGUI_CopyMeshDlg::SelectionIntoArgument() +{ + if (myBusy) return; + BusyLocker lock( myBusy ); + + // clear + myActor = 0; + QString aString = ""; + + myLineEditElements->setText(aString); + myNbOkElements = 0; + buttonOk->setEnabled(false); + buttonApply->setEnabled(false); + myFilterBtn->setEnabled(false); + + // get selected mesh + SALOME_ListIO aList; + mySelectionMgr->selectedObjects(aList,SVTK_Viewer::Type()); + int nbSel = aList.Extent(); + if (nbSel != 1) + return; + + Handle(SALOME_InteractiveObject) IO = aList.First(); + mySelectedObject = SMESH::IObjectToInterface( IO ); + if ( mySelectedObject->_is_nil() ) + return; + + myMesh = SMESH::GetMeshByIO(IO); + if (myMesh->_is_nil()) + return; + + myActor = SMESH::FindActorByEntry(IO->getEntry()); + if (!myActor) + myActor = SMESH::FindActorByObject(myMesh); + + if (myIdSourceCheck->isChecked()) + { + SMESH::GetNameOfSelectedIObjects( mySelectionMgr, aString ); + if ( aString.isEmpty() ) aString = " "; + } + else + { + SMESH::GetNameOfSelectedElements( mySelector, IO, aString ); + myNbOkElements = aString.size(); + myFilterBtn->setEnabled(true); + } + myLineEditElements->setText( aString ); + bool ok = !aString.isEmpty(); + + buttonOk->setEnabled(ok); + buttonApply->setEnabled(ok); +} + +//======================================================================= +//function : onSelectIdSource +//purpose : +//======================================================================= +void SMESHGUI_CopyMeshDlg::onSelectIdSource (bool toSelectMesh) +{ + if (toSelectMesh) + myTextLabelElements->setText(tr("OBJECT_NAME")); + else + myTextLabelElements->setText(tr("ELEM_IDS")); + + if (toSelectMesh) { + myLineEditElements->clear(); + } + + mySelectionMgr->clearFilters(); + mySelectionMgr->installFilter(myIdSourceFilter); + SMESH::SetPointRepresentation(false); + + if (toSelectMesh) { + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) + aViewWindow->SetSelectionMode( ActorSelection ); + myLineEditElements->setReadOnly(true); + myLineEditElements->setValidator(0); + } + else + { + if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI )) + aViewWindow->SetSelectionMode( CellSelection ); + myLineEditElements->setReadOnly(false); + myLineEditElements->setValidator(myIdValidator); + onTextChange(myLineEditElements->text()); + } + + SelectionIntoArgument(); +} + +//================================================================================= +// function : isValid +// purpose : +//================================================================================= + +bool SMESHGUI_CopyMeshDlg::isValid() +{ + if ( myIdSourceCheck->isChecked() ) + return !mySelectedObject->_is_nil(); + + return myNbOkElements > 0; +} + +//================================================================================= +// function : DeactivateActiveDialog() +// purpose : +//================================================================================= +void SMESHGUI_CopyMeshDlg::DeactivateActiveDialog() +{ + if (ConstructorsBox->isEnabled()) { + ConstructorsBox->setEnabled(false); + GroupArguments->setEnabled(false); + GroupButtons->setEnabled(false); + mySMESHGUI->ResetState(); + mySMESHGUI->SetActiveDialogBox(0); + if ( mySelectionMgr ) + mySelectionMgr->removeFilter( myIdSourceFilter ); + } +} + +//================================================================================= +// function : ActivateThisDialog() +// purpose : +//================================================================================= +void SMESHGUI_CopyMeshDlg::ActivateThisDialog() +{ + /* Emit a signal to deactivate the active dialog */ + mySMESHGUI->EmitSignalDeactivateDialog(); + ConstructorsBox->setEnabled(true); + GroupArguments->setEnabled(true); + GroupButtons->setEnabled(true); + + mySMESHGUI->SetActiveDialogBox((QDialog*)this); + + onSelectIdSource( myIdSourceCheck->isChecked() ); + + SelectionIntoArgument(); +} + +//================================================================================= +// function : enterEvent() +// purpose : +//================================================================================= +void SMESHGUI_CopyMeshDlg::enterEvent (QEvent*) +{ + if (!ConstructorsBox->isEnabled()) + ActivateThisDialog(); +} + +//================================================================================= +// function : closeEvent() +// purpose : +//================================================================================= +void SMESHGUI_CopyMeshDlg::closeEvent (QCloseEvent*) +{ + /* same than click on cancel button */ + ClickOnCancel(); +} + +//======================================================================= +//function : hideEvent +//purpose : caused by ESC key +//======================================================================= +void SMESHGUI_CopyMeshDlg::hideEvent (QHideEvent*) +{ + if (!isMinimized()) + ClickOnCancel(); +} + +//================================================================================= +// function : keyPressEvent() +// purpose : +//================================================================================= +void SMESHGUI_CopyMeshDlg::keyPressEvent( QKeyEvent* e ) +{ + QDialog::keyPressEvent( e ); + if ( e->isAccepted() ) + return; + + if ( e->key() == Qt::Key_F1 ) { + e->accept(); + ClickOnHelp(); + } +} + +//================================================================================= +// function : setFilters() +// purpose : SLOT. Called when "Filter" button pressed. +//================================================================================= +void SMESHGUI_CopyMeshDlg::setFilters() +{ + if(myMesh->_is_nil()) { + SUIT_MessageBox::critical(this, + tr("SMESH_ERROR"), + tr("NO_MESH_SELECTED")); + return; + } + if ( !myFilterDlg ) + myFilterDlg = new SMESHGUI_FilterDlg( mySMESHGUI, SMESH::ALL ); + + myFilterDlg->SetSelection(); + myFilterDlg->SetMesh( myMesh ); + myFilterDlg->SetSourceWg( myLineEditElements ); + + myFilterDlg->show(); +} diff --git a/src/SMESHGUI/SMESHGUI_CopyMeshDlg.h b/src/SMESHGUI/SMESHGUI_CopyMeshDlg.h new file mode 100644 index 000000000..83fcd095b --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_CopyMeshDlg.h @@ -0,0 +1,125 @@ +// Copyright (C) 2007-2010 CEA/DEN, EDF R&D, OPEN CASCADE +// +// Copyright (C) 2003-2007 OPEN CASCADE, EADS/CCR, LIP6, CEA/DEN, +// CEDRAT, EDF R&D, LEG, PRINCIPIA R&D, BUREAU VERITAS +// +// 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. +// +// 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 +// + +// SMESH SMESHGUI : GUI for SMESH component +// File : SMESHGUI_CopyMeshDlg.h +// +#ifndef SMESHGUI_CopyMeshDLG_H +#define SMESHGUI_CopyMeshDLG_H + +// SMESH includes +#include "SMESH_SMESHGUI.hxx" + +// Qt includes +#include + +// IDL includes +#include +#include CORBA_SERVER_HEADER(SMESH_Mesh) + +class QCheckBox; +class QGroupBox; +class QLabel; +class QLineEdit; +class QPushButton; + +class SMESHGUI; +class SMESHGUI_IdValidator; +class SMESHGUI_FilterDlg; +class SMESH_Actor; +class SVTK_Selector; +class LightApp_SelectionMgr; +class SUIT_SelectionFilter; + +//================================================================================= +// class : SMESHGUI_CopyMeshDlg +// purpose : copy some elements or a mesh object into a new mesh +//================================================================================= + +class SMESHGUI_EXPORT SMESHGUI_CopyMeshDlg : public QDialog +{ + Q_OBJECT + +public: + SMESHGUI_CopyMeshDlg( SMESHGUI* ); + ~SMESHGUI_CopyMeshDlg(); + +private: + void Init( bool = true ); + void closeEvent( QCloseEvent* ); + void enterEvent( QEvent* ); /* mouse enter the QWidget */ + void hideEvent( QHideEvent* ); /* ESC key */ + void keyPressEvent( QKeyEvent* ); + int GetConstructorId(); + void setNewMeshName(); + + bool isValid(); + + SMESHGUI* mySMESHGUI; /* Current SMESHGUI object */ + SMESHGUI_IdValidator* myIdValidator; + LightApp_SelectionMgr* mySelectionMgr; /* User shape selection */ + int myNbOkElements; /* to check when elements are defined */ + + SVTK_Selector* mySelector; + + bool myBusy; + SMESH::SMESH_Mesh_var myMesh; + SMESH_Actor* myActor; + SUIT_SelectionFilter* myIdSourceFilter; + + SMESH::SMESH_IDSource_var mySelectedObject; + + QGroupBox* ConstructorsBox; + QGroupBox* GroupArguments; + QGroupBox* GroupButtons; + + QPushButton* buttonOk; + QPushButton* buttonCancel; + QPushButton* buttonApply; + QPushButton* buttonHelp; + + QLabel* myTextLabelElements; + QLineEdit* myLineEditElements; + QLineEdit* myMeshNameEdit; + QCheckBox* myIdSourceCheck; + QCheckBox* myCopyGroupsCheck; + QCheckBox* myKeepIdsCheck; + + QPushButton* myFilterBtn; + SMESHGUI_FilterDlg* myFilterDlg; + + QString myHelpFileName; + +private slots: + void ClickOnOk(); + void ClickOnCancel(); + bool ClickOnApply(); + void ClickOnHelp(); + void SelectionIntoArgument(); + void DeactivateActiveDialog(); + void ActivateThisDialog(); + void onTextChange( const QString& ); + void onSelectIdSource( bool ); + void setFilters(); +}; + +#endif // SMESHGUI_CopyMeshDLG_H diff --git a/src/SMESHGUI/SMESHGUI_FilterDlg.cxx b/src/SMESHGUI/SMESHGUI_FilterDlg.cxx index ee88f7662..de2d8e05d 100755 --- a/src/SMESHGUI/SMESHGUI_FilterDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_FilterDlg.cxx @@ -1169,18 +1169,22 @@ void SMESHGUI_FilterTable::SetCriterion (const int theRow, aTable->item( theRow, 2 )->setText( QString( theCriterion.ThresholdID ) ); } else if (theCriterion.Type != SMESH::FT_RangeOfIds && - theCriterion.Type != SMESH::FT_BelongToGeom && - theCriterion.Type != SMESH::FT_BelongToPlane && - theCriterion.Type != SMESH::FT_BelongToCylinder && - theCriterion.Type != SMESH::FT_BelongToGenSurface && - theCriterion.Type != SMESH::FT_LyingOnGeom && - theCriterion.Type != SMESH::FT_CoplanarFaces && - theCriterion.Type != SMESH::FT_FreeBorders && - theCriterion.Type != SMESH::FT_FreeEdges && - theCriterion.Type != SMESH::FT_FreeNodes && - theCriterion.Type != SMESH::FT_FreeFaces && - theCriterion.Type != SMESH::FT_BadOrientedVolume && - theCriterion.Type != SMESH::FT_LinearOrQuadratic) + theCriterion.Type != SMESH::FT_BelongToGeom && + theCriterion.Type != SMESH::FT_BelongToPlane && + theCriterion.Type != SMESH::FT_BelongToCylinder && + theCriterion.Type != SMESH::FT_BelongToGenSurface && + theCriterion.Type != SMESH::FT_LyingOnGeom && + theCriterion.Type != SMESH::FT_CoplanarFaces && + theCriterion.Type != SMESH::FT_FreeBorders && + theCriterion.Type != SMESH::FT_FreeEdges && + theCriterion.Type != SMESH::FT_FreeNodes && + theCriterion.Type != SMESH::FT_FreeFaces && + theCriterion.Type != SMESH::FT_BadOrientedVolume && + theCriterion.Type != SMESH::FT_BareBorderFace && + theCriterion.Type != SMESH::FT_BareBorderVolume && + theCriterion.Type != SMESH::FT_OverConstrainedFace && + theCriterion.Type != SMESH::FT_OverConstrainedVolume && + theCriterion.Type != SMESH::FT_LinearOrQuadratic) { aTable->item( theRow, 2 )->setText(QString("%1").arg(theCriterion.Threshold, 0, 'g', 15)); } @@ -1341,10 +1345,14 @@ void SMESHGUI_FilterTable::updateAdditionalWidget() aCriterion != SMESH::FT_RangeOfIds && aCriterion != SMESH::FT_FreeEdges && aCriterion != SMESH::FT_FreeFaces && - aCriterion != SMESH::FT_BadOrientedVolume) + aCriterion != SMESH::FT_BadOrientedVolume && + aCriterion != SMESH::FT_BareBorderFace && + aCriterion != SMESH::FT_BareBorderVolume && + aCriterion != SMESH::FT_OverConstrainedFace && + aCriterion != SMESH::FT_OverConstrainedVolume) || aCriterion == SMESH::FT_CoplanarFaces); - + if (!myAddWidgets.contains(anItem)) { myAddWidgets[ anItem ] = new AdditionalWidget(myWgStack); @@ -1520,9 +1528,13 @@ void SMESHGUI_FilterTable::onCriterionChanged (const int row, const int col, con if ((aType == SMESH::NODE && aCriterionType == SMESH::FT_FreeNodes ) || (aType == SMESH::EDGE && aCriterionType == SMESH::FT_FreeBorders ) || - (aType == SMESH::FACE && (aCriterionType == SMESH::FT_FreeEdges || + (aType == SMESH::FACE && (aCriterionType == SMESH::FT_BareBorderFace || + aCriterionType == SMESH::FT_OverConstrainedFace || + aCriterionType == SMESH::FT_FreeEdges || aCriterionType == SMESH::FT_FreeFaces)) || - (aType == SMESH::VOLUME && aCriterionType == SMESH::FT_BadOrientedVolume) || + (aType == SMESH::VOLUME && (aCriterionType == SMESH::FT_BadOrientedVolume || + aCriterionType == SMESH::FT_OverConstrainedVolume || + aCriterionType == SMESH::FT_BareBorderVolume)) || aCriterionType == SMESH::FT_LinearOrQuadratic || aCriterionType == SMESH::FT_GroupColor || aCriterionType == SMESH::FT_ElemGeomType || @@ -1808,6 +1820,8 @@ const QMap& SMESHGUI_FilterTable::getCriteria (const int theType) aCriteria[ SMESH::FT_Length2D ] = tr("LENGTH2D"); aCriteria[ SMESH::FT_MultiConnection2D ] = tr("MULTI2D_BORDERS"); aCriteria[ SMESH::FT_FreeFaces ] = tr("FREE_FACES"); + aCriteria[ SMESH::FT_BareBorderFace ] = tr("BARE_BORDER_FACE"); + aCriteria[ SMESH::FT_OverConstrainedFace] = tr("OVER_CONSTRAINED_FACE"); aCriteria[ SMESH::FT_LinearOrQuadratic ] = tr("LINEAR"); aCriteria[ SMESH::FT_GroupColor ] = tr("GROUP_COLOR"); aCriteria[ SMESH::FT_ElemGeomType ] = tr("GEOM_TYPE"); @@ -1820,16 +1834,18 @@ const QMap& SMESHGUI_FilterTable::getCriteria (const int theType) static QMap aCriteria; if (aCriteria.isEmpty()) { - aCriteria[ SMESH::FT_AspectRatio3D ] = tr("ASPECT_RATIO_3D"); - aCriteria[ SMESH::FT_RangeOfIds ] = tr("RANGE_OF_IDS"); - aCriteria[ SMESH::FT_BelongToGeom ] = tr("BELONG_TO_GEOM"); - aCriteria[ SMESH::FT_LyingOnGeom ] = tr("LYING_ON_GEOM"); - aCriteria[ SMESH::FT_BadOrientedVolume ] = tr("BAD_ORIENTED_VOLUME"); - aCriteria[ SMESH::FT_Volume3D ] = tr("VOLUME_3D"); - aCriteria[ SMESH::FT_MaxElementLength3D ] = tr("MAX_ELEMENT_LENGTH_3D"); - aCriteria[ SMESH::FT_LinearOrQuadratic ] = tr("LINEAR"); - aCriteria[ SMESH::FT_GroupColor ] = tr("GROUP_COLOR"); - aCriteria[ SMESH::FT_ElemGeomType ] = tr("GEOM_TYPE"); + aCriteria[ SMESH::FT_AspectRatio3D ] = tr("ASPECT_RATIO_3D"); + aCriteria[ SMESH::FT_RangeOfIds ] = tr("RANGE_OF_IDS"); + aCriteria[ SMESH::FT_BelongToGeom ] = tr("BELONG_TO_GEOM"); + aCriteria[ SMESH::FT_LyingOnGeom ] = tr("LYING_ON_GEOM"); + aCriteria[ SMESH::FT_BadOrientedVolume ] = tr("BAD_ORIENTED_VOLUME"); + aCriteria[ SMESH::FT_BareBorderVolume ] = tr("BARE_BORDER_VOLUME"); + aCriteria[ SMESH::FT_OverConstrainedVolume] = tr("OVER_CONSTRAINED_VOLUME"); + aCriteria[ SMESH::FT_Volume3D ] = tr("VOLUME_3D"); + aCriteria[ SMESH::FT_MaxElementLength3D ] = tr("MAX_ELEMENT_LENGTH_3D"); + aCriteria[ SMESH::FT_LinearOrQuadratic ] = tr("LINEAR"); + aCriteria[ SMESH::FT_GroupColor ] = tr("GROUP_COLOR"); + aCriteria[ SMESH::FT_ElemGeomType ] = tr("GEOM_TYPE"); } return aCriteria; } diff --git a/src/SMESHGUI/SMESHGUI_Preferences_ScalarBarDlg.cxx b/src/SMESHGUI/SMESHGUI_Preferences_ScalarBarDlg.cxx index 43640501e..b1f9284c6 100644 --- a/src/SMESHGUI/SMESHGUI_Preferences_ScalarBarDlg.cxx +++ b/src/SMESHGUI/SMESHGUI_Preferences_ScalarBarDlg.cxx @@ -418,7 +418,7 @@ SMESHGUI_Preferences_ScalarBarDlg::SMESHGUI_Preferences_ScalarBarDlg( SMESHGUI* } QColor distributionColor = mgr->colorValue("SMESH", "distribution_color", - QColor(255, 255, 255)); + QColor(255, 255, 255)); myMonoColorBtn->setColor(distributionColor); @@ -509,18 +509,6 @@ bool SMESHGUI_Preferences_ScalarBarDlg::onApply() myScalarBarActor->SetLabelTextProperty( aLabelsTextPrp ); myScalarBarActor->SetNumberOfLabels( myLabelsSpin->value() ); - if( myColorsSpin->value() != myScalarBarActor->GetMaximumNumberOfColors() ) { - myScalarBarActor->SetMaximumNumberOfColors( myColorsSpin->value() ); - SMESH::Controls::FunctorPtr fn = myActor->GetFunctor(); - SMESH::Controls::NumericalFunctor* aNumericalFunctor = dynamic_cast(fn.get()); - if( aNumericalFunctor ) { - int nbIntervals = myColorsSpin->value(); - std::vector nbEvents; - std::vector funValues; - aNumericalFunctor->GetHistogram(nbIntervals, nbEvents, funValues); - myScalarBarActor->SetDistribution(nbEvents); - } - } if ( myHorizRadioBtn->isChecked() ) myScalarBarActor->SetOrientationToHorizontal(); @@ -550,9 +538,22 @@ bool SMESHGUI_Preferences_ScalarBarDlg::onApply() double aMax = myMaxEdit->text().toDouble(); vtkLookupTable* myLookupTable = static_cast(myScalarBarActor->GetLookupTable()); + double oldMinMax[2] = { myLookupTable->GetRange()[0], myLookupTable->GetRange()[1] }; + bool rangeChanges = ( fabs( oldMinMax[0] - aMin ) + fabs( oldMinMax[1] - aMax ) > + 0.001 * ( aMax-aMin + oldMinMax[1]-oldMinMax[0] )); + + bool nbColorsChanged = (myColorsSpin->value() != myScalarBarActor->GetMaximumNumberOfColors()); + if(nbColorsChanged) + myScalarBarActor->SetMaximumNumberOfColors(myColorsSpin->value()); + + myLookupTable->SetRange( aMin, aMax ); myLookupTable->SetNumberOfTableValues(myColorsSpin->value()); myLookupTable->Build(); + + if( nbColorsChanged || rangeChanges) + myActor->UpdateDistribution(); + SMESH::RepaintCurrentView(); return true; } @@ -655,17 +656,17 @@ void SMESHGUI_Preferences_ScalarBarDlg::onSelectionChanged() myIniH = myScalarBarActor->GetHeight(); setOriginAndSize( myIniX, myIniY, myIniW, myIniH ); - myDistributionGrp->setChecked((bool)myScalarBarActor->GetDistributionVisibility()); - int coloringType = myScalarBarActor->GetDistributionColoringType(); - myScalarBarActor->GetDistributionColor( aTColor ); - myMonoColorBtn->setColor( QColor( (int)( aTColor[0]*255 ), (int)( aTColor[1]*255 ), (int)( aTColor[2]*255 ) ) ); - if ( coloringType == SMESH_MONOCOLOR_TYPE ) { - myDMonoColor->setChecked(true); - onDistributionChanged(myDistribColorGrp->id(myDMonoColor)); - } else { - myDMultiColor->setChecked(true); - onDistributionChanged(myDistribColorGrp->id(myDMultiColor)); - } + myDistributionGrp->setChecked((bool)myScalarBarActor->GetDistributionVisibility()); + int coloringType = myScalarBarActor->GetDistributionColoringType(); + myScalarBarActor->GetDistributionColor( aTColor ); + myMonoColorBtn->setColor( QColor( (int)( aTColor[0]*255 ), (int)( aTColor[1]*255 ), (int)( aTColor[2]*255 ) ) ); + if ( coloringType == SMESH_MONOCOLOR_TYPE ) { + myDMonoColor->setChecked(true); + onDistributionChanged(myDistribColorGrp->id(myDMonoColor)); + } else { + myDMultiColor->setChecked(true); + onDistributionChanged(myDistribColorGrp->id(myDMultiColor)); + } myRangeGrp->setEnabled( true ); myFontGrp->setEnabled( true ); myLabColorGrp->setEnabled( true ); diff --git a/src/SMESHGUI/SMESHGUI_Utils.cxx b/src/SMESHGUI/SMESHGUI_Utils.cxx index dfe778831..331ad9f92 100644 --- a/src/SMESHGUI/SMESHGUI_Utils.cxx +++ b/src/SMESHGUI/SMESHGUI_Utils.cxx @@ -214,7 +214,7 @@ namespace SMESH QString IOR = app->orb()->object_to_string( theObject ); SalomeApp_Study* study = dynamic_cast( app->activeStudy() ); if ( study && !IOR.isEmpty() ) - res = study->studyDS()->FindObjectIOR( IOR.toLatin1().constData() ); + res = study->studyDS()->FindObjectIOR( IOR.toLatin1().constData() ); } return res; } diff --git a/src/SMESHGUI/SMESH_images.ts b/src/SMESHGUI/SMESH_images.ts index 856e88f32..3eff547c5 100644 --- a/src/SMESHGUI/SMESH_images.ts +++ b/src/SMESHGUI/SMESH_images.ts @@ -53,6 +53,10 @@ ICON_BUILD_COMPOUND mesh_build_compound.png + + ICON_COPY_MESH + copy_mesh.png + ICON_COMPUTE mesh_compute.png @@ -109,6 +113,10 @@ ICON_DLG_BUILD_COMPOUND_MESH mesh_build_compound.png + + ICON_DLG_COPY_MESH + copy_mesh.png + ICON_DLG_ELEM0D mesh_vertex.png @@ -457,6 +465,22 @@ ICON_VOLUME_3D mesh_volume_3d.png + + ICON_BARE_BORDER_VOLUME + bare_border_volume.png + + + ICON_BARE_BORDER_FACE + bare_border_face.png + + + ICON_OVER_CONSTRAINED_VOLUME + over_constrained_volume.png + + + ICON_OVER_CONSTRAINED_FACE + over_constrained_face.png + ICON_WARP mesh_wrap.png diff --git a/src/SMESHGUI/SMESH_msg_en.ts b/src/SMESHGUI/SMESH_msg_en.ts index 81e2619ee..fdac42bca 100644 --- a/src/SMESHGUI/SMESH_msg_en.ts +++ b/src/SMESHGUI/SMESH_msg_en.ts @@ -187,6 +187,10 @@ MEN_BUILD_COMPOUND Build Compound + + MEN_COPY_MESH + Copy Mesh + MEN_CLIP Clipping @@ -395,6 +399,22 @@ STB_FIND_ELEM Find Element by Point + + MEN_BARE_BORDER_VOLUME + Volumes with bare border + + + MEN_BARE_BORDER_FACE + Faces with bare border + + + MEN_OVER_CONSTRAINED_VOLUME + Over-constrained volumes + + + MEN_OVER_CONSTRAINED_FACE + Over-constrained faces + MEN_FREE_BORDER Free Borders @@ -1040,6 +1060,14 @@ Please enter correct values and try again SMESH_BUILD_COMPOUND_TITLE Create a Compound + + SMESH_COPY_MESH_TITLE + Copy Mesh + + + SMESH_KEEP_IDS + Preserve IDs of elements + SMESH_BUT_ADD A&dd @@ -2274,6 +2302,10 @@ Please check preferences of Mesh module. STB_BUILD_COMPOUND Build Compound Mesh + + STB_COPY_MESH + Copy Mesh + STB_CLIP Clipping @@ -2434,6 +2466,22 @@ Please check preferences of Mesh module. STB_FACES Faces + + STB_BARE_BORDER_VOLUME + Volumes with bare border + + + STB_BARE_BORDER_FACE + Faces with bare border + + + STB_OVER_CONSTRAINED_VOLUME + Over-constrained volumes + + + STB_OVER_CONSTRAINED_FACE + Over-constrained faces + STB_FREE_BORDER Free Borders @@ -2810,6 +2858,10 @@ Please check preferences of Mesh module. TOP_BUILD_COMPOUND Build Compound Mesh + + TOP_COPY_MESH + Copy Mesh + TOP_CLIP Clipping @@ -2970,6 +3022,22 @@ Please check preferences of Mesh module. TOP_FACES Faces + + TOP_BARE_BORDER_VOLUME + Volumes with bare border + + + TOP_BARE_BORDER_FACE + Faces with bare border + + + TOP_OVER_CONSTRAINED_VOLUME + Over-constrained volumes + + + TOP_OVER_CONSTRAINED_FACE + Over-constrained faces + TOP_FREE_BORDER Free Borders @@ -4320,6 +4388,22 @@ Please check input data and try again BAD_ORIENTED_VOLUME Bad oriented volume + + BARE_BORDER_VOLUME + Volumes with bare border + + + BARE_BORDER_FACE + Faces with bare border + + + OVER_CONSTRAINED_VOLUME + Over-constrained volumes + + + OVER_CONSTRAINED_FACE + Over-constrained faces + BELONG_TO_CYLINDER Belong to Cylinder @@ -5847,6 +5931,21 @@ It is impossible to read point coordinates from file Distance + + SMESHGUI_CopyMeshDlg + + OBJECT_NAME + Source Object + + + ELEM_IDS + Source Element IDs + + + NEW_NAME + New Mesh Name + + SMESHGUI_MeasureDlg diff --git a/src/SMESH_I/SMESH_2smeshpy.cxx b/src/SMESH_I/SMESH_2smeshpy.cxx index fd62cbd2f..c6bc91e8d 100644 --- a/src/SMESH_I/SMESH_2smeshpy.cxx +++ b/src/SMESH_I/SMESH_2smeshpy.cxx @@ -363,7 +363,7 @@ void _pyGen::Process( const Handle(_pyCommand)& theCommand ) myMeshes.insert( make_pair( mesh->GetID(), mesh )); return; } - if ( method == "CreateMeshesFromUNV" || method == "CreateMeshesFromSTL") + if ( method == "CreateMeshesFromUNV" || method == "CreateMeshesFromSTL" || method == "CopyMesh" ) { Handle(_pyMesh) mesh = new _pyMesh( theCommand, theCommand->GetResultValue() ); myMeshes.insert( make_pair( mesh->GetID(), mesh )); diff --git a/src/SMESH_I/SMESH_DumpPython.cxx b/src/SMESH_I/SMESH_DumpPython.cxx index 3fd8ff22f..a8e4205b2 100644 --- a/src/SMESH_I/SMESH_DumpPython.cxx +++ b/src/SMESH_I/SMESH_DumpPython.cxx @@ -232,7 +232,10 @@ namespace SMESH if(!aSObject->_is_nil() || CORBA::is_nil( theArg )) return *this << aSObject; SMESH::long_array_var anElementsId = theArg->GetIDs(); - return *this << anElementsId; + SMESH::SMESH_Mesh_var mesh = theArg->GetMesh(); + SMESH::array_of_ElementType_var types = theArg->GetTypes(); + SMESH::ElementType type = types->length() ? types[0] : SMESH::ALL; + return *this << mesh << ".GetIDSource(" << anElementsId << ", " << type << ")"; } TPythonDump& @@ -266,43 +269,47 @@ namespace SMESH if ( theArg ) { FunctorType aFunctorType = theArg->GetFunctorType(); switch(aFunctorType){ - case FT_AspectRatio: myStream<< "anAspectRatio"; break; - case FT_AspectRatio3D: myStream<< "anAspectRatio3D"; break; - case FT_Warping: myStream<< "aWarping"; break; - case FT_MinimumAngle: myStream<< "aMinimumAngle"; break; - case FT_Taper: myStream<< "aTaper"; break; - case FT_Skew: myStream<< "aSkew"; break; - case FT_Area: myStream<< "aArea"; break; - case FT_Volume3D: myStream<< "aVolume3D"; break; - case FT_MaxElementLength2D:myStream<< "aMaxElementLength2D";break; - case FT_MaxElementLength3D:myStream<< "aMaxElementLength3D";break; - case FT_FreeBorders: myStream<< "aFreeBorders"; break; - case FT_FreeEdges: myStream<< "aFreeEdges"; break; - case FT_FreeNodes: myStream<< "aFreeNodes"; break; - case FT_FreeFaces: myStream<< "aFreeFaces"; break; - case FT_MultiConnection: myStream<< "aMultiConnection"; break; - case FT_MultiConnection2D:myStream<< "aMultiConnection2D";break; - case FT_Length: myStream<< "aLength"; break; - case FT_Length2D: myStream<< "aLength"; break; - case FT_BelongToGeom: myStream<< "aBelongToGeom"; break; - case FT_BelongToPlane: myStream<< "aBelongToPlane"; break; - case FT_BelongToCylinder: myStream<< "aBelongToCylinder"; break; - case FT_BelongToGenSurface:myStream<<"aBelongToGenSurface";break; - case FT_LyingOnGeom: myStream<< "aLyingOnGeom"; break; - case FT_CoplanarFaces: myStream<< "aCoplanarFaces"; break; - case FT_RangeOfIds: myStream<< "aRangeOfIds"; break; - case FT_BadOrientedVolume:myStream<< "aBadOrientedVolume";break; - case FT_LinearOrQuadratic:myStream<< "aLinearOrQuadratic";break; - case FT_GroupColor: myStream<< "aGroupColor"; break; - case FT_ElemGeomType: myStream<< "anElemGeomType"; break; - case FT_LessThan: myStream<< "aLessThan"; break; - case FT_MoreThan: myStream<< "aMoreThan"; break; - case FT_EqualTo: myStream<< "anEqualTo"; break; - case FT_LogicalNOT: myStream<< "aLogicalNOT"; break; - case FT_LogicalAND: myStream<< "aLogicalAND"; break; - case FT_LogicalOR: myStream<< "aLogicalOR"; break; + case FT_AspectRatio: myStream<< "anAspectRatio"; break; + case FT_AspectRatio3D: myStream<< "anAspectRatio3D"; break; + case FT_Warping: myStream<< "aWarping"; break; + case FT_MinimumAngle: myStream<< "aMinimumAngle"; break; + case FT_Taper: myStream<< "aTaper"; break; + case FT_Skew: myStream<< "aSkew"; break; + case FT_Area: myStream<< "aArea"; break; + case FT_Volume3D: myStream<< "aVolume3D"; break; + case FT_MaxElementLength2D: myStream<< "aMaxElementLength2D"; break; + case FT_MaxElementLength3D: myStream<< "aMaxElementLength3D"; break; + case FT_FreeBorders: myStream<< "aFreeBorders"; break; + case FT_FreeEdges: myStream<< "aFreeEdges"; break; + case FT_FreeNodes: myStream<< "aFreeNodes"; break; + case FT_FreeFaces: myStream<< "aFreeFaces"; break; + case FT_MultiConnection: myStream<< "aMultiConnection"; break; + case FT_MultiConnection2D: myStream<< "aMultiConnection2D"; break; + case FT_Length: myStream<< "aLength"; break; + case FT_Length2D: myStream<< "aLength2D"; break; + case FT_BelongToGeom: myStream<< "aBelongToGeom"; break; + case FT_BelongToPlane: myStream<< "aBelongToPlane"; break; + case FT_BelongToCylinder: myStream<< "aBelongToCylinder"; break; + case FT_BelongToGenSurface: myStream<< "aBelongToGenSurface"; break; + case FT_LyingOnGeom: myStream<< "aLyingOnGeom"; break; + case FT_CoplanarFaces: myStream<< "aCoplanarFaces"; break; + case FT_RangeOfIds: myStream<< "aRangeOfIds"; break; + case FT_BadOrientedVolume: myStream<< "aBadOrientedVolume"; break; + case FT_BareBorderVolume: myStream<< "aBareBorderVolume"; break; + case FT_BareBorderFace: myStream<< "aBareBorderFace"; break; + case FT_OverConstrainedVolume: myStream<< "aOverConstrainedVolume"; break; + case FT_OverConstrainedFace: myStream<< "aOverConstrainedFace"; break; + case FT_LinearOrQuadratic: myStream<< "aLinearOrQuadratic"; break; + case FT_GroupColor: myStream<< "aGroupColor"; break; + case FT_ElemGeomType: myStream<< "anElemGeomType"; break; + case FT_LessThan: myStream<< "aLessThan"; break; + case FT_MoreThan: myStream<< "aMoreThan"; break; + case FT_EqualTo: myStream<< "anEqualTo"; break; + case FT_LogicalNOT: myStream<< "aLogicalNOT"; break; + case FT_LogicalAND: myStream<< "aLogicalAND"; break; + case FT_LogicalOR: myStream<< "aLogicalOR"; break; case FT_Undefined: - default: myStream<< "anUndefined"; break; + default: myStream<< "anUndefined"; break; } myStream< nbEvents; std::vector funValues; - myNumericalFunctorPtr->GetHistogram(nbIntervals,nbEvents,funValues); + std::vector elements; + myNumericalFunctorPtr->GetHistogram(nbIntervals,nbEvents,funValues,elements); nbIntervals = CORBA::Short( std::min( nbEvents.size(), funValues.size() - 1)); SMESH::Histogram_var histogram = new SMESH::Histogram; @@ -937,6 +939,66 @@ FunctorType BadOrientedVolume_i::GetFunctorType() return SMESH::FT_BadOrientedVolume; } +/* + Class : BareBorderVolume_i + Description : Verify whether a mesh volume has a free facet without a face on it +*/ +BareBorderVolume_i::BareBorderVolume_i() +{ + Controls::PredicatePtr control( new Controls::BareBorderVolume() ); + myFunctorPtr = myPredicatePtr = control; +}; + +FunctorType BareBorderVolume_i::GetFunctorType() +{ + return SMESH::FT_BareBorderVolume; +} + +/* + Class : BareBorderFace_i + Description : Verify whether a mesh face has a free border without an edge on it +*/ +BareBorderFace_i::BareBorderFace_i() +{ + Controls::PredicatePtr control( new Controls::BareBorderFace() ); + myFunctorPtr = myPredicatePtr = control; +}; + +FunctorType BareBorderFace_i::GetFunctorType() +{ + return SMESH::FT_BareBorderFace; +} + +/* + Class : OverConstrainedVolume_i + Description : Verify whether a mesh volume has only one facet shared with other volumes +*/ +OverConstrainedVolume_i::OverConstrainedVolume_i() +{ + Controls::PredicatePtr control( new Controls::OverConstrainedVolume() ); + myFunctorPtr = myPredicatePtr = control; +}; + +FunctorType OverConstrainedVolume_i::GetFunctorType() +{ + return SMESH::FT_OverConstrainedVolume; +} + +/* + Class : OverConstrainedFace_i + Description : Verify whether a mesh face has only one border shared with other faces +*/ +OverConstrainedFace_i::OverConstrainedFace_i() +{ + Controls::PredicatePtr control( new Controls::OverConstrainedFace() ); + myFunctorPtr = myPredicatePtr = control; +}; + +FunctorType OverConstrainedFace_i::GetFunctorType() +{ + return SMESH::FT_OverConstrainedFace; +} + /* Class : BelongToGeom_i Description : Predicate for selection on geometrical support @@ -2036,6 +2098,38 @@ BadOrientedVolume_ptr FilterManager_i::CreateBadOrientedVolume() return anObj._retn(); } +BareBorderVolume_ptr FilterManager_i::CreateBareBorderVolume() +{ + SMESH::BareBorderVolume_i* aServant = new SMESH::BareBorderVolume_i(); + SMESH::BareBorderVolume_var anObj = aServant->_this(); + TPythonDump()<_this(); + TPythonDump()<_this(); + TPythonDump()<_this(); + TPythonDump()<GetElementType(); + return true; + } + case FT_BareBorderVolume: + { + BareBorderVolume_i* aPred = dynamic_cast( thePred ); + + CORBA::ULong i = theCriteria->length(); + theCriteria->length( i + 1 ); + + theCriteria[ i ] = createCriterion(); + + theCriteria[ i ].Type = FT_BareBorderVolume; + theCriteria[ i ].TypeOfElement = aPred->GetElementType(); + + return true; + } + case FT_BareBorderFace: + { + BareBorderFace_i* aPred = dynamic_cast( thePred ); + + CORBA::ULong i = theCriteria->length(); + theCriteria->length( i + 1 ); + + theCriteria[ i ] = createCriterion(); + + theCriteria[ i ].Type = FT_BareBorderFace; + theCriteria[ i ].TypeOfElement = aPred->GetElementType(); + + return true; + } + case FT_OverConstrainedVolume: + { + OverConstrainedVolume_i* aPred = dynamic_cast( thePred ); + + CORBA::ULong i = theCriteria->length(); + theCriteria->length( i + 1 ); + + theCriteria[ i ] = createCriterion(); + + theCriteria[ i ].Type = FT_OverConstrainedVolume; + theCriteria[ i ].TypeOfElement = aPred->GetElementType(); + + return true; + } + case FT_OverConstrainedFace: + { + OverConstrainedFace_i* aPred = dynamic_cast( thePred ); + + CORBA::ULong i = theCriteria->length(); + theCriteria->length( i + 1 ); + + theCriteria[ i ] = createCriterion(); + + theCriteria[ i ].Type = FT_OverConstrainedFace; + theCriteria[ i ].TypeOfElement = aPred->GetElementType(); + return true; } case FT_LessThan: @@ -2723,6 +2873,26 @@ CORBA::Boolean Filter_i::SetCriteria( const SMESH::Filter::Criteria& theCriteria aPredicate = aFilterMgr->CreateBadOrientedVolume(); } break; + case SMESH::FT_BareBorderVolume: + { + aPredicate = aFilterMgr->CreateBareBorderVolume(); + } + break; + case SMESH::FT_BareBorderFace: + { + aPredicate = aFilterMgr->CreateBareBorderFace(); + } + break; + case SMESH::FT_OverConstrainedVolume: + { + aPredicate = aFilterMgr->CreateOverConstrainedVolume(); + } + break; + case SMESH::FT_OverConstrainedFace: + { + aPredicate = aFilterMgr->CreateOverConstrainedFace(); + } + break; case SMESH::FT_LinearOrQuadratic: { SMESH::LinearOrQuadratic_ptr tmpPred = aFilterMgr->CreateLinearOrQuadratic(); @@ -2963,7 +3133,11 @@ static inline LDOMString toString( CORBA::Long theType ) case FT_BelongToCylinder: return "Belong to Cylinder"; case FT_BelongToGenSurface: return "Belong to Generic Surface"; case FT_LyingOnGeom : return "Lying on Geom"; - case FT_BadOrientedVolume: return "Bad Oriented Volume"; + case FT_BadOrientedVolume:return "Bad Oriented Volume"; + case FT_BareBorderVolume: return "Volumes with bare border"; + case FT_BareBorderFace : return "Faces with bare border"; + case FT_OverConstrainedVolume: return "Over-constrained Volumes"; + case FT_OverConstrainedFace : return "Over-constrained Faces"; case FT_RangeOfIds : return "Range of IDs"; case FT_FreeBorders : return "Free borders"; case FT_FreeEdges : return "Free edges"; @@ -3017,6 +3191,10 @@ static inline SMESH::FunctorType toFunctorType( const LDOMString& theStr ) // else if ( theStr.equals( "Length2D" ) ) return FT_Length2D; else if ( theStr.equals( "Range of IDs" ) ) return FT_RangeOfIds; else if ( theStr.equals( "Bad Oriented Volume" ) ) return FT_BadOrientedVolume; + else if ( theStr.equals( "Volumes with bare border" ) ) return FT_BareBorderVolume; + else if ( theStr.equals( "Faces with bare border" ) ) return FT_BareBorderFace; + else if ( theStr.equals( "Over-constrained Volumes" ) ) return FT_OverConstrainedVolume; + else if ( theStr.equals( "Over-constrained Faces" ) ) return FT_OverConstrainedFace; else if ( theStr.equals( "Less than" ) ) return FT_LessThan; else if ( theStr.equals( "More than" ) ) return FT_MoreThan; else if ( theStr.equals( "Equal to" ) ) return FT_EqualTo; diff --git a/src/SMESH_I/SMESH_Filter_i.hxx b/src/SMESH_I/SMESH_Filter_i.hxx index bef8c2252..9ca20ddb4 100644 --- a/src/SMESH_I/SMESH_Filter_i.hxx +++ b/src/SMESH_I/SMESH_Filter_i.hxx @@ -44,6 +44,7 @@ class SMESHDS_Mesh; namespace SMESH { + // ================================================================================ namespace Controls { @@ -123,8 +124,10 @@ namespace SMESH Controls::ElementsOnShapePtr myElementsOnShapePtr; // only if myIsSubshape == false }; typedef boost::shared_ptr LyingOnGeomPtr; - } - + + } // namespace Controls + + // ================================================================================ /* FUNCTORS */ @@ -387,6 +390,54 @@ namespace SMESH FunctorType GetFunctorType(); }; + /* + Class : BareBorderVolume_i + Description : Verify whether a mesh volume has a free facet without a face on it + */ + class SMESH_I_EXPORT BareBorderVolume_i: public virtual POA_SMESH::BareBorderVolume, + public virtual Predicate_i + { + public: + BareBorderVolume_i(); + FunctorType GetFunctorType(); + }; + + /* + Class : BareBorderFace_i + Description : Verify whether a mesh face has a free border without an edge on it + */ + class SMESH_I_EXPORT BareBorderFace_i: public virtual POA_SMESH::BareBorderFace, + public virtual Predicate_i + { + public: + BareBorderFace_i(); + FunctorType GetFunctorType(); + }; + + /* + Class : OverConstrainedVolume_i + Description : Verify whether a mesh volume has only one facet shared with other volumes + */ + class SMESH_I_EXPORT OverConstrainedVolume_i: public virtual POA_SMESH::OverConstrainedVolume, + public virtual Predicate_i + { + public: + OverConstrainedVolume_i(); + FunctorType GetFunctorType(); + }; + + /* + Class : OverConstrainedFace_i + Description : Verify whether a mesh face has only one border shared with other faces + */ + class SMESH_I_EXPORT OverConstrainedFace_i: public virtual POA_SMESH::OverConstrainedFace, + public virtual Predicate_i + { + public: + OverConstrainedFace_i(); + FunctorType GetFunctorType(); + }; + /* Class : BelongToGeom_i Description : Predicate for selection on geometrical support @@ -954,6 +1005,10 @@ namespace SMESH RangeOfIds_ptr CreateRangeOfIds(); BadOrientedVolume_ptr CreateBadOrientedVolume(); + BareBorderFace_ptr CreateBareBorderFace(); + BareBorderVolume_ptr CreateBareBorderVolume(); + OverConstrainedFace_ptr CreateOverConstrainedFace(); + OverConstrainedVolume_ptr CreateOverConstrainedVolume(); LinearOrQuadratic_ptr CreateLinearOrQuadratic(); GroupColor_ptr CreateGroupColor(); ElemGeomType_ptr CreateElemGeomType(); diff --git a/src/SMESH_I/SMESH_Gen_i.cxx b/src/SMESH_I/SMESH_Gen_i.cxx index a0ce885aa..76e96275f 100644 --- a/src/SMESH_I/SMESH_Gen_i.cxx +++ b/src/SMESH_I/SMESH_Gen_i.cxx @@ -91,9 +91,10 @@ #include "SMDS_EdgePosition.hxx" #include "SMDS_FacePosition.hxx" -#include "SMDS_VertexPosition.hxx" -#include "SMDS_SpacePosition.hxx" #include "SMDS_PolyhedralVolumeOfNodes.hxx" +#include "SMDS_SetIterator.hxx" +#include "SMDS_SpacePosition.hxx" +#include "SMDS_VertexPosition.hxx" #include CORBA_SERVER_HEADER(SMESH_Group) #include CORBA_SERVER_HEADER(SMESH_Filter) @@ -898,7 +899,7 @@ SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CreateMeshesFromUNV( const char* theFileName aServant->ImportUNVFile( theFileName ); // Dump creation of groups - aServant->GetGroups(); + SMESH::ListOfGroups_var groups = aServant->GetGroups(); return aMesh._retn(); } @@ -977,7 +978,7 @@ SMESH::mesh_array* SMESH_Gen_i::CreateMeshesFromMED( const char* theFileName, } // Dump creation of groups for ( int i = 0; i < aResult->length(); ++i ) - aResult[ i ]->GetGroups(); + SMESH::ListOfGroups_var groups = aResult[ i ]->GetGroups(); return aResult._retn(); } @@ -2201,6 +2202,212 @@ SMESH_Gen_i::ConcatenateCommon(const SMESH::mesh_array& theMeshesArray, return aNewMesh._retn(); } +//================================================================================ +/*! + * \brief Create a mesh by copying a part of another mesh + * \param meshPart - a part of mesh to copy + * \param toCopyGroups - to create in the new mesh groups + * the copied elements belongs to + * \param toKeepIDs - to preserve IDs of the copied elements or not + * \retval SMESH::SMESH_Mesh_ptr - the new mesh + */ +//================================================================================ + +SMESH::SMESH_Mesh_ptr SMESH_Gen_i::CopyMesh(SMESH::SMESH_IDSource_ptr meshPart, + const char* meshName, + CORBA::Boolean toCopyGroups, + CORBA::Boolean toKeepIDs) +{ + Unexpect aCatch(SALOME_SalomeException); + + TPythonDump* pyDump = new TPythonDump; // prevent dump from CreateMesh() + + // 1. Get source mesh + + if ( CORBA::is_nil( meshPart )) + THROW_SALOME_CORBA_EXCEPTION( "bad IDSource", SALOME::BAD_PARAM ); + + SMESH::SMESH_Mesh_var srcMesh = meshPart->GetMesh(); + SMESH_Mesh_i* srcMesh_i = SMESH::DownCast( srcMesh ); + if ( !srcMesh_i ) + THROW_SALOME_CORBA_EXCEPTION( "bad mesh of IDSource", SALOME::BAD_PARAM ); + + SMESHDS_Mesh* srcMeshDS = srcMesh_i->GetImpl().GetMeshDS(); + + // 2. Make a new mesh + + SMESH::SMESH_Mesh_var newMesh = CreateMesh(GEOM::GEOM_Object::_nil()); + SMESH_Mesh_i* newMesh_i = SMESH::DownCast( newMesh ); + if ( !newMesh_i ) + THROW_SALOME_CORBA_EXCEPTION( "can't create a mesh", SALOME::INTERNAL_ERROR ); + SALOMEDS::SObject_var meshSO = ObjectToSObject(myCurrentStudy, newMesh ); + if ( !meshSO->_is_nil() ) + { + SetName( meshSO, meshName, "Mesh" ); + SetPixMap( meshSO, "ICON_SMESH_TREE_MESH_IMPORTED"); + } + SMESHDS_Mesh* newMeshDS = newMesh_i->GetImpl().GetMeshDS(); + ::SMESH_MeshEditor editor( &newMesh_i->GetImpl() ); + + // 3. Get elements to copy + + SMDS_ElemIteratorPtr srcElemIt; + TIDSortedElemSet srcElems; + SMESH::array_of_ElementType_var srcElemTypes = meshPart->GetTypes(); + if ( SMESH::DownCast( meshPart )) + { + srcElemIt = srcMeshDS->elementsIterator(); + } + else + { + SMESH::long_array_var ids = meshPart->GetIDs(); + if ( srcElemTypes->length() == 1 && srcElemTypes[0] == SMESH::NODE ) // group of nodes + { + for (int i=0; i < ids->length(); i++) + if ( const SMDS_MeshElement * elem = srcMeshDS->FindNode( ids[i] )) + srcElems.insert( elem ); + } + else + { + for (int i=0; i < ids->length(); i++) + if ( const SMDS_MeshElement * elem = srcMeshDS->FindElement( ids[i] )) + srcElems.insert( elem ); + } + if ( srcElems.empty() ) + return newMesh._retn(); + + typedef SMDS_SetIterator< SMDS_pElement, TIDSortedElemSet::const_iterator > ElIter; + srcElemIt = SMDS_ElemIteratorPtr( new ElIter( srcElems.begin(), srcElems.end() )); + } + + // 4. Copy elements + + typedef map TE2EMap; + TE2EMap e2eMapByType[ SMDSAbs_NbElementTypes ]; + TE2EMap& n2nMap = e2eMapByType[ SMDSAbs_Node ]; + int iN; + const SMDS_MeshNode *nSrc, *nTgt; + vector< const SMDS_MeshNode* > nodes; + while ( srcElemIt->more() ) + { + const SMDS_MeshElement * elem = srcElemIt->next(); + nodes.resize( elem->NbNodes()); + SMDS_ElemIteratorPtr nIt = elem->nodesIterator(); + if ( toKeepIDs ) { + for ( iN = 0; nIt->more(); ++iN ) + { + nSrc = static_cast( nIt->next() ); + nTgt = newMeshDS->FindNode( nSrc->GetID()); + if ( !nTgt ) + nTgt = newMeshDS->AddNodeWithID( nSrc->X(), nSrc->Y(), nSrc->Z(), nSrc->GetID()); + nodes[ iN ] = nTgt; + } + } + else { + for ( iN = 0; nIt->more(); ++iN ) + { + nSrc = static_cast( nIt->next() ); + TE2EMap::iterator n2n = n2nMap.insert( make_pair( nSrc, SMDS_pNode(0) )).first; + if ( !n2n->second ) + n2n->second = newMeshDS->AddNode( nSrc->X(), nSrc->Y(), nSrc->Z() ); + nodes[ iN ] = (const SMDS_MeshNode*) n2n->second; + } + } + if ( elem->GetType() != SMDSAbs_Node ) + { + int ID = toKeepIDs ? elem->GetID() : 0; + const SMDS_MeshElement * newElem = editor.AddElement( nodes, + elem->GetType(), + elem->IsPoly(), + ID); + if ( toCopyGroups && !toKeepIDs ) + e2eMapByType[ elem->GetType() ].insert( make_pair( elem, newElem )); + } + } + + // 5. Copy groups + + int nbNewGroups = 0; + if ( toCopyGroups ) + { + SMESH_Mesh::GroupIteratorPtr gIt = srcMesh_i->GetImpl().GetGroups(); + while ( gIt->more() ) + { + SMESH_Group* group = gIt->next(); + const SMESHDS_GroupBase* groupDS = group->GetGroupDS(); + + // Check group type. We copy nodal groups containing nodes of copied element + SMDSAbs_ElementType groupType = groupDS->GetType(); + if ( groupType != SMDSAbs_Node && + newMeshDS->GetMeshInfo().NbElements( groupType ) == 0 ) + continue; // group type differs from types of meshPart + + // Find copied elements in the group + vector< const SMDS_MeshElement* > groupElems; + SMDS_ElemIteratorPtr eIt = groupDS->GetElements(); + if ( toKeepIDs ) + { + const SMDS_MeshElement* foundElem; + if ( groupType == SMDSAbs_Node ) + { + while ( eIt->more() ) + if (( foundElem = newMeshDS->FindNode( eIt->next()->GetID() ))) + groupElems.push_back( foundElem ); + } + else + { + while ( eIt->more() ) + if (( foundElem = newMeshDS->FindElement( eIt->next()->GetID() ))) + groupElems.push_back( foundElem ); + } + } + else + { + TE2EMap & e2eMap = e2eMapByType[ groupDS->GetType() ]; + if ( e2eMap.empty() ) continue; + int minID = e2eMap.begin()->first->GetID(); + int maxID = e2eMap.rbegin()->first->GetID(); + TE2EMap::iterator e2e; + while ( eIt->more() && groupElems.size() < e2eMap.size()) + { + const SMDS_MeshElement* e = eIt->next(); + if ( e->GetID() < minID || e->GetID() > maxID ) continue; + if ((e2e = e2eMap.find( e )) != e2eMap.end()) + groupElems.push_back( e2e->second ); + } + } + // Make a new group + if ( !groupElems.empty() ) + { + SMESH::SMESH_Group_var newGroupObj = + newMesh->CreateGroup( SMESH::ElementType(groupType), group->GetName() ); + if ( SMESH_GroupBase_i* newGroup_i = SMESH::DownCast( newGroupObj)) + { + SMESHDS_GroupBase * newGroupDS = newGroup_i->GetGroupDS(); + SMDS_MeshGroup& smdsGroup = ((SMESHDS_Group*)newGroupDS)->SMDSGroup(); + for ( unsigned i = 0; i < groupElems.size(); ++i ) + smdsGroup.Add( groupElems[i] ); + + nbNewGroups++; + } + } + } + } + + *pyDump << newMesh << " = " << this + << ".CopyMesh( " << meshPart << ", " + << "'" << meshName << "', " + << toCopyGroups << ", " + << toKeepIDs << ")"; + + delete pyDump; pyDump = 0; // allow dump in GetGroups() + + if ( nbNewGroups > 0 ) // dump created groups + SMESH::ListOfGroups_var groups = newMesh->GetGroups(); + + return newMesh._retn(); +} + //================================================================================ /*! * SMESH_Gen_i::GetMEDVersion diff --git a/src/SMESH_I/SMESH_Gen_i.hxx b/src/SMESH_I/SMESH_Gen_i.hxx index b2c90805c..b4003818d 100644 --- a/src/SMESH_I/SMESH_Gen_i.hxx +++ b/src/SMESH_I/SMESH_Gen_i.hxx @@ -236,6 +236,12 @@ public: SMESH::SMESH_Mesh_ptr CreateMeshesFromSTL( const char* theFileName ) throw ( SALOME::SALOME_Exception ); + // Copy a part of mesh + SMESH::SMESH_Mesh_ptr CopyMesh(SMESH::SMESH_IDSource_ptr meshPart, + const char* meshName, + CORBA::Boolean toCopyGroups, + CORBA::Boolean toKeepIDs); + // Compute mesh on a shape CORBA::Boolean Compute( SMESH::SMESH_Mesh_ptr theMesh, GEOM::GEOM_Object_ptr theShapeObject ) diff --git a/src/SMESH_SWIG/smeshDC.py b/src/SMESH_SWIG/smeshDC.py index a2476107a..64aace0e5 100644 --- a/src/SMESH_SWIG/smeshDC.py +++ b/src/SMESH_SWIG/smeshDC.py @@ -663,27 +663,6 @@ class smeshDC(SMESH._objref_SMESH_Gen): aMesh = Mesh(self, self.geompyD, aSmeshMesh) return aMesh - ## From SMESH_Gen interface - # @return the list of integer values - # @ingroup l1_auxiliary - def GetSubShapesId( self, theMainObject, theListOfSubObjects ): - return SMESH._objref_SMESH_Gen.GetSubShapesId(self,theMainObject, theListOfSubObjects) - - ## From SMESH_Gen interface. Creates a pattern - # @return an instance of SMESH_Pattern - # - # Example of Patterns usage - # @ingroup l2_modif_patterns - def GetPattern(self): - return SMESH._objref_SMESH_Gen.GetPattern(self) - - ## Sets number of segments per diagonal of boundary box of geometry by which - # default segment length of appropriate 1D hypotheses is defined. - # Default value is 10 - # @ingroup l1_auxiliary - def SetBoundaryBoxSegmentation(self, nbSegments): - SMESH._objref_SMESH_Gen.SetBoundaryBoxSegmentation(self,nbSegments) - ## Concatenate the given meshes into one mesh. # @return an instance of Mesh class # @param meshes the meshes to combine into one mesh @@ -707,6 +686,41 @@ class smeshDC(SMESH._objref_SMESH_Gen): aMesh = Mesh(self, self.geompyD, aSmeshMesh) return aMesh + ## Create a mesh by copying a part of another mesh. + # @param meshPart a part of mesh to copy, either a Mesh, a sub-mesh or a group; + # to copy nodes or elements not contained in any mesh object, + # pass result of Mesh.GetIDSource( list_of_ids, type ) as meshPart + # @param meshName a name of the new mesh + # @param toCopyGroups to create in the new mesh groups the copied elements belongs to + # @param toKeepIDs to preserve IDs of the copied elements or not + # @return an instance of Mesh class + def CopyMesh( self, meshPart, meshName, toCopyGroups=False, toKeepIDs=False): + if (isinstance( meshPart, Mesh )): + meshPart = meshPart.GetMesh() + mesh = SMESH._objref_SMESH_Gen.CopyMesh( self,meshPart,meshName,toCopyGroups,toKeepIDs ) + return Mesh(self, self.geompyD, mesh) + + ## From SMESH_Gen interface + # @return the list of integer values + # @ingroup l1_auxiliary + def GetSubShapesId( self, theMainObject, theListOfSubObjects ): + return SMESH._objref_SMESH_Gen.GetSubShapesId(self,theMainObject, theListOfSubObjects) + + ## From SMESH_Gen interface. Creates a pattern + # @return an instance of SMESH_Pattern + # + # Example of Patterns usage + # @ingroup l2_modif_patterns + def GetPattern(self): + return SMESH._objref_SMESH_Gen.GetPattern(self) + + ## Sets number of segments per diagonal of boundary box of geometry by which + # default segment length of appropriate 1D hypotheses is defined. + # Default value is 10 + # @ingroup l1_auxiliary + def SetBoundaryBoxSegmentation(self, nbSegments): + SMESH._objref_SMESH_Gen.SetBoundaryBoxSegmentation(self,nbSegments) + # Filtering. Auxiliary functions: # ------------------------------ @@ -735,6 +749,8 @@ class smeshDC(SMESH._objref_SMESH_Gen): # @param UnaryOp FT_LogicalNOT or FT_Undefined # @param BinaryOp a binary logical operation FT_LogicalAND, FT_LogicalOR or # FT_Undefined (must be for the last criterion of all criteria) + # @param Tolerance the tolerance used by FT_BelongToGeom, FT_BelongToSurface, + # FT_LyingOnGeom, FT_CoplanarFaces criteria # @return SMESH.Filter.Criterion # @ingroup l1_controls def GetCriterion(self,elementType, @@ -742,10 +758,12 @@ class smeshDC(SMESH._objref_SMESH_Gen): Compare = FT_EqualTo, Treshold="", UnaryOp=FT_Undefined, - BinaryOp=FT_Undefined): + BinaryOp=FT_Undefined, + Tolerance=1e-07): aCriterion = self.GetEmptyCriterion() aCriterion.TypeOfElement = elementType aCriterion.Type = self.EnumToLong(CritType) + aCriterion.Tolerance = Tolerance aTreshold = Treshold @@ -810,7 +828,9 @@ class smeshDC(SMESH._objref_SMESH_Gen): return None pass elif CritType in [FT_FreeBorders, FT_FreeEdges, FT_BadOrientedVolume, FT_FreeNodes, - FT_FreeFaces, FT_LinearOrQuadratic]: + FT_FreeFaces, FT_LinearOrQuadratic, + FT_BareBorderFace, FT_BareBorderVolume, + FT_OverConstrainedFace, FT_OverConstrainedVolume]: # At this point the treshold is unnecessary if aTreshold == FT_LogicalNOT: aCriterion.UnaryOp = self.EnumToLong(FT_LogicalNOT) @@ -845,14 +865,17 @@ class smeshDC(SMESH._objref_SMESH_Gen): # @param Compare belongs to {FT_LessThan, FT_MoreThan, FT_EqualTo} # @param Treshold the threshold value (range of id ids as string, shape, numeric) # @param UnaryOp FT_LogicalNOT or FT_Undefined + # @param Tolerance the tolerance used by FT_BelongToGeom, FT_BelongToSurface, + # FT_LyingOnGeom, FT_CoplanarFaces criteria # @return SMESH_Filter # @ingroup l1_controls def GetFilter(self,elementType, CritType=FT_Undefined, Compare=FT_EqualTo, Treshold="", - UnaryOp=FT_Undefined): - aCriterion = self.GetCriterion(elementType, CritType, Compare, Treshold, UnaryOp, FT_Undefined) + UnaryOp=FT_Undefined, + Tolerance=1e-07): + aCriterion = self.GetCriterion(elementType, CritType, Compare, Treshold, UnaryOp, FT_Undefined,Tolerance) aFilterMgr = self.CreateFilterManager() aFilter = aFilterMgr.CreateFilter() aCriteria = [] @@ -1744,6 +1767,8 @@ class Mesh: # @param Compare belongs to {FT_LessThan, FT_MoreThan, FT_EqualTo} # @param Treshold the threshold value (range of id ids as string, shape, numeric) # @param UnaryOp FT_LogicalNOT or FT_Undefined + # @param Tolerance the tolerance used by FT_BelongToGeom, FT_BelongToSurface, + # FT_LyingOnGeom, FT_CoplanarFaces criteria # @return SMESH_Group # @ingroup l2_grps_create def MakeGroup(self, @@ -1752,8 +1777,9 @@ class Mesh: CritType=FT_Undefined, Compare=FT_EqualTo, Treshold="", - UnaryOp=FT_Undefined): - aCriterion = self.smeshpyD.GetCriterion(elementType, CritType, Compare, Treshold, UnaryOp, FT_Undefined) + UnaryOp=FT_Undefined, + Tolerance=1e-07): + aCriterion = self.smeshpyD.GetCriterion(elementType, CritType, Compare, Treshold, UnaryOp, FT_Undefined,Tolerance) group = self.MakeGroupByCriterion(groupName, aCriterion) return group @@ -1969,6 +1995,13 @@ class Mesh: def GetMeshEditor(self): return self.mesh.GetMeshEditor() + ## Wrap a list of IDs of elements or nodes into SMESH_IDSource which + # can be passed as argument to accepting mesh, group or sub-mesh + # @return an instance of SMESH_IDSource + # @ingroup l1_auxiliary + def GetIDSource(self, ids, elemType): + return self.GetMeshEditor().MakeIDSource(ids, elemType) + ## Gets MED Mesh # @return an instance of SALOME_MED::MESH # @ingroup l1_auxiliary @@ -3213,7 +3246,7 @@ class Mesh: ## Generates new elements by extrusion of the elements with given ids # @param IDsOfElements the list of elements ids for extrusion - # @param StepVector vector, defining the direction and value of extrusion + # @param StepVector vector or DirStruct, defining the direction and value of extrusion # @param NbOfSteps the number of steps # @param MakeGroups forces the generation of new groups from existing ones # @return the list of created groups (SMESH_GroupBase) if MakeGroups=True, empty list otherwise @@ -3700,7 +3733,7 @@ class Mesh: if ( isinstance( theObject, Mesh )): theObject = theObject.GetMesh() if ( isinstance( theObject, list )): - theObject = self.editor.MakeIDSource(theObject, SMESH.ALL) + theObject = self.GetIDSource(theObject, SMESH.ALL) thePoint, Parameters = ParsePointStruct(thePoint) self.mesh.SetParameters(Parameters) @@ -3721,7 +3754,7 @@ class Mesh: if (isinstance(theObject, Mesh)): theObject = theObject.GetMesh() if ( isinstance( theObject, list )): - theObject = self.editor.MakeIDSource(theObject,SMESH.ALL) + theObject = self.GetIDSource(theObject,SMESH.ALL) mesh = self.editor.ScaleMakeMesh(theObject, thePoint, theScaleFact, MakeGroups, NewMeshName) @@ -3855,7 +3888,7 @@ class Mesh: if not isinstance( exceptNodes, list): exceptNodes = [ exceptNodes ] if exceptNodes and isinstance( exceptNodes[0], int): - exceptNodes = [ self.editor.MakeIDSource( exceptNodes, SMESH.NODE)] + exceptNodes = [ self.GetIDSource( exceptNodes, SMESH.NODE)] return self.editor.FindCoincidentNodesOnPartBut(SubMeshOrGroup, Tolerance,exceptNodes) ## Merges nodes @@ -4329,8 +4362,11 @@ class Mesh_Algorithm: pass self.mesh.smeshpyD.SetName(hypo, hyp + a) pass + geomName="" + if self.geom: + geomName = GetName(self.geom) status = self.mesh.mesh.AddHypothesis(self.geom, hypo) - TreatHypoStatus( status, GetName(hypo), GetName(self.geom), 0 ) + TreatHypoStatus( status, GetName(hypo), geomName, 0 ) return hypo ## Returns entry of the shape to mesh in the study @@ -4873,20 +4909,31 @@ class Mesh_Triangle(Mesh_Algorithm): self.Parameters().SetOptionValue(optionName,level) ## Sets QuadAllowed flag. - # Only for algoType == NETGEN || NETGEN_2D || BLSURF + # Only for algoType == NETGEN(NETGEN_1D2D) || NETGEN_2D || BLSURF # @ingroup l3_hypos_netgen l3_hypos_blsurf def SetQuadAllowed(self, toAllow=True): if self.algoType == NETGEN_2D: - if toAllow: # add QuadranglePreference - self.Hypothesis("QuadranglePreference", UseExisting=1, CompareMethod=self.CompareEqualHyp) - else: # remove QuadranglePreference + if not self.params: + # use simple hyps + hasSimpleHyps = False + simpleHyps = ["QuadranglePreference","LengthFromEdges","MaxElementArea"] for hyp in self.mesh.GetHypothesisList( self.geom ): - if hyp.GetName() == "QuadranglePreference": - self.mesh.RemoveHypothesis( self.geom, hyp ) + if hyp.GetName() in simpleHyps: + hasSimpleHyps = True + if hyp.GetName() == "QuadranglePreference": + if not toAllow: # remove QuadranglePreference + self.mesh.RemoveHypothesis( self.geom, hyp ) + pass + return pass pass + if hasSimpleHyps: + if toAllow: # add QuadranglePreference + self.Hypothesis("QuadranglePreference", UseExisting=1, CompareMethod=self.CompareEqualHyp) + pass + return pass - return + pass if self.Parameters(): self.params.SetQuadAllowed(toAllow) return @@ -4895,30 +4942,25 @@ class Mesh_Triangle(Mesh_Algorithm): # # @ingroup l3_hypos_netgen def Parameters(self, which=SOLE): - if self.params: - return self.params - if self.algoType == NETGEN: - if which == SIMPLE: - self.params = self.Hypothesis("NETGEN_SimpleParameters_2D", [], + if not self.params: + if self.algoType == NETGEN: + if which == SIMPLE: + self.params = self.Hypothesis("NETGEN_SimpleParameters_2D", [], + "libNETGENEngine.so", UseExisting=0) + else: + self.params = self.Hypothesis("NETGEN_Parameters_2D", [], + "libNETGENEngine.so", UseExisting=0) + elif self.algoType == MEFISTO: + print "Mefisto algo support no multi-parameter hypothesis" + elif self.algoType == NETGEN_2D: + self.params = self.Hypothesis("NETGEN_Parameters_2D_ONLY", [], "libNETGENEngine.so", UseExisting=0) + elif self.algoType == BLSURF: + self.params = self.Hypothesis("BLSURF_Parameters", [], + "libBLSURFEngine.so", UseExisting=0) else: - self.params = self.Hypothesis("NETGEN_Parameters_2D", [], - "libNETGENEngine.so", UseExisting=0) - return self.params - elif self.algoType == MEFISTO: - print "Mefisto algo support no multi-parameter hypothesis" - return None - elif self.algoType == NETGEN_2D: - print "NETGEN_2D_ONLY algo support no multi-parameter hypothesis" - print "NETGEN_2D_ONLY uses 'MaxElementArea' and 'LengthFromEdges' ones" - return None - elif self.algoType == BLSURF: - self.params = self.Hypothesis("BLSURF_Parameters", [], - "libBLSURFEngine.so", UseExisting=0) - return self.params - else: - print "Mesh_Triangle with algo type %s does not have such a parameter, check algo type"%self.algoType - return None + print "Mesh_Triangle with algo type %s does not have such a parameter, check algo type"%self.algoType + return self.params ## Sets MaxSize # @@ -5155,33 +5197,34 @@ class Mesh_Tetrahedron(Mesh_Algorithm): # # @ingroup l3_hypos_netgen def Parameters(self, which=SOLE): - if self.params: - return self.params + if not self.params: - if self.algoType == FULL_NETGEN: - if which == SIMPLE: - self.params = self.Hypothesis("NETGEN_SimpleParameters_3D", [], - "libNETGENEngine.so", UseExisting=0) - else: - self.params = self.Hypothesis("NETGEN_Parameters", [], + if self.algoType == FULL_NETGEN: + if which == SIMPLE: + self.params = self.Hypothesis("NETGEN_SimpleParameters_3D", [], + "libNETGENEngine.so", UseExisting=0) + else: + self.params = self.Hypothesis("NETGEN_Parameters", [], + "libNETGENEngine.so", UseExisting=0) + + if self.algoType == NETGEN: + self.params = self.Hypothesis("NETGEN_Parameters_3D", [], "libNETGENEngine.so", UseExisting=0) - return self.params - if self.algoType == GHS3D: - self.params = self.Hypothesis("GHS3D_Parameters", [], - "libGHS3DEngine.so", UseExisting=0) - return self.params + elif self.algoType == GHS3D: + self.params = self.Hypothesis("GHS3D_Parameters", [], + "libGHS3DEngine.so", UseExisting=0) - if self.algoType == GHS3DPRL: - self.params = self.Hypothesis("GHS3DPRL_Parameters", [], - "libGHS3DPRLEngine.so", UseExisting=0) - return self.params + elif self.algoType == GHS3DPRL: + self.params = self.Hypothesis("GHS3DPRL_Parameters", [], + "libGHS3DPRLEngine.so", UseExisting=0) + else: + print "Algo supports no multi-parameter hypothesis" - print "Algo supports no multi-parameter hypothesis" - return None + return self.params ## Sets MaxSize - # Parameter of FULL_NETGEN + # Parameter of FULL_NETGEN and NETGEN # @ingroup l3_hypos_netgen def SetMaxSize(self, theSize): self.Parameters().SetMaxSize(theSize) @@ -5193,7 +5236,7 @@ class Mesh_Tetrahedron(Mesh_Algorithm): self.Parameters().SetSecondOrder(theVal) ## Sets Optimize flag - # Parameter of FULL_NETGEN + # Parameter of FULL_NETGEN and NETGEN # @ingroup l3_hypos_netgen def SetOptimize(self, theVal): self.Parameters().SetOptimize(theVal) diff --git a/src/StdMeshers/StdMeshers_Import_1D.cxx b/src/StdMeshers/StdMeshers_Import_1D.cxx index fe0f05476..dcd66eca9 100644 --- a/src/StdMeshers/StdMeshers_Import_1D.cxx +++ b/src/StdMeshers/StdMeshers_Import_1D.cxx @@ -120,6 +120,7 @@ namespace // INTERNAL STUFF enum _ListenerDataType { WAIT_HYP_MODIF=1, // data indicating awaiting for valid parameters of src hyp + LISTEN_SRC_MESH, // data storing submesh depending on source mesh state SRC_HYP // data storing ImportSource hyp }; //================================================================================ @@ -130,10 +131,29 @@ namespace // INTERNAL STUFF struct _ListenerData : public SMESH_subMeshEventListenerData { const StdMeshers_ImportSource1D* _srcHyp; - _ListenerData(const StdMeshers_ImportSource1D* h): + _ListenerData(const StdMeshers_ImportSource1D* h, _ListenerDataType type=SRC_HYP): SMESH_subMeshEventListenerData(/*isDeletable=*/true), _srcHyp(h) { - myType = SRC_HYP; + myType = type; + } + }; + //================================================================================ + /*! + * \brief Comparator of sub-meshes + */ + struct _SubLess + { + bool operator()(const SMESH_subMesh* sm1, const SMESH_subMesh* sm2 ) const + { + if ( sm1 == sm2 ) return false; + if ( !sm1 || !sm2 ) return sm1 < sm2; + const TopoDS_Shape& s1 = sm1->GetSubShape(); + const TopoDS_Shape& s2 = sm2->GetSubShape(); + TopAbs_ShapeEnum t1 = s1.IsNull() ? TopAbs_SHAPE : s1.ShapeType(); + TopAbs_ShapeEnum t2 = s2.IsNull() ? TopAbs_SHAPE : s2.ShapeType(); + if ( t1 == t2) + return (sm1 < sm2); + return t1 < t2; // to have: face < edge } }; //================================================================================ @@ -146,10 +166,10 @@ namespace // INTERNAL STUFF StdMeshers_Import_1D::TNodeNodeMap _n2n; StdMeshers_Import_1D::TElemElemMap _e2e; - set< SMESH_subMesh*> _subM; // submeshes relating to this srcMesh - set< SMESH_subMesh*> _copyMeshSubM; // submeshes requesting mesh copying - set< SMESH_subMesh*> _copyGroupSubM; // submeshes requesting mesh copying - set< SMESH_subMesh*> _computedSubM; + set< SMESH_subMesh*, _SubLess > _subM; // submeshes relating to this srcMesh + set< SMESH_subMesh*, _SubLess > _copyMeshSubM; // submeshes requesting mesh copying + set< SMESH_subMesh*, _SubLess > _copyGroupSubM; // submeshes requesting mesh copying + set< SMESH_subMesh*, _SubLess > _computedSubM; SMESHDS_SubMesh* _importMeshSubDS; // submesh storing a copy of _srcMesh int _importMeshSubID; // id of _importMeshSubDS @@ -196,10 +216,30 @@ namespace // INTERNAL STUFF if ( toCopyGroups ) _copyGroupSubM.insert( sm ); else _copyGroupSubM.erase( sm ); } + void addComputed( SMESH_subMesh* sm ) + { + SMESH_subMeshIteratorPtr smIt = sm->getDependsOnIterator(/*includeSelf=*/true, + /*complexShapeFirst=*/true); + while ( smIt->more() ) + { + sm = smIt->next(); + switch ( sm->GetSubShape().ShapeType() ) + { + case TopAbs_EDGE: + case TopAbs_FACE: + _subM.insert( sm ); + if ( !sm->IsEmpty() ) + _computedSubM.insert( sm ); + case TopAbs_VERTEX: + break; + default:; + } + } + } }; //================================================================================ /*! - * Listener notified on events of an imported submesh + * Listener notified on events relating to imported submesh */ class _Listener : public SMESH_subMeshEventListener { @@ -212,198 +252,248 @@ namespace // INTERNAL STUFF // return poiter to a static listener static _Listener* get() { static _Listener theListener; return &theListener; } - //-------------------------------------------------------------------------------- - /*! - * \brief Find or create ImportData for given meshes - */ - static _ImportData* getImportData(const SMESH_Mesh* srcMesh, - SMESH_Mesh* tgtMesh) - { - list< _ImportData >& dList = get()->_tgtMesh2ImportData[tgtMesh]; - list< _ImportData >::iterator d = dList.begin(); - for ( ; d != dList.end(); ++d ) - if ( d->_srcMesh == srcMesh ) - return &*d; - dList.push_back(_ImportData(srcMesh)); - return &dList.back(); - } + static _ImportData* getImportData(const SMESH_Mesh* srcMesh, SMESH_Mesh* tgtMesh); - //-------------------------------------------------------------------------------- - /*! - * \brief Remember an imported mesh and groups - * \param smDS - submesh DS holding the imported mesh - * \param sm - submesh computed by Import algo - * \param srcMeshDS - source mesh - * \param srcHyp - ImportSource hypothesis - */ - static _ImportData* storeImportSubmesh(SMESH_subMesh* importSub, - const SMESH_Mesh* srcMesh, - const StdMeshers_ImportSource1D* srcHyp) - { - // set listener to hear events of the submesh computed by "Import" algo - importSub->SetEventListener( get(), new _ListenerData(srcHyp), importSub ); - - // set a listener to hear events of the source mesh - SMESH_subMesh* smToNotify = importSub; - SMESH_subMesh* smToListen = srcMesh->GetSubMeshContaining(1); - importSub->SetEventListener - ( new SMESH_subMeshEventListener(/*isDeletable=*/true), - SMESH_subMeshEventListenerData::MakeData( smToNotify ), - smToListen ); - - // remeber the submesh - _ImportData* iData = _Listener::getImportData( srcMesh, importSub->GetFather()); - iData->_subM.insert( importSub ); - iData->trackHypParams( importSub, srcHyp ); - if ( !importSub->IsEmpty() ) - iData->_computedSubM.insert( importSub ); - if ( !iData->_copyMeshSubM.empty() && iData->_importMeshSubID < 1 ) - { - SMESH_Mesh* tgtMesh = importSub->GetFather(); - iData->_importMeshSubID = getSubmeshIDForCopiedMesh( srcMesh->GetMeshDS(),tgtMesh); - iData->_importMeshSubDS = tgtMesh->GetMeshDS()->NewSubMesh( iData->_importMeshSubID ); - } - if ( !importSub->IsEmpty() ) - iData->_computedSubM.insert( importSub ); + static void storeImportSubmesh(SMESH_subMesh* importSub, + const SMESH_Mesh* srcMesh, + const StdMeshers_ImportSource1D* srcHyp); - return iData; - } - //-------------------------------------------------------------------------------- - /*! - * \brief mark sm as missing src hyp with valid groups - */ + virtual void ProcessEvent(const int event, + const int eventType, + SMESH_subMesh* subMesh, + SMESH_subMeshEventListenerData* data, + const SMESH_Hypothesis* hyp); + void removeSubmesh( SMESH_subMesh* sm, _ListenerData* data ); + void clearSubmesh ( SMESH_subMesh* sm, _ListenerData* data, bool clearAllSub ); + + // mark sm as missing src hyp with valid groups static void waitHypModification(SMESH_subMesh* sm) { sm->SetEventListener (get(), SMESH_subMeshEventListenerData::MakeData( sm, WAIT_HYP_MODIF ), sm); } + }; + //-------------------------------------------------------------------------------- + /*! + * \brief Find or create ImportData for given meshes + */ + _ImportData* _Listener::getImportData(const SMESH_Mesh* srcMesh, + SMESH_Mesh* tgtMesh) + { + list< _ImportData >& dList = get()->_tgtMesh2ImportData[tgtMesh]; + list< _ImportData >::iterator d = dList.begin(); + for ( ; d != dList.end(); ++d ) + if ( d->_srcMesh == srcMesh ) + return &*d; + dList.push_back(_ImportData(srcMesh)); + return &dList.back(); + } - //-------------------------------------------------------------------------------- - /*! - * \brief Remove imported mesh and/or groups as soon as no more imported submeshes - * remain computed - * \param sm - submesh loosing Import algo - * \param data - data holding imported groups - */ - void removeSubmesh( SMESH_subMesh* sm, _ListenerData* data ) + //-------------------------------------------------------------------------------- + /*! + * \brief Remember an imported sub-mesh and set needed even listeners + * \param importSub - submesh computed by Import algo + * \param srcMesh - source mesh + * \param srcHyp - ImportSource hypothesis + */ + void _Listener::storeImportSubmesh(SMESH_subMesh* importSub, + const SMESH_Mesh* srcMesh, + const StdMeshers_ImportSource1D* srcHyp) + { + // set listener to hear events of the submesh computed by "Import" algo + importSub->SetEventListener( get(), new _ListenerData(srcHyp), importSub ); + + // set a listener to hear events of the source mesh + SMESH_subMesh* smToNotify = importSub; + SMESH_subMesh* smToListen = srcMesh->GetSubMeshContaining(1); + SMESH_subMeshEventListenerData* data = new _ListenerData(srcHyp, LISTEN_SRC_MESH); + data->mySubMeshes.push_back( smToNotify ); + importSub->SetEventListener( get(), data, smToListen ); + + // remeber the submesh importSub and its sub-submeshes + _ImportData* iData = _Listener::getImportData( srcMesh, importSub->GetFather()); + iData->trackHypParams( importSub, srcHyp ); + iData->addComputed( importSub ); + if ( !iData->_copyMeshSubM.empty() && iData->_importMeshSubID < 1 ) { - list< _ImportData > & dList = _tgtMesh2ImportData[ sm->GetFather() ]; - list< _ImportData >::iterator d = dList.begin(); - for ( ; d != dList.end(); ++d ) - if ( (*d)._subM.erase( sm )) + SMESH_Mesh* tgtMesh = importSub->GetFather(); + iData->_importMeshSubID = getSubmeshIDForCopiedMesh( srcMesh->GetMeshDS(),tgtMesh); + iData->_importMeshSubDS = tgtMesh->GetMeshDS()->NewSubMesh( iData->_importMeshSubID ); + } + } + //-------------------------------------------------------------------------------- + /*! + * \brief Remove imported mesh and/or groups if needed + * \param sm - submesh loosing Import algo + * \param data - data holding imported groups + */ + void _Listener::removeSubmesh( SMESH_subMesh* sm, _ListenerData* data ) + { + list< _ImportData > & dList = _tgtMesh2ImportData[ sm->GetFather() ]; + list< _ImportData >::iterator d = dList.begin(); + for ( ; d != dList.end(); ++d ) + if ( (*d)._subM.erase( sm )) + { + d->_computedSubM.erase( sm ); + bool rmMesh = d->_copyMeshSubM.erase( sm ) && d->_copyMeshSubM.empty(); + bool rmGroups = (d->_copyGroupSubM.erase( sm ) && d->_copyGroupSubM.empty()) || rmMesh; + if ( rmMesh ) + d->removeImportedMesh( sm->GetFather()->GetMeshDS() ); + if ( rmGroups && data ) + d->removeGroups( sm, data->_srcHyp ); + } + } + //-------------------------------------------------------------------------------- + /*! + * \brief Clear submeshes and remove imported mesh and/or groups if necessary + * \param sm - cleared submesh + * \param data - data holding imported groups + */ + void _Listener::clearSubmesh(SMESH_subMesh* sm, _ListenerData* data, bool clearAllSub) + { + list< _ImportData > & dList = _tgtMesh2ImportData[ sm->GetFather() ]; + list< _ImportData >::iterator d = dList.begin(); + for ( ; d != dList.end(); ++d ) + { + if ( !d->_subM.count( sm )) continue; + if ( (*d)._computedSubM.erase( sm ) ) + { + bool copyMesh = !d->_copyMeshSubM.empty(); + if ( copyMesh || clearAllSub ) { - d->_computedSubM.erase( sm ); - bool rmMesh = d->_copyMeshSubM.erase( sm ) && d->_copyMeshSubM.empty(); - bool rmGroups = (d->_copyGroupSubM.erase( sm ) && d->_copyGroupSubM.empty()) || rmMesh; - if ( rmMesh ) - d->removeImportedMesh( sm->GetFather()->GetMeshDS() ); - if ( rmGroups && data ) + // remove imported mesh and groups + d->removeImportedMesh( sm->GetFather()->GetMeshDS() ); + + if ( data ) d->removeGroups( sm, data->_srcHyp ); + + // clear the rest submeshes + if ( !d->_computedSubM.empty() ) + { + set< SMESH_subMesh*, _SubLess> subs; + subs.swap( d->_computedSubM ); // avoid recursion via events + while ( !subs.empty() ) + { + SMESH_subMesh* subM = *subs.begin(); subs.erase( subs.begin() ); + _ListenerData* hypData = (_ListenerData*) subM->GetEventListenerData( get() ); + if ( hypData ) + d->removeGroups( sm, hypData->_srcHyp ); + + subM->ComputeStateEngine( SMESH_subMesh::CLEAN ); + if ( subM->GetSubShape().ShapeType() == TopAbs_FACE ) + subM->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN ); + } + } } + sm->ComputeStateEngine( SMESH_subMesh::CLEAN ); + if ( sm->GetSubShape().ShapeType() == TopAbs_FACE ) + sm->ComputeSubMeshStateEngine( SMESH_subMesh::CLEAN ); + } + if ( data ) + d->trackHypParams( sm, data->_srcHyp ); + d->_n2n.clear(); + d->_e2e.clear(); } - //-------------------------------------------------------------------------------- - /*! - * \brief Remove imported mesh and/or groups and - * clear all submeshes with common source mesh - * \param sm - cleared submesh - * \param data - data holding imported groups - */ - void clearSubmesh( SMESH_subMesh* sm, _ListenerData* data ) + } + //-------------------------------------------------------------------------------- + /*! + * \brief Remove imported mesh and/or groups + */ + void _Listener::ProcessEvent(const int event, + const int eventType, + SMESH_subMesh* subMesh, + SMESH_subMeshEventListenerData* data, + const SMESH_Hypothesis* /*hyp*/) + { + if ( data && data->myType == WAIT_HYP_MODIF ) { - list< _ImportData > & dList = _tgtMesh2ImportData[ sm->GetFather() ]; - list< _ImportData >::iterator d = dList.begin(); - for ( ; d != dList.end(); ++d ) + // event of Import submesh + if ( SMESH_subMesh::MODIF_HYP == event && + SMESH_subMesh::ALGO_EVENT == eventType ) { - if ( !d->_subM.count( sm )) continue; - if ( (*d)._computedSubM.erase( sm ) ) - { - bool copyMesh = !d->_copyMeshSubM.empty(); - if ( copyMesh ) + // re-call SetEventListener() to take into account valid parameters + // of ImportSource hypothesis + SMESH_Gen* gen = subMesh->GetFather()->GetGen(); + if ( SMESH_Algo* algo = gen->GetAlgo(*subMesh->GetFather(), subMesh->GetSubShape())) + algo->SetEventListener( subMesh ); + } + } + else if ( data && data->myType == LISTEN_SRC_MESH ) + { + // event of source mesh + if ( SMESH_subMesh::COMPUTE_EVENT == eventType ) + { + switch ( event ) { + case SMESH_subMesh::CLEAN: + // source mesh cleaned -> clean target mesh + clearSubmesh( data->mySubMeshes.front(), (_ListenerData*) data, /*all=*/true ); + break; + case SMESH_subMesh::SUBMESH_COMPUTED: { + // source mesh computed -> reset FAILED state of Import submeshes to + // READY_TO_COMPUTE + SMESH_Mesh* srcMesh = subMesh->GetFather(); + if ( srcMesh->NbEdges() > 0 || srcMesh->NbFaces() > 0 ) { - // clear submeshes - if ( !d->_computedSubM.empty() ) + SMESH_Mesh* m = data->mySubMeshes.front()->GetFather(); + if ( SMESH_subMesh* sm1 = m->GetSubMeshContaining(1)) { - set< SMESH_subMesh*> subs; - subs.swap( d->_computedSubM ); // avoid recursion via events - while ( !subs.empty() ) - { - SMESH_subMesh* subM = *subs.begin(); subs.erase( subs.begin() ); - _ListenerData* hypData = (_ListenerData*) subM->GetEventListenerData( get() ); - if ( hypData ) - d->removeGroups( sm, hypData->_srcHyp ); - - subM->ComputeStateEngine( SMESH_subMesh::CLEAN ); - } + sm1->ComputeStateEngine(SMESH_subMesh::SUBMESH_COMPUTED ); + sm1->ComputeSubMeshStateEngine( SMESH_subMesh::SUBMESH_COMPUTED ); } - // remove imported mesh and groups - d->removeImportedMesh( sm->GetFather()->GetMeshDS() ); - - if ( data ) - d->removeGroups( sm, data->_srcHyp ); } + break; + } + default:; } - if ( data ) - d->trackHypParams( sm, data->_srcHyp ); - d->_n2n.clear(); - d->_e2e.clear(); } } - //-------------------------------------------------------------------------------- - /*! - * \brief Remove imported mesh and/or groups - */ - virtual void ProcessEvent(const int event, - const int eventType, - SMESH_subMesh* subMesh, - SMESH_subMeshEventListenerData* data, - const SMESH_Hypothesis* /*hyp*/) + else // event of Import submesh { - if ( data && data->myType == WAIT_HYP_MODIF ) + // find out what happens: import hyp modified or removed + bool removeImport = false, modifHyp = false; + if ( SMESH_subMesh::ALGO_EVENT == eventType ) + modifHyp = true; + if ( subMesh->GetAlgoState() != SMESH_subMesh::HYP_OK ) { - if ( SMESH_subMesh::MODIF_HYP == event && - SMESH_subMesh::ALGO_EVENT == eventType ) - { - SMESH_Gen* gen = subMesh->GetFather()->GetGen(); - if ( SMESH_Algo* algo = gen->GetAlgo(*subMesh->GetFather(), subMesh->GetSubShape())) - algo->SetEventListener( subMesh ); - } + removeImport = true; } - else + else if ( SMESH_subMesh::REMOVE_ALGO == event || + SMESH_subMesh::REMOVE_FATHER_ALGO == event ) { SMESH_Gen* gen = subMesh->GetFather()->GetGen(); SMESH_Algo* algo = gen->GetAlgo(*subMesh->GetFather(),subMesh->GetSubShape() ); + removeImport = ( strncmp( "Import", algo->GetName(), 6 ) != 0 ); + } - if ( subMesh->GetAlgoState() != SMESH_subMesh::HYP_OK || - strncmp( "Import", algo->GetName(), 6 ) != 0 ) - { - // treate removal of Import algo from subMesh - removeSubmesh( subMesh, (_ListenerData*) data ); - } - else if ( subMesh->IsEmpty() ) - { - // treate modification of ImportSource hypothesis - clearSubmesh( subMesh, (_ListenerData*) data ); - } - else if ( SMESH_subMesh::CHECK_COMPUTE_STATE == event && - SMESH_subMesh::COMPUTE_EVENT == eventType ) - { - // check compute state of all submeshes impoting from same src mesh; - // this is to take into account 1D computed submeshes hidden by 2D import algo; - // else source mesh is not copied as _subM.size != _computedSubM.size() - list< _ImportData > & dList = _tgtMesh2ImportData[ subMesh->GetFather() ]; - list< _ImportData >::iterator d = dList.begin(); - for ( ; d != dList.end(); ++d ) - if ( d->_subM.count( subMesh )) - { - set::iterator smIt = d->_subM.begin(); - for( ; smIt != d->_subM.end(); ++smIt ) - if ( (*smIt)->IsMeshComputed() ) - d->_computedSubM.insert( *smIt); - } - } + if ( removeImport ) + { + // treate removal of Import algo from subMesh + removeSubmesh( subMesh, (_ListenerData*) data ); + } + else if ( modifHyp ) + { + // treate modification of ImportSource hypothesis + clearSubmesh( subMesh, (_ListenerData*) data, /*all=*/false ); + } + else if ( SMESH_subMesh::CHECK_COMPUTE_STATE == event && + SMESH_subMesh::COMPUTE_EVENT == eventType ) + { + // check compute state of all submeshes impoting from same src mesh; + // this is to take into account 1D computed submeshes hidden by 2D import algo; + // else source mesh is not copied as _subM.size != _computedSubM.size() + list< _ImportData > & dList = _tgtMesh2ImportData[ subMesh->GetFather() ]; + list< _ImportData >::iterator d = dList.begin(); + for ( ; d != dList.end(); ++d ) + if ( d->_subM.count( subMesh )) + { + set::iterator smIt = d->_subM.begin(); + for( ; smIt != d->_subM.end(); ++smIt ) + if ( (*smIt)->IsMeshComputed() ) + d->_computedSubM.insert( *smIt); + } } } - }; // class _Listener + } //================================================================================ /*! @@ -495,7 +585,7 @@ namespace // INTERNAL STUFF _ImportData* iData = _Listener::getImportData(srcMesh,tgtMesh); SMESH_subMesh* importedSM = tgtMesh->GetSubMesh( tgtShape ); - iData->_computedSubM.insert( importedSM ); + iData->addComputed( importedSM ); if ( iData->_computedSubM.size() != iData->_subM.size() ) return 0; // not all submeshes computed yet @@ -543,8 +633,8 @@ bool StdMeshers_Import_1D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & th subShapeIDs.insert( shapeID ); // get nodes on vertices - list < SMESH_MeshEditor::TNodeXYZ > vertexNodes; - list < SMESH_MeshEditor::TNodeXYZ >::iterator vNIt; + list < SMESH_MeshEditor::TNodeXYZ > vertexNodes; + list < SMESH_MeshEditor::TNodeXYZ >::iterator vNIt; TopExp_Explorer vExp( theShape, TopAbs_VERTEX ); for ( ; vExp.More(); vExp.Next() ) { diff --git a/src/StdMeshers/StdMeshers_Import_1D2D.cxx b/src/StdMeshers/StdMeshers_Import_1D2D.cxx index 5513a1077..c05480d9c 100644 --- a/src/StdMeshers/StdMeshers_Import_1D2D.cxx +++ b/src/StdMeshers/StdMeshers_Import_1D2D.cxx @@ -153,8 +153,8 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & const bool toCheckOri = (helper.NbAncestors( geomFace, theMesh, TopAbs_SOLID ) == 1 ); Handle(Geom_Surface) surface = BRep_Tool::Surface( geomFace ); - if ( helper.GetSubShapeOri( tgtMesh->ShapeToMesh(), geomFace) == TopAbs_REVERSED ) - surface->UReverse(); + const bool reverse = + ( helper.GetSubShapeOri( tgtMesh->ShapeToMesh(), geomFace) == TopAbs_REVERSED ); gp_Pnt p; gp_Vec du, dv; set subShapeIDs; @@ -262,7 +262,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & { uv = helper.GetNodeUV( geomFace, newNodes[++iNode] ); surface->D1( uv.X(),uv.Y(), p, du,dv ); - geomNorm = du ^ dv; + geomNorm = reverse ? dv^du : du^dv; } while ( geomNorm.SquareMagnitude() < 1e-6 && iNode+1 < face->NbCornerNodes()); @@ -340,7 +340,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & int nbFaces = link2Nb->second; if ( nbFaces == 1 ) { - // check if the link lie on face boundary + // check if a not shared link lie on face boundary bool nodesOnBoundary = true; list< TopoDS_Shape > bndShapes; for ( int is1stN = 0; is1stN < 2 && nodesOnBoundary; ++is1stN ) @@ -355,6 +355,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & if ( Abs(u-f) < 2 * faceTol || Abs(u-l) < 2 * faceTol ) // duplicated node on vertex return error("Source elements overlap one another"); + tgtSM->RemoveNode( n, /*isNodeDeleted=*/false ); tgtMesh->SetNodeOnEdge( (SMDS_MeshNode*)n, edges[iE], u ); break; } @@ -370,10 +371,10 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & } } if ( !nodesOnBoundary ) - break; // free internal link + break; // error: free internal link if ( bndShapes.front().ShapeType() == TopAbs_EDGE && bndShapes.front() != bndShapes.back() ) - break; // link nodes on different geom edges + break; // error: link nodes on different geom edges // find geom edge the link is on if ( bndShapes.back().ShapeType() != TopAbs_EDGE ) @@ -388,7 +389,7 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & geomEdge.Nullify(); } if ( geomEdge.IsNull() ) - break; // vertices belong to different edges -> free internal link + break; // vertices belong to different edges -> error: free internal link bndShapes.push_back( geomEdge ); } @@ -406,15 +407,13 @@ bool StdMeshers_Import_1D2D::Compute(SMESH_Mesh & theMesh, const TopoDS_Shape & TopoDS_Edge geomEdge = TopoDS::Edge(bndShapes.back()); helper.CheckNodeU( geomEdge, link._medium, u, 10*faceTol, /*force=*/true ); + tgtSM->RemoveNode( link._medium, /*isNodeDeleted=*/false ); tgtMesh->SetNodeOnEdge( (SMDS_MeshNode*)link._medium, geomEdge, u ); } else { edge = tgtMesh->AddEdge( newNodes[0], newNodes[1]); } - // remove nodes from submesh of theShape - for ( unsigned i = 0; i < newNodes.size(); ++i ) - tgtSM->RemoveNode( newNodes[i], /*isNodeDeleted=*/false ); if ( !edge ) return false;