Salome HOME
Changes for bug 0020671.
authorskl <skl@opencascade.com>
Wed, 3 Mar 2010 07:23:24 +0000 (07:23 +0000)
committerskl <skl@opencascade.com>
Wed, 3 Mar 2010 07:23:24 +0000 (07:23 +0000)
32 files changed:
doc/salome/gui/SMESH/images/scale01.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/scale02.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/scale03.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/scale04.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/scale06.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/scale07.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/scale09.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/scaleinit01.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/scaleinit02.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/scaleres03.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/scaleres04.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/scaleres06.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/scaleres07.png [new file with mode: 0644]
doc/salome/gui/SMESH/images/scaleres09.png [new file with mode: 0644]
doc/salome/gui/SMESH/input/modifying_meshes.doc
doc/salome/gui/SMESH/input/scale.doc [new file with mode: 0644]
doc/salome/gui/SMESH/input/tui_transforming_meshes.doc
idl/SMESH_MeshEditor.idl
resources/Makefile.am
resources/scale.png [new file with mode: 0644]
resources/scale_along_axes.png [new file with mode: 0644]
src/SMESH/SMESH_MeshEditor.cxx
src/SMESH/SMESH_MeshEditor.hxx
src/SMESHGUI/Makefile.am
src/SMESHGUI/SMESHGUI.cxx
src/SMESHGUI/SMESHGUI_ScaleDlg.cxx [new file with mode: 0644]
src/SMESHGUI/SMESHGUI_ScaleDlg.h [new file with mode: 0644]
src/SMESHGUI/SMESH_images.ts
src/SMESHGUI/SMESH_msg_en.ts
src/SMESH_I/SMESH_MeshEditor_i.cxx
src/SMESH_I/SMESH_MeshEditor_i.hxx
src/SMESH_SWIG/smeshDC.py

diff --git a/doc/salome/gui/SMESH/images/scale01.png b/doc/salome/gui/SMESH/images/scale01.png
new file mode 100644 (file)
index 0000000..72ae775
Binary files /dev/null and b/doc/salome/gui/SMESH/images/scale01.png differ
diff --git a/doc/salome/gui/SMESH/images/scale02.png b/doc/salome/gui/SMESH/images/scale02.png
new file mode 100644 (file)
index 0000000..9d6a5f3
Binary files /dev/null and b/doc/salome/gui/SMESH/images/scale02.png differ
diff --git a/doc/salome/gui/SMESH/images/scale03.png b/doc/salome/gui/SMESH/images/scale03.png
new file mode 100644 (file)
index 0000000..891ae8d
Binary files /dev/null and b/doc/salome/gui/SMESH/images/scale03.png differ
diff --git a/doc/salome/gui/SMESH/images/scale04.png b/doc/salome/gui/SMESH/images/scale04.png
new file mode 100644 (file)
index 0000000..a042834
Binary files /dev/null and b/doc/salome/gui/SMESH/images/scale04.png differ
diff --git a/doc/salome/gui/SMESH/images/scale06.png b/doc/salome/gui/SMESH/images/scale06.png
new file mode 100644 (file)
index 0000000..2bd8219
Binary files /dev/null and b/doc/salome/gui/SMESH/images/scale06.png differ
diff --git a/doc/salome/gui/SMESH/images/scale07.png b/doc/salome/gui/SMESH/images/scale07.png
new file mode 100644 (file)
index 0000000..8ee0923
Binary files /dev/null and b/doc/salome/gui/SMESH/images/scale07.png differ
diff --git a/doc/salome/gui/SMESH/images/scale09.png b/doc/salome/gui/SMESH/images/scale09.png
new file mode 100644 (file)
index 0000000..2816bac
Binary files /dev/null and b/doc/salome/gui/SMESH/images/scale09.png differ
diff --git a/doc/salome/gui/SMESH/images/scaleinit01.png b/doc/salome/gui/SMESH/images/scaleinit01.png
new file mode 100644 (file)
index 0000000..97990a8
Binary files /dev/null and b/doc/salome/gui/SMESH/images/scaleinit01.png differ
diff --git a/doc/salome/gui/SMESH/images/scaleinit02.png b/doc/salome/gui/SMESH/images/scaleinit02.png
new file mode 100644 (file)
index 0000000..008d2e3
Binary files /dev/null and b/doc/salome/gui/SMESH/images/scaleinit02.png differ
diff --git a/doc/salome/gui/SMESH/images/scaleres03.png b/doc/salome/gui/SMESH/images/scaleres03.png
new file mode 100644 (file)
index 0000000..99b65d7
Binary files /dev/null and b/doc/salome/gui/SMESH/images/scaleres03.png differ
diff --git a/doc/salome/gui/SMESH/images/scaleres04.png b/doc/salome/gui/SMESH/images/scaleres04.png
new file mode 100644 (file)
index 0000000..0880989
Binary files /dev/null and b/doc/salome/gui/SMESH/images/scaleres04.png differ
diff --git a/doc/salome/gui/SMESH/images/scaleres06.png b/doc/salome/gui/SMESH/images/scaleres06.png
new file mode 100644 (file)
index 0000000..059fa97
Binary files /dev/null and b/doc/salome/gui/SMESH/images/scaleres06.png differ
diff --git a/doc/salome/gui/SMESH/images/scaleres07.png b/doc/salome/gui/SMESH/images/scaleres07.png
new file mode 100644 (file)
index 0000000..b75f83c
Binary files /dev/null and b/doc/salome/gui/SMESH/images/scaleres07.png differ
diff --git a/doc/salome/gui/SMESH/images/scaleres09.png b/doc/salome/gui/SMESH/images/scaleres09.png
new file mode 100644 (file)
index 0000000..4708be5
Binary files /dev/null and b/doc/salome/gui/SMESH/images/scaleres09.png differ
index cf63ff5f4a8c346743cea2e952da3d6b4dc253ea..2a396d3cdb2c7e8d1f823406d33e87d3a971d9c2 100644 (file)
@@ -18,6 +18,7 @@ elements of the mesh.</li>
 its elements.</li>
 <li>\subpage rotation_page "Rotate" by the indicated axis and angle
 the mesh or some of its elements.</li>
+<li>\subpage scale_page "Scale Transform" the mesh or some of its elements.</li>
 <li>Create a \subpage symmetry_page "symmetrical copy" of the mesh
 through a point or a vector of symmetry.</li>
 <li>Unite meshes by \subpage sewing_meshes_page "sewing" free borders,
diff --git a/doc/salome/gui/SMESH/input/scale.doc b/doc/salome/gui/SMESH/input/scale.doc
new file mode 100644 (file)
index 0000000..4f77ce8
--- /dev/null
@@ -0,0 +1,132 @@
+/*!
+
+\page scale_page Scale
+
+\n This geometrical operation allows to scale in space your mesh
+or some of its elements.
+
+<em>To scale a mesh:</em>
+
+<ol>
+<li>From the \b Modification menu choose \b Transformation -> \b Scale
+\b Transform item.
+
+One of the following dialogs will appear:
+
+With one scale factor:
+\image html scale01.png
+
+Or with different scale factors for axises:
+\image html scale02.png
+
+</li>
+
+<li>
+In the dialog:
+<ul>
+<li>specify the IDs of the translated elements:
+
+<ul>
+<li><b>Select the whole mesh, submesh or group</b> activating this
+checkbox; or</li>
+<li>choose mesh elements with the mouse in the 3D Viewer. It is
+possible to select a whole area with a mouse frame; or</li> 
+<li>input the element IDs directly in <b>ID Elements</b> field. The selected elements will be highlighted in the
+viewer; or</li>
+<li>apply Filters. <b>Set filter</b> button allows to apply a filter to the selection of elements. See more
+about filters in the \ref selection_filter_library_page "Selection filter library" page.</li>
+</ul>
+</li>
+
+<li>specify the base point for scale</li>
+
+<li>specify the scale factor</li>
+
+<li>specify the conditions of scale:
+<ul>
+<li>activate <b>Move elements</b> radio button to create  the source
+mesh (or elements) at the new location and erase it from the previous location;</li>
+<li>activate <b>Copy elements</b> radio button to create the source
+mesh (or elements) at the new location, but leave it at the previous
+location, the source mesh will be considered one and single mesh with the result of the rotation;</li>
+<li>activate <b>Create as new mesh</b> radio button to leave the
+source mesh (or elements) at its previous location and create a new
+mesh at the new location, the new mesh appears in the Object Browser
+with the default name MeshName_rotated (it is possible to change this
+name in the adjacent box);</li>
+<li>activate <b> Copy groups </b> checkbox to copy the groups of elements of the source mesh to the newly created mesh.</li>
+</ul>
+</li>
+
+</li>
+
+<li>Click \b Apply or <b> Apply and Close</b> button to confirm the operation.</li>
+</ol>
+
+
+
+<b>Examle of using:</b>
+
+1. Create quandrangle mesh 3x3 on simple planar face (200x200)
+
+\image html scaleinit01.png
+
+and union 3 face (along axis Z) to group "gr_faces"
+
+\image html scaleinit02.png
+
+
+
+2. Perform scale opration for whole mesh with creation of new mesh:
+
+\image html scale03.png
+
+result after operation:
+
+\image html scaleres03.png
+
+
+
+3. Perform scale operation for whole mesh with copy of elements:
+
+\image html scale04.png
+
+result after operation:
+
+\image html scaleres04.png
+
+
+
+4. Perform scale opration for group of faces with copy of elements:
+
+\image html scale06.png
+
+result after operation:
+
+\image html scaleres06.png
+
+
+
+5. Perform scale opration for two edges with moving of elements:
+
+\image html scale07.png
+
+result after operation:
+
+\image html scaleres07.png
+
+
+
+6. Perform scale opration for one face with moving of elements:
+
+\image html scale09.png
+
+result after operation:
+
+\image html scaleres09.png
+
+
+<br><b>See Also</b> a sample TUI Script of a \ref tui_scale "Scale" operation.  
+
+
+*/
index 163afe0e49f2bae1c8cb0b404add6cbaab50b21b..1658e58c59af8e655909af89f0cb3ff62d8a3f19 100644 (file)
@@ -44,6 +44,37 @@ angle270 = 1.5 * math.pi
 mesh.Rotate([], axisXYZ, angle270, 1)  
 \endcode
 
+<br>
+\anchor tui_scale
+<h3>Scale</h3>
+
+\code
+import geompy
+Box = geompy.MakeBoxDXDYDZ(200, 200, 200)
+f = geompy.SubShapeAllSorted(Box, geompy.ShapeType["FACE"])
+
+import smesh,SMESH
+import StdMeshers
+Mesh1 = smesh.Mesh(f[0])
+Regular_1D = Mesh1.Segment()
+Nb_Segments_1 = Regular_1D.NumberOfSegments(3)
+Nb_Segments_1.SetDistrType( 0 )
+Quadrangle_2D = Mesh1.Quadrangle()
+isDone = Mesh1.Compute()
+
+#Perform scale opration for whole mesh with creation of new mesh
+newMesh = Mesh1.ScaleMakeMesh(Mesh1,SMESH.PointStruct(100,100,200),[0.5,0.3,0.7],True,"ScaledMesh")
+
+#Perform scale operation for whole mesh with copy of elements
+Mesh1.Scale(Mesh1,SMESH.PointStruct(200,100,100),[0.5,0.5,0.5],True,True)
+
+#Perform scale opration for two edges with moving of elements
+Mesh1.Scale([1,2],SMESH.PointStruct(-100,100,100),[0.8,1.0,0.7],False)
+
+#Perform scale opration for one face with moving of elements
+Mesh1.Scale([21],SMESH.PointStruct(0,200,200),[0.7,0.7,0.7],False)
+\endcode
+
 <br>
 \anchor tui_symmetry
 <h3>Symmetry</h3>
