From: skl Date: Wed, 3 Mar 2010 07:23:24 +0000 (+0000) Subject: Changes for bug 0020671. X-Git-Tag: V5_1_4a1~57 X-Git-Url: http://git.salome-platform.org/gitweb/?a=commitdiff_plain;h=0af7b3cb3da78759e382cf61a35e8de56a2f8170;p=modules%2Fsmesh.git Changes for bug 0020671. --- diff --git a/doc/salome/gui/SMESH/images/scale01.png b/doc/salome/gui/SMESH/images/scale01.png new file mode 100644 index 000000000..72ae775ff 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 index 000000000..9d6a5f30f 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 index 000000000..891ae8d17 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 index 000000000..a0428342a 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 index 000000000..2bd8219d2 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 index 000000000..8ee0923bd 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 index 000000000..2816bac4b 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 index 000000000..97990a868 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 index 000000000..008d2e321 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 index 000000000..99b65d72a 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 index 000000000..0880989cb 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 index 000000000..059fa97f4 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 index 000000000..b75f83c3c 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 index 000000000..4708be51f Binary files /dev/null and b/doc/salome/gui/SMESH/images/scaleres09.png differ diff --git a/doc/salome/gui/SMESH/input/modifying_meshes.doc b/doc/salome/gui/SMESH/input/modifying_meshes.doc index cf63ff5f4..2a396d3cd 100644 --- a/doc/salome/gui/SMESH/input/modifying_meshes.doc +++ b/doc/salome/gui/SMESH/input/modifying_meshes.doc @@ -18,6 +18,7 @@ elements of the mesh. its elements.
  • \subpage rotation_page "Rotate" by the indicated axis and angle the mesh or some of its elements.
  • +
  • \subpage scale_page "Scale Transform" the mesh or some of its elements.
  • Create a \subpage symmetry_page "symmetrical copy" of the mesh through a point or a vector of symmetry.
  • 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 index 000000000..4f77ce8ad --- /dev/null +++ b/doc/salome/gui/SMESH/input/scale.doc @@ -0,0 +1,132 @@ +/*! + +\page scale_page Scale + +\n This geometrical operation allows to scale in space your mesh +or some of its elements. + +To scale a mesh: + +
      +
    1. 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 + +
    2. + +
    3. +In the dialog: +
        +
      • specify the IDs of the translated elements: + +
          +
        • Select the whole mesh, submesh or group activating this +checkbox; or
        • +
        • choose mesh elements with the mouse in the 3D Viewer. It is +possible to select a whole area with a mouse frame; or
        • +
        • input the element IDs directly in ID Elements field. The selected elements will be highlighted in the +viewer; or
        • +
        • apply Filters. Set filter 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.
        • +
        +
      • + +
      • specify the base point for scale
      • + +
      • specify the scale factor
      • + +
      • specify the conditions of scale: +
          +
        • activate Move elements radio button to create the source +mesh (or elements) at the new location and erase it from the previous location;
        • +
        • activate Copy elements 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;
        • +
        • activate Create as new mesh 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);
        • +
        • activate Copy groups checkbox to copy the groups of elements of the source mesh to the newly created mesh.
        • +
        +
      • + + + +
      • Click \b Apply or Apply and Close button to confirm the operation.
      • +
    + + + +Examle of using: + +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 + + +
    See Also a sample TUI Script of a \ref tui_scale "Scale" operation. + + +*/ diff --git a/doc/salome/gui/SMESH/input/tui_transforming_meshes.doc b/doc/salome/gui/SMESH/input/tui_transforming_meshes.doc index 163afe0e4..1658e58c5 100644 --- a/doc/salome/gui/SMESH/input/tui_transforming_meshes.doc +++ b/doc/salome/gui/SMESH/input/tui_transforming_meshes.doc @@ -44,6 +44,37 @@ angle270 = 1.5 * math.pi mesh.Rotate([], axisXYZ, angle270, 1) \endcode +
    +\anchor tui_scale +

    Scale

    + +\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 +
    \anchor tui_symmetry

    Symmetry

    @@ -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 +*/ diff --git a/idl/SMESH_MeshEditor.idl b/idl/SMESH_MeshEditor.idl index eb2715b4e..49a786619 100644 --- a/idl/SMESH_MeshEditor.idl +++ b/idl/SMESH_MeshEditor.idl @@ -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, diff --git a/resources/Makefile.am b/resources/Makefile.am index 0b8807d71..1444dc111 100644 --- a/resources/Makefile.am +++ b/resources/Makefile.am @@ -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 index 000000000..d838d9f89 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 index 000000000..04a4ae0a8 Binary files /dev/null and b/resources/scale_along_axes.png differ diff --git a/src/SMESH/SMESH_MeshEditor.cxx b/src/SMESH/SMESH_MeshEditor.cxx index 9822c70ea..1032898a3 100644 --- a/src/SMESH/SMESH_MeshEditor.cxx +++ b/src/SMESH/SMESH_MeshEditor.cxx @@ -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& 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::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 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 poly_nodes (nbNodes); + int iNode = 0; + SMDS_ElemIteratorPtr itN = elem->nodesIterator(); + while (itN->more()) { + const SMDS_MeshNode* node = + static_cast(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( elem ); + if (!aPolyedre) { + MESSAGE("Warning: bad volumic element"); + continue; + } + + vector poly_nodes; + vector 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 nodes(nbNodes); + int iNode = 0; + SMDS_ElemIteratorPtr itN = elem->nodesIterator(); + while ( itN->more() ) { + const SMDS_MeshNode* node = + static_cast( 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 diff --git a/src/SMESH/SMESH_MeshEditor.hxx b/src/SMESH/SMESH_MeshEditor.hxx index 3c197b2ac..db3c262e1 100644 --- a/src/SMESH/SMESH_MeshEditor.hxx +++ b/src/SMESH/SMESH_MeshEditor.hxx @@ -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& theScaleFact, + const bool theCopy, + const bool theMakeGroups, + SMESH_Mesh* theTargetMesh=0); + typedef std::list< std::list< const SMDS_MeshNode* > > TListOfListOfNodes; void FindCoincidentNodes (std::set & theNodes, diff --git a/src/SMESHGUI/Makefile.am b/src/SMESHGUI/Makefile.am index 9f5eedcb2..e217ed97f 100644 --- a/src/SMESHGUI/Makefile.am +++ b/src/SMESHGUI/Makefile.am @@ -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 \ diff --git a/src/SMESHGUI/SMESHGUI.cxx b/src/SMESHGUI/SMESHGUI.cxx index a57406e8c..602de94d9 100644 --- a/src/SMESHGUI/SMESHGUI.cxx +++ b/src/SMESHGUI/SMESHGUI.cxx @@ -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 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 index 000000000..cec62dc86 --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_ScaleDlg.cxx @@ -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 +#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) + +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 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(IO)->_is_nil()) { //MESH, SUBMESH, OR GROUP + mySelectedObject = SMESH::IObjectToInterface(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(IO)->_is_nil()) { //SUBMESH + // get submesh + SMESH::SMESH_subMesh_var aSubMesh = SMESH::IObjectToInterface(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(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 index 000000000..f9941a99f --- /dev/null +++ b/src/SMESHGUI/SMESHGUI_ScaleDlg.h @@ -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 + +// IDL includes +#include +#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 diff --git a/src/SMESHGUI/SMESH_images.ts b/src/SMESHGUI/SMESH_images.ts index 66f4131a8..24ab4bea1 100644 --- a/src/SMESHGUI/SMESH_images.ts +++ b/src/SMESHGUI/SMESH_images.ts @@ -373,6 +373,14 @@ ICON_SMESH_TRANSLATION_VECTOR mesh_translation_vector.png + + ICON_DLG_MESH_SCALE + scale.png + + + ICON_DLG_SCALE_ALONG_AXES + scale_along_axes.png + ICON_SMESH_TREE_ALGO mesh_tree_algo.png diff --git a/src/SMESHGUI/SMESH_msg_en.ts b/src/SMESHGUI/SMESH_msg_en.ts index f04580041..5aa706b4b 100644 --- a/src/SMESHGUI/SMESH_msg_en.ts +++ b/src/SMESHGUI/SMESH_msg_en.ts @@ -642,6 +642,10 @@ MEN_TRANS Translation + + MEN_SCALE + Scale Transform + MEN_TRANSF Transformation @@ -1715,6 +1719,10 @@ add the exported data to its contents? SMESH_POINT_2 Point 2 + + SMESH_BASE_POINT + Base Point + SMESH_POLYEDRE_CREATE_ERROR Polyedron creation error @@ -1916,6 +1924,30 @@ add the exported data to its contents? SMESH_TRANSLATION Translation + + SMESH_SCALE_TITLE + Scale Transform + + + SMESH_SCALE + Scale + + + SMESH_SCALE_FACTOR + Scale Factor : + + + SMESH_SCALE_FACTOR_X + Scale Factor X : + + + SMESH_SCALE_FACTOR_Y + Scale Factor Y : + + + SMESH_SCALE_FACTOR_Z + Scale Factor Z : + SMESH_TRANSPARENCY_OPAQUE ---> Opaque @@ -2492,6 +2524,10 @@ Consider saving your work before application crash STB_TRANS Translation + + STB_SCALE + Scale Transform + STB_TRANSP Transparency @@ -3002,6 +3038,10 @@ Consider saving your work before application crash TOP_TRANS Translation + + TOP_SCALE + Scale Transform + TOP_TRANSP Transparency diff --git a/src/SMESH_I/SMESH_MeshEditor_i.cxx b/src/SMESH_I/SMESH_MeshEditor_i.cxx index 7ea5df70b..ac304fdf1 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.cxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.cxx @@ -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 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(" <( 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 : diff --git a/src/SMESH_I/SMESH_MeshEditor_i.hxx b/src/SMESH_I/SMESH_MeshEditor_i.hxx index bf0a3540b..c1a4f7b34 100644 --- a/src/SMESH_I/SMESH_MeshEditor_i.hxx +++ b/src/SMESH_I/SMESH_MeshEditor_i.hxx @@ -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, diff --git a/src/SMESH_SWIG/smeshDC.py b/src/SMESH_SWIG/smeshDC.py index c4f773d6c..fd890c1ba 100644 --- a/src/SMESH_SWIG/smeshDC.py +++ b/src/SMESH_SWIG/smeshDC.py @@ -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)