Salome HOME
Merge branch 'master' into pre/penta18
[modules/smesh.git] / src / SMESH_I / SMESH_MeshEditor_i.cxx
index bd08f9d67785800357512b06fb0b24fe07213f70..9b79bead18dd32ccbf89e18eeda5d5c957cea472 100644 (file)
@@ -1,4 +1,4 @@
-// Copyright (C) 2007-2015  CEA/DEN, EDF R&D, OPEN CASCADE
+// Copyright (C) 2007-2016  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
@@ -184,7 +184,7 @@ namespace MeshEditor_I {
 
   //=============================================================================
   /*!
-   * \brief Deleter of theNodeSearcher at any compute event occured
+   * \brief Deleter of theNodeSearcher at any compute event occurred
    */
   //=============================================================================
 
@@ -467,9 +467,9 @@ void SMESH_MeshEditor_i::initData(bool deleteSearchers)
 //================================================================================
 /*!
  * \brief Increment mesh modif time and optionally record that the performed
- *        modification may influence futher mesh re-compute.
+ *        modification may influence further mesh re-compute.
  *  \param [in] isReComputeSafe - true if the modification does not influence
- *              futher mesh re-compute
+ *              further mesh re-compute
  */
 //================================================================================
 
@@ -501,7 +501,7 @@ void SMESH_MeshEditor_i::declareMeshModified( bool isReComputeSafe )
  * \brief Initialize and return myPreviewMesh
  *  \param previewElements - type of elements to show in preview
  *
- *  WARNING: call it once par a method!
+ *  WARNING: call it once per method!
  */
 //================================================================================
 
@@ -669,7 +669,7 @@ void SMESH_MeshEditor_i::ClearLastCreated() throw (SALOME::SALOME_Exception)
 
 //=======================================================================
 /*
- * Returns description of an error/warning occured during the last operation
+ * Returns description of an error/warning occurred during the last operation
  * WARNING: ComputeError.code >= 100 and no corresponding enum in IDL API
  */
 //=======================================================================
@@ -903,14 +903,19 @@ CORBA::Long SMESH_MeshEditor_i::AddNode(CORBA::Double x,CORBA::Double y, CORBA::
  */
 //=============================================================================
 
-CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long IDOfNode)
+CORBA::Long SMESH_MeshEditor_i::Add0DElement(CORBA::Long    IDOfNode,
+                                             CORBA::Boolean DuplicateElements)
   throw (SALOME::SALOME_Exception)
 {
   SMESH_TRY;
   initData();
 
   const SMDS_MeshNode* aNode = getMeshDS()->FindNode(IDOfNode);
-  SMDS_MeshElement* elem = getMeshDS()->Add0DElement(aNode);
+  SMDS_ElemIteratorPtr it0D = aNode->GetInverseElementIterator( SMDSAbs_0DElement );
+  
+  SMDS_MeshElement* elem = 0;
+  if ( DuplicateElements || !it0D->more() )
+    elem = getMeshDS()->Add0DElement(aNode);
 
   // Update Python script
   TPythonDump() << "elem0d = " << this << ".Add0DElement( " << IDOfNode <<" )";
@@ -1243,11 +1248,11 @@ CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_ar
 
 //=============================================================================
 //
-// \brief Create 0D elements on all nodes of the given object except those 
-//        nodes on which a 0D element already exists.
+// \brief Create 0D elements on all nodes of the given object.
 //  \param theObject object on whose nodes 0D elements will be created.
 //  \param theGroupName optional name of a group to add 0D elements created
 //         and/or found on nodes of \a theObject.
+//  \param DuplicateElements to add one more 0D element to a node or not.
 //  \return an object (a new group or a temporary SMESH_IDSource) holding
 //          ids of new and/or found 0D elements.
 //
@@ -1255,7 +1260,8 @@ CORBA::Long SMESH_MeshEditor_i::AddPolyhedralVolumeByFaces (const SMESH::long_ar
 
 SMESH::SMESH_IDSource_ptr
 SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObject,
-                                               const char*               theGroupName)
+                                               const char*               theGroupName,
+                                               CORBA::Boolean            theDuplicateElements)
   throw (SALOME::SALOME_Exception)
 {
   SMESH_TRY;
@@ -1266,7 +1272,7 @@ SMESH_MeshEditor_i::Create0DElementsOnAllNodes(SMESH::SMESH_IDSource_ptr theObje
 
   TIDSortedElemSet elements, elems0D;
   if ( idSourceToSet( theObject, getMeshDS(), elements, SMDSAbs_All, /*emptyIfIsMesh=*/1))
-    getEditor().Create0DElementsOnAllNodes( elements, elems0D );
+    getEditor().Create0DElementsOnAllNodes( elements, elems0D, theDuplicateElements );
 
   SMESH::long_array_var newElems = new SMESH::long_array;
   newElems->length( elems0D.size() );
@@ -2484,6 +2490,7 @@ namespace MeshEditor_I
     bool myIsExtrusionByNormal;
 
     static int makeFlags( CORBA::Boolean MakeGroups,
+                          CORBA::Boolean LinearVariation = false,
                           CORBA::Boolean ByAverageNormal = false,
                           CORBA::Boolean UseInputElemsOnly = false,
                           CORBA::Long    Flags = 0,
@@ -2492,18 +2499,24 @@ namespace MeshEditor_I
       if ( MakeGroups       ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS;
       if ( ByAverageNormal  ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BY_AVG_NORMAL;
       if ( UseInputElemsOnly) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_USE_INPUT_ELEMS_ONLY;
+      if ( LinearVariation  ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_SCALE_LINEAR_VARIATION;
       if ( MakeBoundary     ) Flags |= ::SMESH_MeshEditor::EXTRUSION_FLAG_BOUNDARY;
       return Flags;
     }
     // standard params
-    ExtrusionParams(const SMESH::DirStruct &  theDir,
-                    CORBA::Long               theNbOfSteps,
-                    CORBA::Boolean            theMakeGroups):
+    ExtrusionParams(const SMESH::DirStruct &    theDir,
+                    CORBA::Long                 theNbOfSteps,
+                    const SMESH::double_array & theScaleFactors,
+                    CORBA::Boolean              theLinearVariation,
+                    const SMESH::double_array & theBasePoint,
+                    CORBA::Boolean              theMakeGroups):
       ::SMESH_MeshEditor::ExtrusParam ( gp_Vec( theDir.PS.x,
                                                 theDir.PS.y,
                                                 theDir.PS.z ),
                                         theNbOfSteps,
-                                        makeFlags( theMakeGroups )),
+                                        toList( theScaleFactors ),
+                                        TBasePoint( theBasePoint ),
+                                        makeFlags( theMakeGroups, theLinearVariation )),
       myIsExtrusionByNormal( false )
     {
     }
@@ -2517,7 +2530,9 @@ namespace MeshEditor_I
                                                 theDir.PS.y,
                                                 theDir.PS.z ),
                                         theNbOfSteps,
-                                        makeFlags( theMakeGroups, false, false,
+                                        std::list<double>(),
+                                        0,
+                                        makeFlags( theMakeGroups, false, false, false,
                                                    theExtrFlags, false ),
                                         theSewTolerance ),
       myIsExtrusionByNormal( false )
@@ -2532,7 +2547,7 @@ namespace MeshEditor_I
                     CORBA::Boolean theMakeGroups ):
       ::SMESH_MeshEditor::ExtrusParam ( theStepSize, 
                                         theNbOfSteps,
-                                        makeFlags( theMakeGroups,
+                                        makeFlags( theMakeGroups, false,
                                                    theByAverageNormal, theUseInputElemsOnly ),
                                         theDim),
       myIsExtrusionByNormal( true )
@@ -2543,6 +2558,32 @@ namespace MeshEditor_I
     {
       Flags() &= ~(::SMESH_MeshEditor::EXTRUSION_FLAG_GROUPS);
     }
+
+  private:
+
+    static std::list<double> toList( const SMESH::double_array & theScaleFactors )
+    {
+      std::list<double> scales;
+      for ( CORBA::ULong i = 0; i < theScaleFactors.length(); ++i )
+        scales.push_back( theScaleFactors[i] );
+      return scales;
+    }
+
+    // structure used to convert SMESH::double_array to gp_XYZ*
+    struct TBasePoint
+    {
+      gp_XYZ *pp, p;
+      TBasePoint( const SMESH::double_array & theBasePoint )
+      {
+        pp = 0;
+        if ( theBasePoint.length() == 3 )
+        {
+          p.SetCoord( theBasePoint[0], theBasePoint[1], theBasePoint[2] );
+          pp = &p;
+        }
+      }
+      operator const gp_XYZ*() const { return pp; }
+    };
   };
 }
 
@@ -2566,13 +2607,17 @@ SMESH_MeshEditor_i::ExtrusionSweepObjects(const SMESH::ListOfIDSources & theNode
                                           const SMESH::ListOfIDSources & theFaces,
                                           const SMESH::DirStruct &       theStepVector,
                                           CORBA::Long                    theNbOfSteps,
+                                          const SMESH::double_array &    theScaleFactors,
+                                          CORBA::Boolean                 theLinearVariation,
+                                          const SMESH::double_array &    theBasePoint,
                                           CORBA::Boolean                 theToMakeGroups)
   throw (SALOME::SALOME_Exception)
 {
   SMESH_TRY;
   initData();
 
-  ExtrusionParams params( theStepVector, theNbOfSteps, theToMakeGroups );
+  ExtrusionParams params( theStepVector, theNbOfSteps, theScaleFactors,
+                          theLinearVariation, theBasePoint, theToMakeGroups );
 
   TIDSortedElemSet elemsNodes[2];
   for ( int i = 0, nb = theNodes.length(); i < nb; ++i ) {
@@ -2907,8 +2952,9 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the
   }
 
   if ( !myIsPreviewMode ) {
-    aPythonDump << "(" << aGroups << ", error) = "
-                << this << ".ExtrusionAlongPathObjects( "
+    if ( aGroups->length() > 0 ) aPythonDump << "(" << aGroups << ", error) = ";
+    else                         aPythonDump << "(_noGroups, error) = ";
+    aPythonDump << this << ".ExtrusionAlongPathObjects( "
                 << theNodes            << ", "
                 << theEdges            << ", "
                 << theFaces            << ", "
@@ -2916,13 +2962,13 @@ SMESH_MeshEditor_i::ExtrusionAlongPathObjects(const SMESH::ListOfIDSources & the
                 << thePathShape        << ", "
                 << theNodeStart        << ", "
                 << theHasAngles        << ", "
-                << theAngles           << ", "
+                << TVar( theAngles )   << ", "
                 << theLinearVariation  << ", "
                 << theHasRefPoint      << ", "
                 << "SMESH.PointStruct( "
-                << ( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
-                << ( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
-                << ( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
+                << TVar( theHasRefPoint ? theRefPoint.x : 0 ) << ", "
+                << TVar( theHasRefPoint ? theRefPoint.y : 0 ) << ", "
+                << TVar( theHasRefPoint ? theRefPoint.z : 0 ) << " ), "
                 << theMakeGroups       << " )";
   }
   else
@@ -3062,17 +3108,14 @@ SMESH_MeshEditor_i::mirror(TIDSortedElemSet &                  theElements,
   ::SMESH_MeshEditor::PGroupIDs groupIds =
       getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
 
-  if ( theCopy && !myIsPreviewMode)
+  if ( !myIsPreviewMode )
   {
     if ( theTargetMesh )
-    {
       theTargetMesh->GetMeshDS()->Modified();
-    }
     else
-    {
       declareMeshModified( /*isReComputeSafe=*/false );
-    }
   }
+
   return theMakeGroups ? getGroups(groupIds.get()) : 0;
 
   SMESH_CATCH( SMESH::throwCorbaException );
@@ -3329,16 +3372,12 @@ SMESH_MeshEditor_i::translate(TIDSortedElemSet        & theElements,
   ::SMESH_MeshEditor::PGroupIDs groupIds =
       getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
 
-  if ( theCopy && !myIsPreviewMode )
+  if ( !myIsPreviewMode )
   {
     if ( theTargetMesh )
-    {
       theTargetMesh->GetMeshDS()->Modified();
-    }
     else
-    {
       declareMeshModified( /*isReComputeSafe=*/false );
-    }
   }
 
   return theMakeGroups ? getGroups(groupIds.get()) : 0;
@@ -3586,7 +3625,7 @@ SMESH_MeshEditor_i::rotate(TIDSortedElemSet &        theElements,
   ::SMESH_MeshEditor::PGroupIDs groupIds =
       getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
 
-  if ( theCopy && !myIsPreviewMode)
+  if ( !myIsPreviewMode)
   {
     if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
     else                 declareMeshModified( /*isReComputeSafe=*/false );
@@ -3886,7 +3925,7 @@ SMESH_MeshEditor_i::scale(SMESH::SMESH_IDSource_ptr  theObject,
   ::SMESH_MeshEditor::PGroupIDs groupIds =
       getEditor().Transform (*workElements, aTrsf, theCopy, theMakeGroups, theTargetMesh);
 
-  if ( theCopy && !myIsPreviewMode )
+  if ( !myIsPreviewMode )
   {
     if ( theTargetMesh ) theTargetMesh->GetMeshDS()->Modified();
     else                 declareMeshModified( /*isReComputeSafe=*/false );
@@ -4113,7 +4152,8 @@ FindCoincidentNodesOnPartBut(SMESH::SMESH_IDSource_ptr      theObject,
 //=======================================================================
 
 void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfNodes,
-                                     const SMESH::ListOfIDSources&     NodesToKeep)
+                                     const SMESH::ListOfIDSources&     NodesToKeep,
+                                     CORBA::Boolean                    AvoidMakingHoles)
   throw (SALOME::SALOME_Exception)
 {
   SMESH_TRY;
@@ -4157,9 +4197,9 @@ void SMESH_MeshEditor_i::MergeNodes (const SMESH::array_of_long_array& GroupsOfN
     aTPythonDump << aNodeGroup;
   }
 
-  getEditor().MergeNodes( aListOfListOfNodes );
+  getEditor().MergeNodes( aListOfListOfNodes, AvoidMakingHoles );
 
-  aTPythonDump << "], " << NodesToKeep << ")";
+  aTPythonDump << "], " << NodesToKeep << ", " << AvoidMakingHoles << ")";
 
   declareMeshModified( /*isReComputeSafe=*/false );
 
@@ -4480,13 +4520,15 @@ SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementID
 {
   SMESH_TRY;
   SMESH::long_array_var res = new SMESH::long_array;
-  
-  SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
-  if ( types->length() == 1 && // a part contains only nodes or 0D elements
-       ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
-       type != types[0] ) // but search of elements of dim > 0
-    return res._retn();
 
+  if ( type != SMESH::NODE )
+  {
+    SMESH::array_of_ElementType_var types = elementIDs->GetTypes();
+    if ( types->length() == 1 && // a part contains only nodes or 0D elements
+         ( types[0] == SMESH::NODE || types[0] == SMESH::ELEM0D || types[0] == SMESH::BALL) &&
+         type != types[0] ) // but search of elements of dim > 0
+      return res._retn();
+  }
   if ( SMESH::DownCast<SMESH_Mesh_i*>( elementIDs )) // elementIDs is the whole mesh 
     return FindElementsByPoint( x,y,z, type );
 
@@ -4500,7 +4542,8 @@ SMESH_MeshEditor_i::FindAmongElementsByPoint(SMESH::SMESH_IDSource_ptr elementID
     SMESHDS_Mesh* meshDS = SMESH::DownCast<SMESH_Mesh_i*>( mesh )->GetImpl().GetMeshDS();
 
     if ( !idSourceToSet( elementIDs, meshDS, elements,
-                         SMDSAbs_ElementType(type), /*emptyIfIsMesh=*/true))
+                         ( type == SMESH::NODE ? SMDSAbs_All : (SMDSAbs_ElementType) type ),
+                         /*emptyIfIsMesh=*/true))
       return res._retn();
 
     typedef SMDS_SetIterator<const SMDS_MeshElement*, TIDSortedElemSet::const_iterator > TIter;
@@ -5068,7 +5111,6 @@ CORBA::Boolean SMESH_MeshEditor_i::ChangeElemNodes(CORBA::Long ide,
   TPythonDump() << "isDone = " << this << ".ChangeElemNodes( "
                 << ide << ", " << newIDs << " )";
 
-  MESSAGE("ChangeElementNodes");
   bool res = getMeshDS()->ChangeElementNodes( elem, & aNodes[0], nbn1+1 );
 
   declareMeshModified( /*isReComputeSafe=*/ !res );
@@ -5249,10 +5291,10 @@ void SMESH_MeshEditor_i::dumpGroupsList(TPythonDump &               theDumpPytho
 */
 //================================================================================
 
-string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
+std::string SMESH_MeshEditor_i::generateGroupName(const std::string& thePrefix)
 {
   SMESH::ListOfGroups_var groups = myMesh_i->GetGroups();
-  set<string> groupNames;
+  set<std::string> groupNames;
 
   // Get existing group names
   for (int i = 0, nbGroups = groups->length(); i < nbGroups; i++ ) {
@@ -5265,7 +5307,7 @@ string SMESH_MeshEditor_i::generateGroupName(const string& thePrefix)
   }
 
   // Find new name
-  string name = thePrefix;
+  std::string name = thePrefix;
   int index = 0;
 
   while (!groupNames.insert(name).second)
@@ -5573,8 +5615,8 @@ SMESH_MeshEditor_i::DoubleNodeGroupNew( SMESH::SMESH_GroupBase_ptr theNodes,
     // Create group with newly created nodes
     SMESH::long_array_var anIds = GetLastCreatedNodes();
     if (anIds->length() > 0) {
-      string anUnindexedName (theNodes->GetName());
-      string aNewName = generateGroupName(anUnindexedName + "_double");
+      std::string anUnindexedName (theNodes->GetName());
+      std::string aNewName = generateGroupName(anUnindexedName + "_double");
       aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
       aNewGroup->Add(anIds);
       pyDump << aNewGroup << " = ";
@@ -5672,8 +5714,8 @@ SMESH_MeshEditor_i::DoubleNodeGroupsNew( const SMESH::ListOfGroups& theNodes,
     // Create group with newly created nodes
     SMESH::long_array_var anIds = GetLastCreatedNodes();
     if (anIds->length() > 0) {
-      string anUnindexedName (theNodes[0]->GetName());
-      string aNewName = generateGroupName(anUnindexedName + "_double");
+      std::string anUnindexedName (theNodes[0]->GetName());
+      std::string aNewName = generateGroupName(anUnindexedName + "_double");
       aNewGroup = myMesh_i->CreateGroup(SMESH::NODE, aNewName.c_str());
       aNewGroup->Add(anIds);
       pyDump << aNewGroup << " = ";
@@ -5897,7 +5939,7 @@ SMESH_MeshEditor_i::DoubleNodeElemGroup2New(SMESH::SMESH_GroupBase_ptr theElems,
   {
     // Create group with newly created elements
     CORBA::String_var elemGroupName = theElems->GetName();
-    string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
+    std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
     if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
     {
       SMESH::long_array_var anIds = GetLastCreatedElems();
@@ -6129,7 +6171,7 @@ SMESH_MeshEditor_i::DoubleNodeElemGroups2New(const SMESH::ListOfGroups& theElems
   {
     // Create group with newly created elements
     CORBA::String_var elemGroupName = theElems[0]->GetName();
-    string aNewName = generateGroupName( string(elemGroupName.in()) + "_double");
+    std::string aNewName = generateGroupName( std::string(elemGroupName.in()) + "_double");
     if ( !getEditor().GetLastCreatedElems().IsEmpty() && theElemGroupNeeded )
     {
       SMESH::long_array_var anIds = GetLastCreatedElems();
@@ -6231,7 +6273,6 @@ SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theEl
   throw (SALOME::SALOME_Exception)
 {
   SMESH_TRY;
-  MESSAGE("AffectedElemGroupsInRegion");
   SMESH::ListOfGroups_var aListOfGroups = new SMESH::ListOfGroups();
   bool isEdgeGroup = false;
   bool isFaceGroup = false;
@@ -6260,7 +6301,6 @@ SMESH_MeshEditor_i::AffectedElemGroupsInRegion( const SMESH::ListOfGroups& theEl
   if (aResult)
   {
     int lg = anAffected.size();
-    MESSAGE("lg="<< lg);
     SMESH::long_array_var volumeIds = new SMESH::long_array;
     volumeIds->length(lg);
     SMESH::long_array_var faceIds = new SMESH::long_array;
@@ -6609,7 +6649,7 @@ SMESH_MeshEditor_i::MakeBoundaryMesh(SMESH::SMESH_IDSource_ptr idSource,
   else
     pyDump << mesh_var << ", ";
   if ( group_var->_is_nil() )
-    pyDump << "_NoneGroup = "; // assignment to None is forbiden
+    pyDump << "_NoneGroup = "; // assignment to None is forbidden
   else
     pyDump << group_var << " = ";
   pyDump << this << ".MakeBoundaryMesh( "
@@ -6673,7 +6713,7 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
     else
       groupsOfThisMesh[ nbGroups++ ] = groups[i];
     if ( SMESH::DownCast<SMESH_Mesh_i*>( groups[i] ))
-      THROW_SALOME_CORBA_EXCEPTION("expect a group but recieve a mesh", SALOME::BAD_PARAM);
+      THROW_SALOME_CORBA_EXCEPTION("expected a group but received a mesh", SALOME::BAD_PARAM);
   }
   groupsOfThisMesh->length( nbGroups );
   groupsOfOtherMesh->length( nbGroupsOfOtherMesh );
@@ -6767,7 +6807,7 @@ CORBA::Long SMESH_MeshEditor_i::MakeBoundaryElements(SMESH::Bnd_Dimension dim,
   else
     pyDump << mesh_var << ", ";
   if ( group_var->_is_nil() )
-    pyDump << "_NoneGroup = "; // assignment to None is forbiden
+    pyDump << "_NoneGroup = "; // assignment to None is forbidden
   else
     pyDump << group_var << " = ";
   pyDump << this << ".MakeBoundaryElements( "