@@ -319,4 +350,4 @@ mesh.Compute()
 mesh.SewSideElements([69, 70, 71, 72], [91, 92, 89, 90], 8, 38, 23, 58)
 \endcode
 
-*/
\ No newline at end of file
+*/
index eb2715b4ed407e58b8d81e182cca97e76d7a5949..49a78661903272216757631dfb3381cbcd17b3e0 100644 (file)
@@ -570,6 +570,19 @@ module SMESH
                                         in boolean        CopyGroups,
                                         in string         MeshName);
 
+    void Scale (in SMESH_IDSource theObject,
+                in PointStruct    thePoint,
+                in double_array   theScaleFact,
+                in boolean        Copy);
+    ListOfGroups ScaleMakeGroups (in SMESH_IDSource theObject,
+                                  in PointStruct    thePoint,
+                                  in double_array   theScaleFact);
+    SMESH_Mesh ScaleMakeMesh (in SMESH_IDSource theObject,
+                              in PointStruct    thePoint,
+                              in double_array   theScaleFact,
+                              in boolean        CopyGroups,
+                              in string         MeshName);
+
     void Rotate (in long_array IDsOfElements,
                  in AxisStruct Axis,
                  in double     AngleInRadians,
index 0b8807d715603b07252646fad32722b21f54738e..1444dc11168b6105ecfadbd8186ede20965a4dec 100644 (file)
@@ -167,7 +167,9 @@ dist_salomeres_DATA = \
        mesh_extractGroup.png \
        mesh_precompute.png \
        mesh_2d_from_3d.png \
-        mesh_free_faces.png
+        mesh_free_faces.png \
+        scale.png \
+        scale_along_axes.png
 
 # VSR: little trick to avoid putting if SMESHCatalog.xml to the distribution archive
 nodist_salomeres_SCRIPTS = SMESHCatalog.xml
diff --git a/resources/scale.png b/resources/scale.png
new file mode 100644 (file)
index 0000000..d838d9f
Binary files /dev/null and b/resources/scale.png differ
diff --git a/resources/scale_along_axes.png b/resources/scale_along_axes.png
new file mode 100644 (file)
index 0000000..04a4ae0
Binary files /dev/null and b/resources/scale_along_axes.png differ
index 9822c70eaf74f8d582d64161593867b492c958f9..1032898a35d53447a00c0e9ce1fb0413def1bc4f 100644 (file)
@@ -4936,6 +4936,331 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
   return newGroupIDs;
 }
 
+
+//=======================================================================
+//function : Scale
+//purpose  :
+//=======================================================================
+
+SMESH_MeshEditor::PGroupIDs
+SMESH_MeshEditor::Scale (TIDSortedElemSet & theElems,
+                         const gp_Pnt&            thePoint,
+                         const std::list<double>& theScaleFact,
+                         const bool         theCopy,
+                         const bool         theMakeGroups,
+                         SMESH_Mesh*        theTargetMesh)
+{
+  myLastCreatedElems.Clear();
+  myLastCreatedNodes.Clear();
+
+  SMESH_MeshEditor targetMeshEditor( theTargetMesh );
+  SMESHDS_Mesh* aTgtMesh = theTargetMesh ? theTargetMesh->GetMeshDS() : 0;
+  SMESHDS_Mesh* aMesh    = GetMeshDS();
+
+  double scaleX=1.0, scaleY=1.0, scaleZ=1.0;
+  std::list<double>::const_iterator itS = theScaleFact.begin();
+  scaleX = (*itS);
+  if(theScaleFact.size()==1) {
+    scaleY = (*itS);
+    scaleZ= (*itS);
+  }
+  if(theScaleFact.size()==2) {
+    itS++;
+    scaleY = (*itS);
+    scaleZ= (*itS);
+  }
+  if(theScaleFact.size()>2) {
+    itS++;
+    scaleY = (*itS);
+    itS++;
+    scaleZ= (*itS);
+  }
+  
+  // map old node to new one
+  TNodeNodeMap nodeMap;
+
+  // elements sharing moved nodes; those of them which have all
+  // nodes mirrored but are not in theElems are to be reversed
+  TIDSortedElemSet inverseElemSet;
+
+  // source elements for each generated one
+  SMESH_SequenceOfElemPtr srcElems, srcNodes;
+
+  // loop on theElems
+  TIDSortedElemSet::iterator itElem;
+  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ ) {
+    const SMDS_MeshElement* elem = *itElem;
+    if ( !elem )
+      continue;
+
+    // loop on elem nodes
+    SMDS_ElemIteratorPtr itN = elem->nodesIterator();
+    while ( itN->more() ) {
+
+      // check if a node has been already transformed
+      const SMDS_MeshNode* node = cast2Node( itN->next() );
+      pair<TNodeNodeMap::iterator,bool> n2n_isnew =
+        nodeMap.insert( make_pair ( node, node ));
+      if ( !n2n_isnew.second )
+        continue;
+
+      //double coord[3];
+      //coord[0] = node->X();
+      //coord[1] = node->Y();
+      //coord[2] = node->Z();
+      //theTrsf.Transforms( coord[0], coord[1], coord[2] );
+      double dx = (node->X() - thePoint.X()) * scaleX;
+      double dy = (node->Y() - thePoint.Y()) * scaleY;
+      double dz = (node->Z() - thePoint.Z()) * scaleZ;
+      if ( theTargetMesh ) {
+        //const SMDS_MeshNode * newNode = aTgtMesh->AddNode( coord[0], coord[1], coord[2] );
+        const SMDS_MeshNode * newNode =
+          aTgtMesh->AddNode( thePoint.X()+dx, thePoint.Y()+dy, thePoint.Z()+dz );
+        n2n_isnew.first->second = newNode;
+        myLastCreatedNodes.Append(newNode);
+        srcNodes.Append( node );
+      }
+      else if ( theCopy ) {
+        //const SMDS_MeshNode * newNode = aMesh->AddNode( coord[0], coord[1], coord[2] );
+        const SMDS_MeshNode * newNode =
+          aMesh->AddNode( thePoint.X()+dx, thePoint.Y()+dy, thePoint.Z()+dz );
+        n2n_isnew.first->second = newNode;
+        myLastCreatedNodes.Append(newNode);
+        srcNodes.Append( node );
+      }
+      else {
+        //aMesh->MoveNode( node, coord[0], coord[1], coord[2] );
+        aMesh->MoveNode( node, thePoint.X()+dx, thePoint.Y()+dy, thePoint.Z()+dz );
+        // node position on shape becomes invalid
+        const_cast< SMDS_MeshNode* > ( node )->SetPosition
+          ( SMDS_SpacePosition::originSpacePosition() );
+      }
+
+      // keep inverse elements
+      //if ( !theCopy && !theTargetMesh && needReverse ) {
+      //  SMDS_ElemIteratorPtr invElemIt = node->GetInverseElementIterator();
+      //  while ( invElemIt->more() ) {
+      //    const SMDS_MeshElement* iel = invElemIt->next();
+      //    inverseElemSet.insert( iel );
+      //  }
+      //}
+    }
+  }
+
+  // either create new elements or reverse mirrored ones
+  //if ( !theCopy && !needReverse && !theTargetMesh )
+  if ( !theCopy && !theTargetMesh )
+    return PGroupIDs();
+
+  TIDSortedElemSet::iterator invElemIt = inverseElemSet.begin();
+  for ( ; invElemIt != inverseElemSet.end(); invElemIt++ )
+    theElems.insert( *invElemIt );
+
+  // replicate or reverse elements
+
+  enum {
+    REV_TETRA   = 0,  //  = nbNodes - 4
+    REV_PYRAMID = 1,  //  = nbNodes - 4
+    REV_PENTA   = 2,  //  = nbNodes - 4
+    REV_FACE    = 3,
+    REV_HEXA    = 4,  //  = nbNodes - 4
+    FORWARD     = 5
+  };
+  int index[][8] = {
+    { 2, 1, 0, 3, 4, 0, 0, 0 },  // REV_TETRA
+    { 2, 1, 0, 3, 4, 0, 0, 0 },  // REV_PYRAMID
+    { 2, 1, 0, 5, 4, 3, 0, 0 },  // REV_PENTA
+    { 2, 1, 0, 3, 0, 0, 0, 0 },  // REV_FACE
+    { 2, 1, 0, 3, 6, 5, 4, 7 },  // REV_HEXA
+    { 0, 1, 2, 3, 4, 5, 6, 7 }   // FORWARD
+  };
+
+  for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
+  {
+    const SMDS_MeshElement* elem = *itElem;
+    if ( !elem || elem->GetType() == SMDSAbs_Node )
+      continue;
+
+    int nbNodes = elem->NbNodes();
+    int elemType = elem->GetType();
+
+    if (elem->IsPoly()) {
+      // Polygon or Polyhedral Volume
+      switch ( elemType ) {
+      case SMDSAbs_Face:
+        {
+          vector<const SMDS_MeshNode*> poly_nodes (nbNodes);
+          int iNode = 0;
+          SMDS_ElemIteratorPtr itN = elem->nodesIterator();
+          while (itN->more()) {
+            const SMDS_MeshNode* node =
+              static_cast<const SMDS_MeshNode*>(itN->next());
+            TNodeNodeMap::iterator nodeMapIt = nodeMap.find(node);
+            if (nodeMapIt == nodeMap.end())
+              break; // not all nodes transformed
+            //if (needReverse) {
+            //  // reverse mirrored faces and volumes
+            //  poly_nodes[nbNodes - iNode - 1] = (*nodeMapIt).second;
+            //} else {
+            poly_nodes[iNode] = (*nodeMapIt).second;
+            //}
+            iNode++;
+          }
+          if ( iNode != nbNodes )
+            continue; // not all nodes transformed
+
+          if ( theTargetMesh ) {
+            myLastCreatedElems.Append(aTgtMesh->AddPolygonalFace(poly_nodes));
+            srcElems.Append( elem );
+          }
+          else if ( theCopy ) {
+            myLastCreatedElems.Append(aMesh->AddPolygonalFace(poly_nodes));
+            srcElems.Append( elem );
+          }
+          else {
+            aMesh->ChangePolygonNodes(elem, poly_nodes);
+          }
+        }
+        break;
+      case SMDSAbs_Volume:
+        {
+          // ATTENTION: Reversing is not yet done!!!
+          const SMDS_PolyhedralVolumeOfNodes* aPolyedre =
+            dynamic_cast<const SMDS_PolyhedralVolumeOfNodes*>( elem );
+          if (!aPolyedre) {
+            MESSAGE("Warning: bad volumic element");
+            continue;
+          }
+
+          vector<const SMDS_MeshNode*> poly_nodes;
+          vector<int> quantities;
+
+          bool allTransformed = true;
+          int nbFaces = aPolyedre->NbFaces();
+          for (int iface = 1; iface <= nbFaces && allTransformed; iface++) {
+            int nbFaceNodes = aPolyedre->NbFaceNodes(iface);
+            for (int inode = 1; inode <= nbFaceNodes && allTransformed; inode++) {
+              const SMDS_MeshNode* node = aPolyedre->GetFaceNode(iface, inode);
+              TNodeNodeMap::iterator nodeMapIt = nodeMap.find(node);
+              if (nodeMapIt == nodeMap.end()) {
+                allTransformed = false; // not all nodes transformed
+              } else {
+                poly_nodes.push_back((*nodeMapIt).second);
+              }
+            }
+            quantities.push_back(nbFaceNodes);
+          }
+          if ( !allTransformed )
+            continue; // not all nodes transformed
+
+          if ( theTargetMesh ) {
+            myLastCreatedElems.Append(aTgtMesh->AddPolyhedralVolume(poly_nodes, quantities));
+            srcElems.Append( elem );
+          }
+          else if ( theCopy ) {
+            myLastCreatedElems.Append(aMesh->AddPolyhedralVolume(poly_nodes, quantities));
+            srcElems.Append( elem );
+          }
+          else {
+            aMesh->ChangePolyhedronNodes(elem, poly_nodes, quantities);
+          }
+        }
+        break;
+      default:;
+      }
+      continue;
+    }
+
+    // Regular elements
+    int* i = index[ FORWARD ];
+    //if ( needReverse && nbNodes > 2) // reverse mirrored faces and volumes
+    //  if ( elemType == SMDSAbs_Face )
+    //    i = index[ REV_FACE ];
+    //  else
+    //    i = index[ nbNodes - 4 ];
+
+    if(elem->IsQuadratic()) {
+      static int anIds[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19};
+      i = anIds;
+      //if(needReverse) {
+      //  if(nbNodes==3) { // quadratic edge
+      //    static int anIds[] = {1,0,2};
+      //    i = anIds;
+      //  }
+      //  else if(nbNodes==6) { // quadratic triangle
+      //    static int anIds[] = {0,2,1,5,4,3};
+      //    i = anIds;
+      //  }
+      //  else if(nbNodes==8) { // quadratic quadrangle
+      //    static int anIds[] = {0,3,2,1,7,6,5,4};
+      //    i = anIds;
+      //  }
+      //  else if(nbNodes==10) { // quadratic tetrahedron of 10 nodes
+      //    static int anIds[] = {0,2,1,3,6,5,4,7,9,8};
+      //    i = anIds;
+      //  }
+      //  else if(nbNodes==13) { // quadratic pyramid of 13 nodes
+      //    static int anIds[] = {0,3,2,1,4,8,7,6,5,9,12,11,10};
+      //    i = anIds;
+      //  }
+      //  else if(nbNodes==15) { // quadratic pentahedron with 15 nodes
+      //    static int anIds[] = {0,2,1,3,5,4,8,7,6,11,10,9,12,14,13};
+      //    i = anIds;
+      //  }
+      //  else { // nbNodes==20 - quadratic hexahedron with 20 nodes
+      //    static int anIds[] = {0,3,2,1,4,7,6,5,11,10,9,8,15,14,13,12,16,19,18,17};
+      //    i = anIds;
+      //  }
+      //}
+    }
+
+    // find transformed nodes
+    vector<const SMDS_MeshNode*> nodes(nbNodes);
+    int iNode = 0;
+    SMDS_ElemIteratorPtr itN = elem->nodesIterator();
+    while ( itN->more() ) {
+      const SMDS_MeshNode* node =
+        static_cast<const SMDS_MeshNode*>( itN->next() );
+      TNodeNodeMap::iterator nodeMapIt = nodeMap.find( node );
+      if ( nodeMapIt == nodeMap.end() )
+        break; // not all nodes transformed
+      nodes[ i [ iNode++ ]] = (*nodeMapIt).second;
+    }
+    if ( iNode != nbNodes )
+      continue; // not all nodes transformed
+
+    if ( theTargetMesh ) {
+      if ( SMDS_MeshElement* copy =
+           targetMeshEditor.AddElement( nodes, elem->GetType(), elem->IsPoly() )) {
+        myLastCreatedElems.Append( copy );
+        srcElems.Append( elem );
+      }
+    }
+    else if ( theCopy ) {
+      if ( SMDS_MeshElement* copy = AddElement( nodes, elem->GetType(), elem->IsPoly() )) {
+        myLastCreatedElems.Append( copy );
+        srcElems.Append( elem );
+      }
+    }
+    else {
+      // reverse element as it was reversed by transformation
+      if ( nbNodes > 2 )
+        aMesh->ChangeElementNodes( elem, &nodes[0], nbNodes );
+    }
+  }
+
+  PGroupIDs newGroupIDs;
+
+  if ( theMakeGroups && theCopy ||
+       theMakeGroups && theTargetMesh ) {
+    string groupPostfix = "scaled";
+    newGroupIDs = generateGroups( srcNodes, srcElems, groupPostfix, theTargetMesh );
+  }
+
+  return newGroupIDs;
+}
+
+
 //=======================================================================
 /*!
  * \brief Create groups of elements made during transformation
index 3c197b2ac20fcf5b4fe91b6dadfbab4d9e45a7e1..db3c262e1fd1bfb85547146a26cb5b86497001d0 100644 (file)
@@ -359,6 +359,23 @@ public:
   // Move or copy theElements applying theTrsf to their nodes
 
 
+  /*!
+   * Generate new elements by extrusion of theElements
+   * param theElems - list of elements for scale
+   * param thePoint - base point for scale
+   * param theScaleFact - scale factors for axises
+   * param theCopy - allows copying the translated elements
+   * param theMakeGroups - forces the generation of new groups from existing ones
+   * param theTargetMesh - the name of the newly created mesh
+   * return instance of Mesh class
+   */
+  PGroupIDs Scale (TIDSortedElemSet&        theElements,
+                   const gp_Pnt&            thePoint,
+                   const std::list<double>& theScaleFact,
+                   const bool               theCopy,
+                   const bool               theMakeGroups,
+                   SMESH_Mesh*              theTargetMesh=0);
+
   typedef std::list< std::list< const SMDS_MeshNode* > > TListOfListOfNodes;
 
   void FindCoincidentNodes (std::set<const SMDS_MeshNode*> & theNodes,
index 9f5eedcb2cc41876a0c603e38004056915a7ecbc..e217ed97ff9b8bc8c9400fef15093d108e58af73 100644 (file)
@@ -71,6 +71,7 @@ salomeinclude_HEADERS = \
        SMESHGUI_RevolutionDlg.h \
        SMESHGUI_RotationDlg.h \
        SMESHGUI_TranslationDlg.h \
+       SMESHGUI_ScaleDlg.h \
        SMESHGUI_SymmetryDlg.h \
        SMESHGUI_SewingDlg.h \
        SMESHGUI_EditMeshDlg.h \
@@ -134,6 +135,7 @@ dist_libSMESH_la_SOURCES = \
        SMESHGUI_RevolutionDlg.cxx \
        SMESHGUI_RotationDlg.cxx \
        SMESHGUI_TranslationDlg.cxx \
+       SMESHGUI_ScaleDlg.cxx \
        SMESHGUI_SymmetryDlg.cxx \
        SMESHGUI_SewingDlg.cxx \
        SMESHGUI_EditMeshDlg.cxx \
@@ -203,6 +205,7 @@ MOC_FILES = \
        SMESHGUI_RevolutionDlg_moc.cxx \
        SMESHGUI_RotationDlg_moc.cxx \
        SMESHGUI_TranslationDlg_moc.cxx \
+       SMESHGUI_ScaleDlg_moc.cxx \
        SMESHGUI_SymmetryDlg_moc.cxx \
        SMESHGUI_SewingDlg_moc.cxx \
        SMESHGUI_EditMeshDlg_moc.cxx \
index a57406e8cc04d1c26e3c1409d2fe8d978897c5b6..602de94d9113d8627de583d65dc5f973ed939954 100644 (file)
@@ -69,6 +69,7 @@
 #include "SMESHGUI_StandardMeshInfosDlg.h"
 #include "SMESHGUI_SymmetryDlg.h"
 #include "SMESHGUI_TranslationDlg.h"
+#include "SMESHGUI_ScaleDlg.h"
 #include "SMESHGUI_TransparencyDlg.h"
 #include "SMESHGUI_WhatIsDlg.h"
 
@@ -2632,6 +2633,20 @@ bool SMESHGUI::OnGUIEvent( int theCommandID )
     startOperation( 4067 );
     break;
 
+  case 4068: // SCALE
+    {
+      if(checkLock(aStudy)) break;
+      if ( vtkwnd ) {
+        EmitSignalDeactivateDialog();
+        ( new SMESHGUI_ScaleDlg( this ) )->show();
+      }
+      else {
+        SUIT_MessageBox::warning(SMESHGUI::desktop(),
+                                 tr("SMESH_WRN_WARNING"), tr("SMESH_WRN_VIEWER_VTK"));
+      }
+      break;
+    }
+
   case 5105: // Library of selection filters
   {
     static QList<int> aTypes;
@@ -2926,6 +2941,7 @@ void SMESHGUI::initialize( CAM_Application* app )
   createSMESHAction( 4065, "MERGE",           "ICON_SMESH_MERGE_NODES" );
   createSMESHAction( 4066, "MERGE_ELEMENTS",  "ICON_DLG_MERGE_ELEMENTS" );
   createSMESHAction( 4067, "MESH_THROU_POINT","ICON_DLG_MESH_THROU_POINT" );
+  createSMESHAction( 4068, "SCALE",           "ICON_DLG_MESH_SCALE" );
   createSMESHAction(  406, "MOVE",            "ICON_DLG_MOVE_NODE" );
   createSMESHAction(  407, "INV",             "ICON_DLG_MESH_DIAGONAL" );
   createSMESHAction(  408, "UNION2",          "ICON_UNION2TRI" );
@@ -3096,6 +3112,7 @@ void SMESHGUI::initialize( CAM_Application* app )
   createMenu( 4064, transfId, -1 );
   createMenu( 4065, transfId, -1 );
   createMenu( 4066, transfId, -1 );
+  createMenu( 4068, transfId, -1 );
 
   createMenu( 406, modifyId, -1 );
   createMenu( 4067,modifyId, -1 );
@@ -3194,6 +3211,7 @@ void SMESHGUI::initialize( CAM_Application* app )
   createTool( 4064, addRemTb );
   createTool( 4065, addRemTb );
   createTool( 4066, addRemTb );
+  createTool( 4068, addRemTb );
   createTool( separator(), addRemTb );
 
   createTool( 406, modifyTb );
diff --git a/src/SMESHGUI/SMESHGUI_ScaleDlg.cxx b/src/SMESHGUI/SMESHGUI_ScaleDlg.cxx
new file mode 100644 (file)
index 0000000..cec62dc
--- /dev/null
@@ -0,0 +1,1058 @@
+//  Copyright (C) 2007-2008  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_ScaleDlg.cxx
+// Author : Michael ZORIN, Open CASCADE S.A.S.
+// SMESH includes
+//
+#include "SMESHGUI_ScaleDlg.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 <SMESH_Actor.h>
+#include <SMESH_TypeFilter.hxx>
+#include <SMESH_LogicalFilter.hxx>
+#include <SMDS_Mesh.hxx>
+
+// SALOME GUI includes
+#include <SUIT_Desktop.h>
+#include <SUIT_ResourceMgr.h>
+#include <SUIT_Session.h>
+#include <SUIT_MessageBox.h>
+#include <SUIT_OverrideCursor.h>
+
+#include <LightApp_Application.h>
+#include <LightApp_SelectionMgr.h>
+
+#include <SVTK_ViewModel.h>
+#include <SVTK_ViewWindow.h>
+#include <SALOME_ListIO.hxx>
+
+// SALOME KERNEL includes
+#include <SALOMEDSClient_SObject.hxx>
+
+// OCCT includes
+#include <TColStd_MapOfInteger.hxx>
+
+// Qt includes
+#include <QApplication>
+#include <QButtonGroup>
+#include <QGroupBox>
+#include <QLabel>
+#include <QLineEdit>
+#include <QPushButton>
+#include <QRadioButton>
+#include <QCheckBox>
+#include <QHBoxLayout>
+#include <QVBoxLayout>
+#include <QGridLayout>
+#include <QSpinBox>
+#include <QKeyEvent>
+
+// IDL includes
+#include <SALOMEconfig.h>
+#include CORBA_SERVER_HEADER(SMESH_Group)
+#include CORBA_SERVER_HEADER(SMESH_MeshEditor)
+
+enum { MOVE_ELEMS_BUTTON = 0, COPY_ELEMS_BUTTON, MAKE_MESH_BUTTON }; //!< action type
+
+/*!
+  \class BusyLocker
+  \brief Simple 'busy state' flag locker.
+  \internal
+*/
+
+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
+
+//=================================================================================
+// class    : SMESHGUI_ScaleDlg()
+// purpose  :
+//=================================================================================
+SMESHGUI_ScaleDlg::SMESHGUI_ScaleDlg( SMESHGUI* theModule )
+  : QDialog( SMESH::GetDesktop( theModule ) ),
+    mySMESHGUI( theModule ),
+    mySelectionMgr( SMESH::GetSelectionMgr( theModule ) ),
+    myFilterDlg(0),
+    mySelectedObject(SMESH::SMESH_IDSource::_nil())
+{
+  QPixmap image0 (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_DLG_MESH_SCALE")));
+  QPixmap image1 (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_DLG_SCALE_ALONG_AXES")));
+  QPixmap image2 (SMESH::GetResourceMgr( mySMESHGUI )->loadPixmap("SMESH", tr("ICON_SELECT")));
+
+  setModal(false);
+  setAttribute(Qt::WA_DeleteOnClose, true);
+  setWindowTitle(tr("SMESH_SCALE_TITLE"));
+  setSizeGripEnabled(true);
+
+  QVBoxLayout* SMESHGUI_ScaleDlgLayout = new QVBoxLayout(this);
+  SMESHGUI_ScaleDlgLayout->setSpacing(SPACING);
+  SMESHGUI_ScaleDlgLayout->setMargin(MARGIN);
+
+  /***************************************************************/
+  ConstructorsBox = new QGroupBox(tr("SMESH_SCALE"), this);
+  GroupConstructors = new QButtonGroup(this);
+  QHBoxLayout* ConstructorsBoxLayout = new QHBoxLayout(ConstructorsBox);
+  ConstructorsBoxLayout->setSpacing(SPACING);
+  ConstructorsBoxLayout->setMargin(MARGIN);
+
+  RadioButton1= new QRadioButton(ConstructorsBox);
+  RadioButton1->setIcon(image0);
+  RadioButton2= new QRadioButton(ConstructorsBox);
+  RadioButton2->setIcon(image1);
+
+  ConstructorsBoxLayout->addWidget(RadioButton1);
+  ConstructorsBoxLayout->addWidget(RadioButton2);
+  GroupConstructors->addButton(RadioButton1, 0);
+  GroupConstructors->addButton(RadioButton2, 1);
+
+  /***************************************************************/
+  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 elements selection
+  TextLabelElements = new QLabel(tr("SMESH_ID_ELEMENTS"), GroupArguments);
+  SelectElementsButton = new QPushButton(GroupArguments);
+  SelectElementsButton->setIcon(image2);
+  LineEditElements = new QLineEdit(GroupArguments);
+  LineEditElements->setValidator(myIdValidator);
+  myFilterBtn = new QPushButton( tr( "SMESH_BUT_FILTER" ), GroupArguments );
+  connect(myFilterBtn,   SIGNAL(clicked()), this, SLOT(setFilters()));
+
+  // Control for the whole mesh selection
+  CheckBoxMesh = new QCheckBox(tr("SMESH_SELECT_WHOLE_MESH"), GroupArguments);
+
+  // Controls for vector and points selection
+  TextLabel1 = new QLabel(tr("SMESH_BASE_POINT"), GroupArguments);
+  SelectButton1 = new QPushButton(GroupArguments);
+  SelectButton1->setIcon(image2);
+
+  TextLabel1_1 = new QLabel(tr("SMESH_X"), GroupArguments);
+  SpinBox1_1 = new SMESHGUI_SpinBox(GroupArguments);
+  TextLabel1_2 = new QLabel(tr("SMESH_Y"), GroupArguments);
+  SpinBox1_2 = new SMESHGUI_SpinBox(GroupArguments);
+  TextLabel1_3 = new QLabel(tr("SMESH_Z"), GroupArguments);
+  SpinBox1_3 = new SMESHGUI_SpinBox(GroupArguments);
+
+  TextLabel2 = new QLabel(tr("SMESH_SCALE_FACTOR"), GroupArguments);
+  SpinBox_FX = new SMESHGUI_SpinBox(GroupArguments);
+
+  TextLabel3 = new QLabel(tr("SMESH_SCALE_FACTOR_Y"), GroupArguments);
+  SpinBox_FY = new SMESHGUI_SpinBox(GroupArguments);
+
+  TextLabel4 = new QLabel(tr("SMESH_SCALE_FACTOR_Z"), GroupArguments);
+  SpinBox_FZ = new SMESHGUI_SpinBox(GroupArguments);
+
+
+  // switch of action type
+  ActionBox = new QGroupBox(GroupArguments);
+  ActionGroup = new QButtonGroup(GroupArguments);
+  QVBoxLayout* ActionBoxLayout = new QVBoxLayout(ActionBox);
+  ActionBoxLayout->addSpacing(SPACING);
+  ActionBoxLayout->setMargin(MARGIN);
+
+  QRadioButton* aMoveElements = new QRadioButton(tr("SMESH_MOVE_ELEMENTS"), ActionBox);
+  QRadioButton* aCopyElements = new QRadioButton(tr("SMESH_COPY_ELEMENTS"), ActionBox);
+  QRadioButton* aCreateMesh   = new QRadioButton(tr("SMESH_CREATE_MESH"),   ActionBox);
+
+  ActionBoxLayout->addWidget(aMoveElements);
+  ActionBoxLayout->addWidget(aCopyElements);
+  ActionBoxLayout->addWidget(aCreateMesh);
+  ActionGroup->addButton(aMoveElements, MOVE_ELEMS_BUTTON);
+  ActionGroup->addButton(aCopyElements, COPY_ELEMS_BUTTON);
+  ActionGroup->addButton(aCreateMesh,   MAKE_MESH_BUTTON);
+
+  // CheckBox for groups generation
+  MakeGroupsCheck = new QCheckBox(tr("SMESH_MAKE_GROUPS"), GroupArguments);
+  MakeGroupsCheck->setChecked(false);
+
+  // Name of a mesh to create
+  LineEditNewMesh = new QLineEdit(GroupArguments);
+
+  // layout
+  GroupArgumentsLayout->addWidget(TextLabelElements,    0, 0);
+  GroupArgumentsLayout->addWidget(SelectElementsButton, 0, 1);
+  GroupArgumentsLayout->addWidget(LineEditElements,     0, 2, 1, 5);
+  GroupArgumentsLayout->addWidget(myFilterBtn,          0, 7);
+  GroupArgumentsLayout->addWidget(CheckBoxMesh,         1, 0, 1, 8);
+  GroupArgumentsLayout->addWidget(TextLabel1,           2, 0);
+  GroupArgumentsLayout->addWidget(SelectButton1,        2, 1);
+  GroupArgumentsLayout->addWidget(TextLabel1_1,         2, 2);
+  GroupArgumentsLayout->addWidget(SpinBox1_1,           2, 3);
+  GroupArgumentsLayout->addWidget(TextLabel1_2,         2, 4);
+  GroupArgumentsLayout->addWidget(SpinBox1_2,           2, 5);
+  GroupArgumentsLayout->addWidget(TextLabel1_3,         2, 6);
+  GroupArgumentsLayout->addWidget(SpinBox1_3,           2, 7);
+  GroupArgumentsLayout->addWidget(TextLabel2,           3, 0);
+  GroupArgumentsLayout->addWidget(SpinBox_FX,           3, 3);
+  GroupArgumentsLayout->addWidget(TextLabel3,           4, 0);
+  GroupArgumentsLayout->addWidget(SpinBox_FY,           4, 3);
+  GroupArgumentsLayout->addWidget(TextLabel4,           5, 0);
+  GroupArgumentsLayout->addWidget(SpinBox_FZ,           5, 3);
+  GroupArgumentsLayout->addWidget(ActionBox,            7, 0, 3, 4);
+  GroupArgumentsLayout->addWidget(MakeGroupsCheck,      7, 5, 1, 4);
+  GroupArgumentsLayout->addWidget(LineEditNewMesh,      8, 5, 1, 4);
+
+  /***************************************************************/
+  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_ScaleDlgLayout->addWidget(ConstructorsBox);
+  SMESHGUI_ScaleDlgLayout->addWidget(GroupArguments);
+  SMESHGUI_ScaleDlgLayout->addWidget(GroupButtons);
+
+  /* Initialisations */
+  SpinBox1_1->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, DBL_DIGITS_DISPLAY);
+  SpinBox1_2->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, DBL_DIGITS_DISPLAY);
+  SpinBox1_3->RangeStepAndValidator(COORD_MIN, COORD_MAX, 10.0, DBL_DIGITS_DISPLAY);
+  SpinBox_FX->RangeStepAndValidator(0.0, COORD_MAX, 1.0, DBL_DIGITS_DISPLAY);
+  SpinBox_FY->RangeStepAndValidator(0.0, COORD_MAX, 1.0, DBL_DIGITS_DISPLAY);
+  SpinBox_FZ->RangeStepAndValidator(0.0, COORD_MAX, 1.0, DBL_DIGITS_DISPLAY);
+
+  RadioButton1->setChecked(true);
+
+  mySelector = (SMESH::GetViewWindow( mySMESHGUI ))->GetSelector();
+
+  mySMESHGUI->SetActiveDialogBox((QDialog*)this);
+
+  // Costruction of the logical filter
+  SMESH_TypeFilter* aMeshOrSubMeshFilter = new SMESH_TypeFilter (MESHorSUBMESH);
+  SMESH_TypeFilter* aSmeshGroupFilter    = new SMESH_TypeFilter (GROUP);
+
+  QList<SUIT_SelectionFilter*> aListOfFilters;
+  if (aMeshOrSubMeshFilter) aListOfFilters.append(aMeshOrSubMeshFilter);
+  if (aSmeshGroupFilter)    aListOfFilters.append(aSmeshGroupFilter);
+
+  myMeshOrSubMeshOrGroupFilter =
+    new SMESH_LogicalFilter(aListOfFilters, SMESH_LogicalFilter::LO_OR);
+
+  myHelpFileName = "scale_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(GroupConstructors, SIGNAL(buttonClicked(int)), SLOT(ConstructorsClicked(int)));
+
+  connect(SelectElementsButton, SIGNAL (clicked()), this, SLOT(SetEditCurrentArgument()));
+  connect(SelectButton1,        SIGNAL (clicked()), this, SLOT(SetEditCurrentArgument()));
+
+  connect(mySMESHGUI, SIGNAL (SignalDeactivateActiveDialog()), this, SLOT(DeactivateActiveDialog()));
+  connect(mySelectionMgr, SIGNAL(currentSelectionChanged()),   this, SLOT(SelectionIntoArgument()));
+  /* to close dialog if study change */
+  connect(mySMESHGUI,       SIGNAL (SignalCloseAllDialogs()), this, SLOT(ClickOnCancel()));
+  connect(LineEditElements, SIGNAL(textChanged(const QString&)),    SLOT(onTextChange(const QString&)));
+  connect(CheckBoxMesh,     SIGNAL(toggled(bool)),                  SLOT(onSelectMesh(bool)));
+  connect(ActionGroup,      SIGNAL(buttonClicked(int)),             SLOT(onActionClicked(int)));
+
+  ConstructorsClicked(0);
+  SelectionIntoArgument();
+  onActionClicked(MOVE_ELEMS_BUTTON);
+}
+
+//=================================================================================
+// function : ~SMESHGUI_ScaleDlg()
+// purpose  : Destroys the object and frees any allocated resources
+//=================================================================================
+SMESHGUI_ScaleDlg::~SMESHGUI_ScaleDlg()
+{
+  if ( myFilterDlg ) {
+    myFilterDlg->setParent( 0 );
+    delete myFilterDlg;
+    myFilterDlg = 0;
+  }
+}
+
+//=================================================================================
+// function : Init()
+// purpose  :
+//=================================================================================
+void SMESHGUI_ScaleDlg::Init (bool ResetControls)
+{
+  myBusy = false;
+
+  myEditCurrentArgument = 0;
+  LineEditElements->clear();
+  myElementsId = "";
+  myNbOkElements = 0;
+
+  buttonOk->setEnabled(false);
+  buttonApply->setEnabled(false);
+
+  myActor = 0;
+  myMesh = SMESH::SMESH_Mesh::_nil();
+
+  if (ResetControls) {
+    SpinBox1_1->SetValue(0.0);
+    SpinBox1_2->SetValue(0.0);
+    SpinBox1_3->SetValue(0.0);
+    SpinBox_FX->SetValue(1.0);
+    SpinBox_FY->SetValue(1.0);
+    SpinBox_FZ->SetValue(1.0);
+
+    ActionGroup->button( MOVE_ELEMS_BUTTON )->setChecked(true);
+    CheckBoxMesh->setChecked(false);
+    onSelectMesh(false);
+  }
+}
+
+//=================================================================================
+// function : ConstructorsClicked()
+// purpose  : Radio button management
+//=================================================================================
+void SMESHGUI_ScaleDlg::ConstructorsClicked (int constructorId)
+{
+  disconnect(mySelectionMgr, 0, this, 0);
+
+  switch (constructorId) {
+  case 0:
+    {
+      TextLabel2->setText(tr("SMESH_SCALE_FACTOR"));
+      TextLabel3->hide();
+      TextLabel4->hide();
+      SpinBox_FY->hide();
+      SpinBox_FZ->hide();
+      break;
+    }
+  case 1:
+    {
+      TextLabel2->setText(tr("SMESH_SCALE_FACTOR_X"));
+      TextLabel3->show();
+      TextLabel4->show();
+      SpinBox_FY->show();
+      SpinBox_FZ->show();
+      break;
+    }
+  }
+
+  if (myEditCurrentArgument != (QWidget*)LineEditElements) {
+    SMESH::SetPointRepresentation(false);
+    if (!CheckBoxMesh->isChecked())
+      if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+        aViewWindow->SetSelectionMode( CellSelection );
+  }
+
+  myEditCurrentArgument = (QWidget*)LineEditElements;
+  LineEditElements->setFocus();
+
+  if (CheckBoxMesh->isChecked())
+    onSelectMesh(true);
+
+  connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
+
+  QApplication::instance()->processEvents();
+  updateGeometry();
+  resize(100,100);
+}
+
+//=================================================================================
+// function : ClickOnApply()
+// purpose  :
+//=================================================================================
+bool SMESHGUI_ScaleDlg::ClickOnApply()
+{
+  if (mySMESHGUI->isActiveStudyLocked())
+    return false;
+
+  if( !isValid() )
+    return false;
+
+  if (myNbOkElements) {
+    QStringList aListElementsId = myElementsId.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::PointStruct aPoint;
+    aPoint.x = SpinBox1_1->GetValue();
+    aPoint.y = SpinBox1_2->GetValue();
+    aPoint.z = SpinBox1_3->GetValue();
+    SMESH::double_array_var aScaleFact = new SMESH::double_array;
+    aScaleFact->length(3);
+    aScaleFact[0] = SpinBox_FX->GetValue();
+    if (GetConstructorId() == 0) {
+      aScaleFact[1] = SpinBox_FX->GetValue();
+      aScaleFact[2] = SpinBox_FX->GetValue();
+    }
+    else {
+      aScaleFact[1] = SpinBox_FY->GetValue();
+      aScaleFact[2] = SpinBox_FZ->GetValue();
+    }
+
+    QStringList aParameters;
+    aParameters << SpinBox1_1->text();
+    aParameters << SpinBox1_2->text();
+    aParameters << SpinBox1_3->text();
+    aParameters << SpinBox_FX->text();
+    if (GetConstructorId() == 1) {
+      aParameters << SpinBox_FX->text();
+      aParameters << SpinBox_FX->text();
+    }
+    else {
+      aParameters << SpinBox_FY->text();
+      aParameters << SpinBox_FZ->text();
+    }
+
+    int actionButton = ActionGroup->checkedId();
+    bool makeGroups = ( MakeGroupsCheck->isEnabled() && MakeGroupsCheck->isChecked() );
+    try {
+      SUIT_OverrideCursor aWaitCursor;
+      SMESH::SMESH_MeshEditor_var aMeshEditor = myMesh->GetMeshEditor();
+      switch ( actionButton ) {
+      case MOVE_ELEMS_BUTTON:
+        if(CheckBoxMesh->isChecked()) {
+          aMeshEditor->Scale(mySelectedObject, aPoint, aScaleFact, false);
+        }
+        else {
+          SMESH::SMESH_IDSource_ptr anObj = aMeshEditor->MakeIDSource(anElementsId);
+          aMeshEditor->Scale(anObj, aPoint, aScaleFact, false);
+        }
+        if( !myMesh->_is_nil())
+          myMesh->SetParameters( aParameters.join(":").toLatin1().constData() );
+        break;
+      case COPY_ELEMS_BUTTON:
+        if ( makeGroups ) {
+          SMESH::ListOfGroups_var groups; 
+          if(CheckBoxMesh->isChecked()) {
+            groups = aMeshEditor->ScaleMakeGroups(mySelectedObject, aPoint, aScaleFact);
+          }
+          else {
+            groups = aMeshEditor->ScaleMakeGroups(aMeshEditor->MakeIDSource(anElementsId),
+                                                  aPoint, aScaleFact);
+          }
+        }
+        else {
+          if(CheckBoxMesh->isChecked()) {
+            aMeshEditor->Scale(mySelectedObject, aPoint, aScaleFact, true);
+          }
+          else {
+            aMeshEditor->Scale(aMeshEditor->MakeIDSource(anElementsId),
+                               aPoint, aScaleFact, true);
+          }
+        }
+        if( !myMesh->_is_nil())
+          myMesh->SetParameters( aParameters.join(":").toLatin1().constData() );
+        break;
+      case MAKE_MESH_BUTTON:
+        SMESH::SMESH_Mesh_var mesh; 
+        if(CheckBoxMesh->isChecked()) {
+          mesh = aMeshEditor->ScaleMakeMesh(mySelectedObject, aPoint, aScaleFact, makeGroups,
+                                            LineEditNewMesh->text().toLatin1().data());
+        }
+        else {
+          mesh = aMeshEditor->ScaleMakeMesh(aMeshEditor->MakeIDSource(anElementsId),
+                                            aPoint, aScaleFact, makeGroups,
+                                            LineEditNewMesh->text().toLatin1().data());
+        }
+        if( !mesh->_is_nil())
+          mesh->SetParameters( aParameters.join(":").toLatin1().constData() );
+      }
+    } catch (...) {
+    }
+    
+    SMESH::UpdateView();
+    if ( MakeGroupsCheck->isEnabled() && MakeGroupsCheck->isChecked() ||
+         actionButton == MAKE_MESH_BUTTON )
+      mySMESHGUI->updateObjBrowser(true); // new groups may appear
+    Init(false);
+    ConstructorsClicked(GetConstructorId());
+    mySelectedObject = SMESH::SMESH_IDSource::_nil();
+    SelectionIntoArgument();
+  }
+  
+  return true;
+}
+
+//=================================================================================
+// function : ClickOnOk()
+// purpose  :
+//=================================================================================
+void SMESHGUI_ScaleDlg::ClickOnOk()
+{
+  if( ClickOnApply() )
+    ClickOnCancel();
+}
+
+//=================================================================================
+// function : ClickOnCancel()
+// purpose  :
+//=================================================================================
+void SMESHGUI_ScaleDlg::ClickOnCancel()
+{
+  disconnect(mySelectionMgr, 0, this, 0);
+  mySelectionMgr->clearFilters();
+  //mySelectionMgr->clearSelected();
+  if (SMESH::GetCurrentVtkView()) {
+    SMESH::RemoveFilters(); // PAL6938 -- clean all mesh entity filters
+    SMESH::SetPointRepresentation(false);
+  }
+  if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+    aViewWindow->SetSelectionMode( ActorSelection );
+  mySMESHGUI->ResetState();
+  reject();
+}
+
+//=================================================================================
+// function : ClickOnHelp()
+// purpose  :
+//=================================================================================
+void SMESHGUI_ScaleDlg::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_ScaleDlg::onTextChange (const QString& theNewText)
+{
+  QLineEdit* send = (QLineEdit*)sender();
+
+  if (myBusy) return;
+  BusyLocker lock( myBusy );
+
+  if (send == LineEditElements)
+    myNbOkElements = 0;
+
+  buttonOk->setEnabled(false);
+  buttonApply->setEnabled(false);
+
+  // hilight entered elements
+  SMDS_Mesh* aMesh = 0;
+  if (myActor)
+    aMesh = myActor->GetObject()->GetMesh();
+
+  if (aMesh) {
+    Handle(SALOME_InteractiveObject) anIO = myActor->getIO();
+    
+    TColStd_MapOfInteger newIndices;
+
+    QStringList aListId = theNewText.split(" ", QString::SkipEmptyParts);
+
+    if (send == LineEditElements) {
+      for (int i = 0; i < aListId.count(); i++) {
+        const SMDS_MeshElement * e = aMesh->FindElement(aListId[ i ].toInt());
+        if (e)
+          newIndices.Add(e->GetID());
+        myNbOkElements++;
+      }
+    }
+
+    mySelector->AddOrRemoveIndex( anIO, newIndices, false );
+    if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+      aViewWindow->highlight( anIO, true, true );
+    
+    myElementsId = theNewText;
+  }
+
+  if (myNbOkElements) {
+    buttonOk->setEnabled(true);
+    buttonApply->setEnabled(true);
+  }
+}
+
+//=================================================================================
+// function : SelectionIntoArgument()
+// purpose  : Called when selection as changed or other case
+//=================================================================================
+void SMESHGUI_ScaleDlg::SelectionIntoArgument()
+{
+  if (myBusy) return;
+  BusyLocker lock( myBusy );
+  // clear
+  myActor = 0;
+  QString aString = "";
+
+  if (myEditCurrentArgument == (QWidget*)LineEditElements) {
+    LineEditElements->setText(aString);
+    myNbOkElements = 0;
+    buttonOk->setEnabled(false);
+    buttonApply->setEnabled(false);
+  }
+
+  if (!GroupButtons->isEnabled()) // inactive
+    return;
+
+  // 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();
+  myMesh = SMESH::GetMeshByIO(IO);
+  if (myMesh->_is_nil())
+    return;
+
+  myActor = SMESH::FindActorByObject(myMesh);
+  if (!myActor)
+    myActor = SMESH::FindActorByEntry(IO->getEntry());
+  if (!myActor)
+    return;
+
+  int aNbUnits = 0;
+
+  if (myEditCurrentArgument == (QWidget*)LineEditElements) {
+    myElementsId = "";
+
+    // MakeGroups is available if there are groups and "Copy"
+    if ( myMesh->NbGroups() == 0 ) {
+      MakeGroupsCheck->setChecked(false);
+      MakeGroupsCheck->setEnabled(false);
+    }
+    else if ( ActionGroup->checkedId() != MOVE_ELEMS_BUTTON ) {
+      MakeGroupsCheck->setEnabled(true);
+    }
+
+    if (CheckBoxMesh->isChecked()) {
+      SMESH::GetNameOfSelectedIObjects( mySelectionMgr, aString );
+
+      if (!SMESH::IObjectToInterface<SMESH::SMESH_IDSource>(IO)->_is_nil()) { //MESH, SUBMESH, OR GROUP
+        mySelectedObject = SMESH::IObjectToInterface<SMESH::SMESH_IDSource>(IO);
+      }
+      else
+        return;
+        // get IDs from mesh
+        /*
+        SMDS_Mesh* aSMDSMesh = myActor->GetObject()->GetMesh();
+        if (!aSMDSMesh)
+          return;
+
+        for (int i = aSMDSMesh->MinElementID(); i <= aSMDSMesh->MaxElementID(); i++) {
+          const SMDS_MeshElement * e = aSMDSMesh->FindElement(i);
+          if (e) {
+            myElementsId += QString(" %1").arg(i);
+            aNbUnits++;
+          }
+        }
+      } else if (!SMESH::IObjectToInterface<SMESH::SMESH_subMesh>(IO)->_is_nil()) { //SUBMESH
+        // get submesh
+        SMESH::SMESH_subMesh_var aSubMesh = SMESH::IObjectToInterface<SMESH::SMESH_subMesh>(IO);
+
+        // get IDs from submesh
+        SMESH::long_array_var anElementsIds = new SMESH::long_array;
+        anElementsIds = aSubMesh->GetElementsId();
+        for (int i = 0; i < anElementsIds->length(); i++) {
+          myElementsId += QString(" %1").arg(anElementsIds[i]);
+        }
+        aNbUnits = anElementsIds->length();
+      } else { // GROUP
+        // get smesh group
+        SMESH::SMESH_GroupBase_var aGroup =
+          SMESH::IObjectToInterface<SMESH::SMESH_GroupBase>(IO);
+        if (aGroup->_is_nil())
+          return;
+
+        // get IDs from smesh group
+        SMESH::long_array_var anElementsIds = new SMESH::long_array;
+        anElementsIds = aGroup->GetListOfID();
+        for (int i = 0; i < anElementsIds->length(); i++) {
+          myElementsId += QString(" %1").arg(anElementsIds[i]);
+        }
+        aNbUnits = anElementsIds->length();
+      }
+        */
+    } else {
+      aNbUnits = SMESH::GetNameOfSelectedElements(mySelector, IO, aString);
+      myElementsId = aString;
+      if (aNbUnits < 1)
+        return;  
+    }
+
+    myNbOkElements = true;
+  } else {
+    aNbUnits = SMESH::GetNameOfSelectedNodes(mySelector, IO, aString);
+    if (aNbUnits != 1)
+      return;
+
+    SMDS_Mesh* aMesh =  myActor->GetObject()->GetMesh();
+    if (!aMesh)
+      return;
+
+    const SMDS_MeshNode * n = aMesh->FindNode(aString.toInt());
+    if (!n)
+      return;
+
+    double x = n->X();
+    double y = n->Y();
+    double z = n->Z();
+
+    if (myEditCurrentArgument == (QWidget*)SpinBox1_1) {
+      SpinBox1_1->SetValue(x);
+      SpinBox1_2->SetValue(y);
+      SpinBox1_3->SetValue(z);
+    }
+    else if (myEditCurrentArgument == (QWidget*)SpinBox_FX) {
+      SpinBox_FX->SetValue(x);
+      SpinBox_FY->SetValue(y);
+      SpinBox_FZ->SetValue(z);
+    }
+  }
+
+  if (myEditCurrentArgument == (QWidget*)LineEditElements) {
+    LineEditElements->setText(aString);
+    LineEditElements->repaint();
+    LineEditElements->setEnabled(false); // to fully update lineedit IPAL 19809
+    LineEditElements->setEnabled(true); 
+    setNewMeshName();
+  }
+
+  // OK
+  if (myNbOkElements) {
+    buttonOk->setEnabled(true);
+    buttonApply->setEnabled(true);
+  }
+}
+
+//=================================================================================
+// function : SetEditCurrentArgument()
+// purpose  :
+//=================================================================================
+void SMESHGUI_ScaleDlg::SetEditCurrentArgument()
+{
+  QPushButton* send = (QPushButton*)sender();
+
+  disconnect(mySelectionMgr, 0, this, 0);
+  mySelectionMgr->clearSelected();
+  mySelectionMgr->clearFilters();
+
+  if (send == SelectElementsButton) {
+    myEditCurrentArgument = (QWidget*)LineEditElements;
+    SMESH::SetPointRepresentation(false);
+    if (CheckBoxMesh->isChecked()) {
+      if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+        aViewWindow->SetSelectionMode( ActorSelection );
+      mySelectionMgr->installFilter(myMeshOrSubMeshOrGroupFilter);
+    }
+    else {
+      if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+        aViewWindow->SetSelectionMode( CellSelection );
+    }
+  }
+  else if (send == SelectButton1) {
+    myEditCurrentArgument = (QWidget*)SpinBox1_1;
+    SMESH::SetPointRepresentation(true);
+    if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+      aViewWindow->SetSelectionMode( NodeSelection );
+  }
+
+  myEditCurrentArgument->setFocus();
+  connect(mySelectionMgr, SIGNAL(currentSelectionChanged()), this, SLOT(SelectionIntoArgument()));
+  SelectionIntoArgument();
+}
+
+//=================================================================================
+// function : DeactivateActiveDialog()
+// purpose  :
+//=================================================================================
+void SMESHGUI_ScaleDlg::DeactivateActiveDialog()
+{
+  if (ConstructorsBox->isEnabled()) {
+    ConstructorsBox->setEnabled(false);
+    GroupArguments->setEnabled(false);
+    GroupButtons->setEnabled(false);
+    mySMESHGUI->ResetState();
+    mySMESHGUI->SetActiveDialogBox(0);
+  }
+}
+
+//=================================================================================
+// function : ActivateThisDialog()
+// purpose  :
+//=================================================================================
+void SMESHGUI_ScaleDlg::ActivateThisDialog()
+{
+  /* Emit a signal to deactivate the active dialog */
+  mySMESHGUI->EmitSignalDeactivateDialog();
+  ConstructorsBox->setEnabled(true);
+  GroupArguments->setEnabled(true);
+  GroupButtons->setEnabled(true);
+
+  mySMESHGUI->SetActiveDialogBox((QDialog*)this);
+
+  if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+    aViewWindow->SetSelectionMode( CellSelection );
+
+  SelectionIntoArgument();
+}
+
+//=================================================================================
+// function : enterEvent()
+// purpose  :
+//=================================================================================
+void SMESHGUI_ScaleDlg::enterEvent (QEvent*)
+{
+  if (!ConstructorsBox->isEnabled())
+    ActivateThisDialog();
+}
+
+//=================================================================================
+// function : closeEvent()
+// purpose  :
+//=================================================================================
+void SMESHGUI_ScaleDlg::closeEvent (QCloseEvent*)
+{
+  /* same than click on cancel button */
+  ClickOnCancel();
+}
+
+//=======================================================================
+//function : hideEvent
+//purpose  : caused by ESC key
+//=======================================================================
+void SMESHGUI_ScaleDlg::hideEvent (QHideEvent*)
+{
+  if (!isMinimized())
+    ClickOnCancel();
+}
+
+//=======================================================================
+//function : onSelectMesh
+//purpose  :
+//=======================================================================
+void SMESHGUI_ScaleDlg::onSelectMesh (bool toSelectMesh)
+{
+  if (toSelectMesh)
+    TextLabelElements->setText(tr("SMESH_NAME"));
+  else
+    TextLabelElements->setText(tr("SMESH_ID_ELEMENTS"));
+  myFilterBtn->setEnabled(!toSelectMesh);
+
+  if (myEditCurrentArgument != LineEditElements) {
+    LineEditElements->clear();
+    return;
+  }
+
+  mySelectionMgr->clearFilters();
+  SMESH::SetPointRepresentation(false);
+
+  if (toSelectMesh) {
+    if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+      aViewWindow->SetSelectionMode( ActorSelection );
+    mySelectionMgr->installFilter(myMeshOrSubMeshOrGroupFilter);
+    LineEditElements->setReadOnly(true);
+    LineEditElements->setValidator(0);
+  } else {
+    if ( SVTK_ViewWindow* aViewWindow = SMESH::GetViewWindow( mySMESHGUI ))
+      aViewWindow->SetSelectionMode( CellSelection );
+    LineEditElements->setReadOnly(false);
+    LineEditElements->setValidator(myIdValidator);
+    onTextChange(LineEditElements->text());
+  }
+
+  SelectionIntoArgument();
+}
+
+//=======================================================================
+//function : onActionClicked
+//purpose  : slot called when an action type changed
+//=======================================================================
+
+void SMESHGUI_ScaleDlg::onActionClicked(int button)
+{
+  switch ( button ) {
+  case MOVE_ELEMS_BUTTON:
+    MakeGroupsCheck->setEnabled(false);
+    LineEditNewMesh->setEnabled(false);
+    break;
+  case COPY_ELEMS_BUTTON:
+    LineEditNewMesh->setEnabled(false);
+    MakeGroupsCheck->setText( tr("SMESH_MAKE_GROUPS"));
+    if ( myMesh->_is_nil() || myMesh->NbGroups() > 0)
+      MakeGroupsCheck->setEnabled(true);
+    else
+      MakeGroupsCheck->setEnabled(false);
+    break;
+  case MAKE_MESH_BUTTON:
+    LineEditNewMesh->setEnabled(true);
+    MakeGroupsCheck->setText( tr("SMESH_COPY_GROUPS"));
+    if ( myMesh->_is_nil() || myMesh->NbGroups() > 0)
+      MakeGroupsCheck->setEnabled(true);
+    else
+      MakeGroupsCheck->setEnabled(false);
+    break;
+  }
+  setNewMeshName();
+}
+
+//=======================================================================
+//function : setNewMeshName
+//purpose  : update contents of LineEditNewMesh
+//=======================================================================
+
+void SMESHGUI_ScaleDlg::setNewMeshName()
+{
+  LineEditNewMesh->setText("");
+  if ( LineEditNewMesh->isEnabled() && !myMesh->_is_nil() ) {
+    QString name;
+    if ( CheckBoxMesh->isChecked() ) {
+      name = LineEditElements->text();
+    }
+    else {
+      _PTR(SObject) meshSO = SMESH::FindSObject( myMesh );
+      name = meshSO->GetName().c_str();
+    }
+    if ( !name.isEmpty() )
+      LineEditNewMesh->setText( SMESH::UniqueMeshName( name, "scaled"));
+  }
+}
+
+//=================================================================================
+// function : GetConstructorId()
+// purpose  :
+//=================================================================================
+int SMESHGUI_ScaleDlg::GetConstructorId()
+{
+  return GroupConstructors->checkedId();
+}
+
+//=================================================================================
+// function : keyPressEvent()
+// purpose  :
+//=================================================================================
+void SMESHGUI_ScaleDlg::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_ScaleDlg::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( LineEditElements );
+
+  myFilterDlg->show();
+}
+
+//=================================================================================
+// function : isValid
+// purpose  :
+//=================================================================================
+bool SMESHGUI_ScaleDlg::isValid()
+{
+  bool ok = true;
+  QString msg;
+
+  ok = SpinBox1_1->isValid( msg, true ) && ok;
+  ok = SpinBox1_2->isValid( msg, true ) && ok;
+  ok = SpinBox1_3->isValid( msg, true ) && ok;
+  ok = SpinBox_FX->isValid( msg, true ) && ok;
+  if (GetConstructorId() == 1) {
+    ok = SpinBox_FY->isValid( msg, true ) && ok;
+    ok = SpinBox_FZ->isValid( msg, true ) && ok;
+  }
+
+  if( !ok ) {
+    QString str( tr( "SMESH_INCORRECT_INPUT" ) );
+    if ( !msg.isEmpty() )
+      str += "\n" + msg;
+    SUIT_MessageBox::critical( this, tr( "SMESH_ERROR" ), str );
+    return false;
+  }
+  return true;
+}
diff --git a/src/SMESHGUI/SMESHGUI_ScaleDlg.h b/src/SMESHGUI/SMESHGUI_ScaleDlg.h
new file mode 100644 (file)
index 0000000..f9941a9
--- /dev/null
@@ -0,0 +1,149 @@
+//  Copyright (C) 2007-2008  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_ScaleDlg.h
+// Author : Sergey Kuul, Open CASCADE S.A.S.
+//
+#ifndef SMESHGUI_SCALEDLG_H
+#define SMESHGUI_SCALEDLG_H
+
+// SMESH includes
+#include "SMESH_SMESHGUI.hxx"
+
+// Qt includes
+#include <QDialog>
+
+// IDL includes
+#include <SALOMEconfig.h>
+#include CORBA_SERVER_HEADER(SMESH_Mesh)
+
+class QButtonGroup;
+class QGroupBox;
+class QLabel;
+class QLineEdit;
+class QPushButton;
+class QRadioButton;
+class QCheckBox;
+class SMESHGUI;
+class SMESHGUI_IdValidator;
+class SMESHGUI_SpinBox;
+class SMESHGUI_FilterDlg;
+class SMESH_Actor;
+class SVTK_Selector;
+class LightApp_SelectionMgr;
+class SMESH_LogicalFilter;
+
+//=================================================================================
+// class    : SMESHGUI_ScaleDlg
+// purpose  :
+//=================================================================================
+class SMESHGUI_EXPORT SMESHGUI_ScaleDlg : public QDialog
+{ 
+  Q_OBJECT
+
+public:
+  SMESHGUI_ScaleDlg( SMESHGUI* );
+  ~SMESHGUI_ScaleDlg();
+
+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 */
+  QString                myElementsId;
+  int                    myNbOkElements;          /* to check when elements are defined */
+
+  SVTK_Selector*         mySelector;
+
+  QWidget*               myEditCurrentArgument;
+
+  bool                   myBusy;
+  SMESH::SMESH_Mesh_var  myMesh;
+  SMESH_Actor*           myActor;
+  SMESH_LogicalFilter*   myMeshOrSubMeshOrGroupFilter;
+
+  SMESH::SMESH_IDSource_var mySelectedObject;
+
+  QGroupBox*             ConstructorsBox;
+  QButtonGroup*          GroupConstructors;
+  QRadioButton*          RadioButton1;
+  QRadioButton*          RadioButton2;
+  QGroupBox*             GroupButtons;
+  QPushButton*           buttonOk;
+  QPushButton*           buttonCancel;
+  QPushButton*           buttonApply;
+  QPushButton*           buttonHelp;
+  QGroupBox*             GroupArguments;
+  QLabel*                TextLabelElements;
+  QPushButton*           SelectElementsButton;
+  QLineEdit*             LineEditElements;
+  QCheckBox*             CheckBoxMesh;
+  QLabel*                TextLabel1;
+  QPushButton*           SelectButton1;
+  QLabel*                TextLabel1_1;
+  SMESHGUI_SpinBox*      SpinBox1_1;
+  QLabel*                TextLabel1_2;
+  SMESHGUI_SpinBox*      SpinBox1_2;
+  QLabel*                TextLabel1_3;
+  SMESHGUI_SpinBox*      SpinBox1_3;
+  QLabel*                TextLabel2;
+  SMESHGUI_SpinBox*      SpinBox_FX;
+  QLabel*                TextLabel3;
+  SMESHGUI_SpinBox*      SpinBox_FY;
+  QLabel*                TextLabel4;
+  SMESHGUI_SpinBox*      SpinBox_FZ;
+  QGroupBox*             ActionBox;
+  QButtonGroup*          ActionGroup;
+  QCheckBox*             MakeGroupsCheck;
+  QLineEdit*             LineEditNewMesh;
+
+  QString                myHelpFileName;
+
+  QPushButton*           myFilterBtn;
+  SMESHGUI_FilterDlg*    myFilterDlg;
+   
+private slots:
+  void                   ConstructorsClicked( int );
+  void                   ClickOnOk();
+  void                   ClickOnCancel();
+  bool                   ClickOnApply();
+  void                   ClickOnHelp();
+  void                   SetEditCurrentArgument();
+  void                   SelectionIntoArgument();
+  void                   DeactivateActiveDialog();
+  void                   ActivateThisDialog();
+  void                   onTextChange( const QString& );
+  void                   onSelectMesh( bool );
+  void                   onActionClicked( int );
+  void                   setFilters();
+};
+
+#endif // SMESHGUI_SCALEDLG_H
index 66f4131a81b5bd18b5f7a5254f614d13f1375c74..24ab4bea16d738daf89a6918bd65b445a06febb9 100644 (file)
             <source>ICON_SMESH_TRANSLATION_VECTOR</source>
             <translation>mesh_translation_vector.png</translation>
         </message>
+        <message>
+            <source>ICON_DLG_MESH_SCALE</source>
+            <translation>scale.png</translation>
+        </message>
+        <message>
+            <source>ICON_DLG_SCALE_ALONG_AXES</source>
+            <translation>scale_along_axes.png</translation>
+        </message>
         <message>
             <source>ICON_SMESH_TREE_ALGO</source>
             <translation>mesh_tree_algo.png</translation>
index f045800418ec0ace31f92dc5e956bd7fead62c9b..5aa706b4b80f4a03a25d086b9c5617832b3c1d46 100644 (file)
             <source>MEN_TRANS</source>
             <translation>Translation</translation>
         </message>
+        <message>
+            <source>MEN_SCALE</source>
+            <translation>Scale Transform</translation>
+        </message>
         <message>
             <source>MEN_TRANSF</source>
             <translation>Transformation</translation>
@@ -1715,6 +1719,10 @@ add the exported data to its contents?</translation>
             <source>SMESH_POINT_2</source>
             <translation>Point 2</translation>
         </message>
+        <message>
+            <source>SMESH_BASE_POINT</source>
+            <translation>Base Point</translation>
+        </message>
         <message>
             <source>SMESH_POLYEDRE_CREATE_ERROR</source>
             <translation>Polyedron creation error</translation>
@@ -1916,6 +1924,30 @@ add the exported data to its contents?</translation>
             <source>SMESH_TRANSLATION</source>
             <translation>Translation</translation>
         </message>
+        <message>
+            <source>SMESH_SCALE_TITLE</source>
+            <translation>Scale Transform</translation>
+        </message>
+        <message>
+            <source>SMESH_SCALE</source>
+            <translation>Scale</translation>
+        </message>
+        <message>
+            <source>SMESH_SCALE_FACTOR</source>
+            <translation>Scale Factor :</translation>
+        </message>
+        <message>
+            <source>SMESH_SCALE_FACTOR_X</source>
+            <translation>Scale Factor X :</translation>
+        </message>
+        <message>
+            <source>SMESH_SCALE_FACTOR_Y</source>
+            <translation>Scale Factor Y :</translation>
+        </message>
+        <message>
+            <source>SMESH_SCALE_FACTOR_Z</source>
+            <translation>Scale Factor Z :</translation>
+        </message>
         <message>
             <source>SMESH_TRANSPARENCY_OPAQUE</source>
             <translation>---> Opaque</translation>
@@ -2492,6 +2524,10 @@ Consider saving your work before application crash</translation>
             <source>STB_TRANS</source>
             <translation>Translation</translation>
         </message>
+        <message>
+            <source>STB_SCALE</source>
+            <translation>Scale Transform</translation>
+        </message>
         <message>
             <source>STB_TRANSP</source>
             <translation>Transparency</translation>
@@ -3002,6 +3038,10 @@ Consider saving your work before application crash</translation>
             <source>TOP_TRANS</source>
             <translation>Translation</translation>
         </message>
+        <message>
+            <source>TOP_SCALE</source>
+            <translation>Scale Transform</translation>
+        </message>
         <message>
             <source>TOP_TRANSP</source>
             <translation>Transparency</translation>
index 7ea5df70b9e997245db42cfb380f57f22b37d060..ac304fdf13b73228a5d6f574a1dafd44f1be8c51 100644 (file)
@@ -279,7 +279,7 @@ void SMESH_MeshEditor_i::initData(bool deleteSearchers)
 struct _IDSource : public POA_SMESH::SMESH_IDSource
 {
   SMESH::long_array _ids;
-  SMESH::long_array* GetIDs()      { return & _ids; }
+  SMESH::long_array* GetIDs()      { return new SMESH::long_array( _ids ); }
   SMESH::long_array* GetMeshInfo() { return 0; }
 };
 
@@ -3367,6 +3367,140 @@ SMESH_MeshEditor_i::RotateObjectMakeMesh(SMESH::SMESH_IDSource_ptr theObject,
   return mesh._retn();
 }
 
+
+//=======================================================================
+//function : scale
+//purpose  : 
+//=======================================================================
+
+SMESH::ListOfGroups*
+SMESH_MeshEditor_i::scale(const SMESH::long_array &  theIDsOfElements,
+                          const SMESH::PointStruct&  thePoint,
+                          const SMESH::double_array& theScaleFact,
+                          CORBA::Boolean             theCopy,
+                          const bool                 theMakeGroups,
+                          ::SMESH_Mesh*              theTargetMesh)
+{
+  initData();
+
+  TIDSortedElemSet elements;
+  arrayToSet(theIDsOfElements, GetMeshDS(), elements);
+
+  gp_Pnt aPnt( thePoint.x, thePoint.y, thePoint.z );
+  list<double> aScaleFact;
+  for (int i = 0; i < theScaleFact.length(); i++) {
+    aScaleFact.push_back( theScaleFact[i] );
+  }
+
+  ::SMESH_MeshEditor anEditor( myMesh );
+  ::SMESH_MeshEditor::PGroupIDs groupIds =
+      anEditor.Scale (elements, aPnt, aScaleFact, theCopy,
+                      theMakeGroups, theTargetMesh);
+
+  if(theCopy)
+    storeResult(anEditor);
+
+  return theMakeGroups ? getGroups(groupIds.get()) : 0;
+}
+
+
+//=======================================================================
+//function : Scale
+//purpose  :
+//=======================================================================
+
+void SMESH_MeshEditor_i::Scale(SMESH::SMESH_IDSource_ptr  theObject,
+                               const SMESH::PointStruct&  thePoint,
+                               const SMESH::double_array& theScaleFact,
+                               CORBA::Boolean             theCopy)
+{
+  if ( !myPreviewMode ) {
+    TPythonDump() << this << ".Scale( "
+                  << theObject << ", "
+                  << "SMESH.PointStruct( "  << thePoint.x << ", "
+                  << thePoint.y << ", " << thePoint.z << " ) ,"
+                  << theScaleFact << ", "
+                  << theCopy << " )";
+  }
+  SMESH::long_array_var anElementsId = theObject->GetIDs();
+  scale(anElementsId, thePoint, theScaleFact, theCopy, false);
+}
+
+
+//=======================================================================
+//function : ScaleMakeGroups
+//purpose  : 
+//=======================================================================
+
+SMESH::ListOfGroups*
+SMESH_MeshEditor_i::ScaleMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
+                                    const SMESH::PointStruct&  thePoint,
+                                    const SMESH::double_array& theScaleFact)
+{
+  SMESH::long_array_var anElementsId = theObject->GetIDs();
+  SMESH::ListOfGroups * aGroups = 
+    scale(anElementsId, thePoint, theScaleFact, true, true);
+
+  if ( !myPreviewMode ) {
+
+    TPythonDump aPythonDump;
+    DumpGroupsList(aPythonDump,aGroups);
+    aPythonDump << this << ".Scale("
+                << theObject << ","
+                << "SMESH.PointStruct(" <<thePoint.x << ","
+                << thePoint.y << "," << thePoint.z << "),"
+                << theScaleFact << ",True,True)";
+  }
+  return aGroups;
+}
+
+
+//=======================================================================
+//function : ScaleMakeMesh
+//purpose  : 
+//=======================================================================
+
+SMESH::SMESH_Mesh_ptr
+SMESH_MeshEditor_i::ScaleMakeMesh(SMESH::SMESH_IDSource_ptr  theObject,
+                                  const SMESH::PointStruct&  thePoint,
+                                  const SMESH::double_array& theScaleFact,
+                                  CORBA::Boolean             theCopyGroups,
+                                  const char*                theMeshName)
+{
+  SMESH_Mesh_i* mesh_i;
+  SMESH::SMESH_Mesh_var mesh;
+  { // open new scope to dump "MakeMesh" command
+    // and then "GetGroups" using SMESH_Mesh::GetGroups()
+
+    TPythonDump pydump; // to prevent dump at mesh creation
+    mesh = makeMesh( theMeshName );
+    mesh_i = SMESH::DownCast<SMESH_Mesh_i*>( mesh );
+
+    if ( mesh_i ) {
+      SMESH::long_array_var anElementsId = theObject->GetIDs();
+      scale(anElementsId, thePoint, theScaleFact,
+            false, theCopyGroups, & mesh_i->GetImpl());
+      mesh_i->CreateGroupServants();
+    }
+    if ( !myPreviewMode ) {
+      pydump << mesh << " = " << this << ".ScaleMakeMesh( "
+             << theObject << ", "
+             << "SMESH.PointStruct( "  << thePoint.x << ", "
+             << thePoint.y << ", " << thePoint.z << " ) ,"
+             << theScaleFact << ", "
+             << theCopyGroups << ", '"
+             << theMeshName << "' )";
+    }
+  }
+
+  //dump "GetGroups"
+  if(!myPreviewMode && mesh_i)
+    mesh_i->GetGroups();
+
+  return mesh._retn();
+}
+
+
 //=======================================================================
 //function : FindCoincidentNodes
 //purpose  :
index bf0a3540be2d404c289ca16d87c7dabfd15e33e7..c1a4f7b34bf9d6f20aadaab3d650a41775abf3c6 100644 (file)
@@ -426,6 +426,21 @@ public:
                                              CORBA::Boolean            CopyGroups,
                                              const char*               MeshName);
 
+  void Scale(SMESH::SMESH_IDSource_ptr  theObject,
+             const SMESH::PointStruct&  thePoint,
+             const SMESH::double_array& theScaleFact,
+             CORBA::Boolean             theCopy);
+
+  SMESH::ListOfGroups* ScaleMakeGroups(SMESH::SMESH_IDSource_ptr  theObject,
+                                       const SMESH::PointStruct&  thePoint,
+                                       const SMESH::double_array& theScaleFact);
+
+  SMESH::SMESH_Mesh_ptr ScaleMakeMesh(SMESH::SMESH_IDSource_ptr Object,
+                                      const SMESH::PointStruct& Point,
+                                      const SMESH::double_array& theScaleFact,
+                                      CORBA::Boolean            CopyGroups,
+                                      const char*               MeshName);
+
   void FindCoincidentNodes (CORBA::Double                  Tolerance,
                             SMESH::array_of_long_array_out GroupsOfNodes);
   void FindCoincidentNodesOnPart(SMESH::SMESH_IDSource_ptr      Object,
@@ -702,6 +717,13 @@ public:
                               const bool                MakeGroups,
                               ::SMESH_Mesh*             TargetMesh=0);
 
+  SMESH::ListOfGroups* scale(const SMESH::long_array &  theIDsOfElements,
+                             const SMESH::PointStruct&  thePoint,
+                             const SMESH::double_array& theScaleFact,
+                             CORBA::Boolean             theCopy,
+                             const bool                 theMakeGroups,
+                             ::SMESH_Mesh*              theTargetMesh=0);
+
   SMESH::SMESH_Mesh_ptr makeMesh(const char* theMeshName);
 
   void DumpGroupsList(SMESH::TPythonDump & theDumpPython, 
index c4f773d6c15a78db98c0e0b6d86e2babe766556d..fd890c1ba09b09bdac8daf9ded9e49b24489686b 100644 (file)
@@ -3271,6 +3271,51 @@ class Mesh:
         mesh.SetParameters(Parameters)
         return Mesh( self.smeshpyD, self.geompyD, mesh )
 
+
+
+    ## Scales the object
+    #  @param theObject - the object to translate (mesh, submesh, or group)
+    #  @param thePoint - base point for scale
+    #  @param theScaleFact - scale factors for axises
+    #  @param Copy - allows copying the translated elements
+    #  @param MakeGroups - forces the generation of new groups from existing
+    #                      ones (if Copy)
+    #  @return list of created groups (SMESH_GroupBase) if MakeGroups=True,
+    #          empty list otherwise
+    def Scale(self, theObject, thePoint, theScaleFact, Copy, MakeGroups=False):
+        if ( isinstance( theObject, Mesh )):
+            theObject = theObject.GetMesh()
+        if ( isinstance( theObject, list )):
+            theObject = self.editor.MakeIDSource(theObject)
+
+        thePoint, Parameters = ParsePointStruct(thePoint)
+        self.mesh.SetParameters(Parameters)
+
+        if Copy and MakeGroups:
+            return self.editor.ScaleMakeGroups(theObject, thePoint, theScaleFact)
+        self.editor.Scale(theObject, thePoint, theScaleFact, Copy)
+        return []
+
+    ## Creates a new mesh from the translated object
+    #  @param theObject - the object to translate (mesh, submesh, or group)
+    #  @param thePoint - base point for scale
+    #  @param theScaleFact - scale factors for axises
+    #  @param MakeGroups - forces the generation of new groups from existing ones
+    #  @param NewMeshName - the name of the newly created mesh
+    #  @return instance of Mesh class
+    def ScaleMakeMesh(self, theObject, thePoint, theScaleFact, MakeGroups=False, NewMeshName=""):
+        if (isinstance(theObject, Mesh)):
+            theObject = theObject.GetMesh()
+        if ( isinstance( theObject, list )):
+            theObject = self.editor.MakeIDSource(theObject)
+
+        mesh = self.editor.ScaleMakeMesh(theObject, thePoint, theScaleFact,
+                                         MakeGroups, NewMeshName)
+        #mesh.SetParameters(Parameters)
+        return Mesh( self.smeshpyD, self.geompyD, mesh )
+
+
+
     ## Rotates the elements
     #  @param IDsOfElements list of elements ids
     #  @param Axis the axis of rotation (AxisStruct or geom line)