Salome HOME
0020749: EDF 1291 SMESH : Create 2D Mesh from 3D improvement
[modules/smesh.git] / src / SMESH / SMESH_MeshEditor.cxx
index caeb8a29517d9e033e732a849eb409d5d4501b53..580f7371671b744a162d158e7b074a394cd8b2a3 100644 (file)
 // Created   : Mon Apr 12 16:10:22 2004
 // Author    : Edward AGAPOV (eap)
 
-#define CHRONODEF
 #include "SMESH_MeshEditor.hxx"
 
 #include "SMDS_FaceOfNodes.hxx"
 #include "SMDS_VolumeTool.hxx"
 #include "SMDS_EdgePosition.hxx"
-#include "SMDS_PolyhedralVolumeOfNodes.hxx"
 #include "SMDS_FacePosition.hxx"
 #include "SMDS_SpacePosition.hxx"
-//#include "SMDS_QuadraticFaceOfNodes.hxx"
 #include "SMDS_MeshGroup.hxx"
 #include "SMDS_LinearEdge.hxx"
 #include "SMDS_Downward.hxx"
@@ -4683,7 +4680,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet &   theElements,
   list<SMESH_MeshEditor_PathPoint> fullList;
 
   const TopoDS_Shape& aS = theTrack->GetSubShape();
-  // Sub shape for the Pattern must be an Edge or Wire
+  // Sub-shape for the Pattern must be an Edge or Wire
   if( aS.ShapeType() == TopAbs_EDGE ) {
     aTrackEdge = TopoDS::Edge( aS );
     // the Edge must not be degenerated
@@ -4973,7 +4970,7 @@ SMESH_MeshEditor::ExtrusionAlongTrack (TIDSortedElemSet &   theElements,
     }
     fullList.push_back(PP1);
     
-  } // Sub shape for the Pattern must be an Edge or Wire
+  } // Sub-shape for the Pattern must be an Edge or Wire
   else if( aS.ShapeType() == TopAbs_EDGE ) {
     aTrackEdge = TopoDS::Edge( aS );
     // the Edge must not be degenerated
@@ -5599,6 +5596,7 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
 
   // Replicate or reverse elements
 
+  std::vector<int> iForw;
   for ( itElem = theElems.begin(); itElem != theElems.end(); itElem++ )
   {
     const SMDS_MeshElement* elem = *itElem;
@@ -5700,7 +5698,9 @@ SMESH_MeshEditor::Transform (TIDSortedElemSet & theElems,
 
     // Regular elements
 
-    const std::vector<int>& i = SMDS_MeshCell::reverseSmdsOrder( elem->GetEntityType() );
+    while ( iForw.size() < nbNodes ) iForw.push_back( iForw.size() );
+    const std::vector<int>& iRev = SMDS_MeshCell::reverseSmdsOrder( elem->GetEntityType() );
+    const std::vector<int>& i = needReverse ? iRev : iForw;
 
     // find transformed nodes
     vector<const SMDS_MeshNode*> nodes(nbNodes);
@@ -5817,9 +5817,9 @@ SMESH_MeshEditor::generateGroups(const SMESH_SequenceOfElemPtr& nodeGens,
           if ( resElem != sourceElem )
             resultElems.push_back( resElem );
       // do not generate element groups from node ones
-      if ( sourceElem->GetType() == SMDSAbs_Node &&
-           elems( iElem )->GetType() != SMDSAbs_Node )
-        continue;
+//      if ( sourceElem->GetType() == SMDSAbs_Node &&
+//           elems( iElem )->GetType() != SMDSAbs_Node )
+//        continue;
 
       // add resultElems to groups made by ones the sourceElem belongs to
       list< TOldNewGroup >::iterator gOldNew, gLast = groupsOldNew.end();
@@ -7145,15 +7145,13 @@ void SMESH_MeshEditor::MergeNodes (TListOfListOfNodes & theGroupsOfNodes)
           }
         }
         // BUG 0020185: end
-        iRepl[ nbRepl++ ] = iCur;
       }
       curNodes[ iCur ] = n;
       bool isUnique = nodeSet.insert( n ).second;
-      if ( isUnique ) {
+      if ( isUnique )
         uniqueNodes[ iUnique++ ] = n;
-        if ( nbRepl && iRepl[ nbRepl-1 ] == iCur )
-          --nbRepl; // n do not stick to a node of the elem
-      }
+      else
+        iRepl[ nbRepl++ ] = iCur;
       iCur++;
     }
 
@@ -9034,13 +9032,14 @@ int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh *   theSm,
 
     // get elem data needed to re-create it
     //
-    int id = elem->GetID();
-    int nbNodes = elem->NbNodes();
-    SMDSAbs_ElementType aType = elem->GetType();
+    const int id                        = elem->GetID();
+    const int nbNodes                   = elem->NbNodes();
+    const SMDSAbs_ElementType aType     = elem->GetType();
+    const SMDSAbs_EntityType  aGeomType = elem->GetEntityType();
     nodes.assign(elem->begin_nodes(), elem->end_nodes());
-    if ( elem->GetEntityType() == SMDSEntity_Polyhedra )
+    if ( aGeomType == SMDSEntity_Polyhedra )
       nbNodeInFaces = static_cast<const SMDS_VtkVolume* >( elem )->GetQuantities();
-    else if ( elem->GetEntityType() == SMDSEntity_Hexagonal_Prism )
+    else if ( aGeomType == SMDSEntity_Hexagonal_Prism )
       volumeToPolyhedron( elem, nodes, nbNodeInFaces );
 
     // remove a linear element
@@ -9073,7 +9072,7 @@ int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh *   theSm,
       }
     case SMDSAbs_Volume :
       {
-        switch( elem->GetEntityType() )
+        switch( aGeomType )
         {
         case SMDSEntity_Tetra:
           NewElem = theHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
@@ -9101,8 +9100,6 @@ int SMESH_MeshEditor::convertElemToQuadratic(SMESHDS_SubMesh *   theSm,
     if( NewElem )
       theSm->AddElement( NewElem );
   }
-//  if (!GetMeshDS()->isCompacted())
-//    GetMeshDS()->compactMesh();
   return nbElem;
 }
 
@@ -9201,8 +9198,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool theForce3d)
       switch ( type )
       {
       case SMDSEntity_Tetra:
-        NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2],
-                                      nodes[3], id, theForce3d );
+        NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d );
         break;
       case SMDSEntity_Hexa:
         NewVolume = aHelper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3],
@@ -9245,7 +9241,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool        theForce3d,
   if ( theElements.empty() ) return;
 
   // we believe that all theElements are of the same type
-  SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
+  const SMDSAbs_ElementType elemType = (*theElements.begin())->GetType();
   
   // get all nodes shared by theElements
   TIDSortedNodeSet allNodes;
@@ -9322,8 +9318,8 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool        theForce3d,
     if( elem->IsQuadratic() || elem->NbNodes() < 2 || elem->IsPoly() )
       continue;
 
-    int id = elem->GetID();
-    SMDSAbs_ElementType type = elem->GetType();
+    const int id                   = elem->GetID();
+    const SMDSAbs_ElementType type = elem->GetType();
     vector<const SMDS_MeshNode *> nodes ( elem->begin_nodes(), elem->end_nodes());
 
     if ( !smDS || !smDS->Contains( elem ))
@@ -9333,7 +9329,7 @@ void SMESH_MeshEditor::ConvertToQuadratic(const bool        theForce3d,
     SMDS_MeshElement * newElem = 0;
     switch( nodes.size() )
     {
-    case 4: // cases for most multiple element types go first (for optimization)
+    case 4: // cases for most frequently used element types go first (for optimization)
       if ( type == SMDSAbs_Volume )
         newElem = helper.AddVolume(nodes[0], nodes[1], nodes[2], nodes[3], id, theForce3d);
       else
@@ -10731,6 +10727,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
       //     and corresponding volume of this domain, for each shared face.
       //     a volume has a face shared by 2 domains if it has a neighbor which is not in is domain.
 
+      //MESSAGE("Domain " << idom);
       const TIDSortedElemSet& domain = theElems[idom];
       TIDSortedElemSet::const_iterator elemItr = domain.begin();
       for (; elemItr != domain.end(); ++elemItr)
@@ -10739,6 +10736,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
           if (!anElem)
             continue;
           int vtkId = anElem->getVtkId();
+          //MESSAGE("  vtkId " << vtkId << " smdsId " << anElem->GetID());
           int neighborsVtkIds[NBMAXNEIGHBORS];
           int downIds[NBMAXNEIGHBORS];
           unsigned char downTypes[NBMAXNEIGHBORS];
@@ -10756,6 +10754,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
                     {
                       faceDomains[face][idom] = vtkId; // volume associated to face in this domain
                       celldom[vtkId] = idom;
+                      //MESSAGE("       cell with a border " << vtkId << " domain " << idom);
                     }
                 }
             }
@@ -10771,6 +10770,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
 
   for (int idomain = 0; idomain < theElems.size(); idomain++)
     {
+      //MESSAGE("Domain " << idomain);
       const TIDSortedElemSet& domain = theElems[idomain];
       itface = faceDomains.begin();
       for (; itface != faceDomains.end(); ++itface)
@@ -10810,6 +10810,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
                     continue;
                   cellDomains[aCell][idomain] = vtkId;
                   celldom[vtkId] = idomain;
+                  //MESSAGE("       cell " << vtkId << " domain " << idomain);
                 }
             }
         }
@@ -10824,7 +10825,8 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
   //     the value is the ordered domain ids. (more than 4 domains not taken into account)
 
   std::map<std::vector<int>, std::vector<int> > edgesMultiDomains; // nodes of edge --> ordered domains
-  std::map<int, std::vector<int> > mutipleNodes; // nodes muti domains with domain order
+  std::map<int, std::vector<int> > mutipleNodes; // nodes multi domains with domain order
+  std::map<int, std::vector<int> > mutipleNodesToFace; // nodes multi domains with domain order to transform in Face (junction between 3 or more 2D domains)
 
   for (int idomain = 0; idomain < theElems.size(); idomain++)
     {
@@ -10894,76 +10896,89 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
               //MESSAGE("multiple Nodes detected on a shared face");
               int downId = itface->first.cellId;
               unsigned char cellType = itface->first.cellType;
-              int nbEdges = grid->getDownArray(cellType)->getNumberOfDownCells(downId);
-              const int *downEdgeIds = grid->getDownArray(cellType)->getDownCells(downId);
-              const unsigned char* edgeType = grid->getDownArray(cellType)->getDownTypes(downId);
-              for (int ie =0; ie < nbEdges; ie++)
+              // --- shared edge or shared face ?
+              if ((cellType == VTK_LINE) || (cellType == VTK_QUADRATIC_EDGE)) // shared edge (between two faces)
                 {
                   int nodes[3];
-                  int nbNodes = grid->getDownArray(edgeType[ie])->getNodes(downEdgeIds[ie], nodes);
-                  if (mutipleNodes.count(nodes[0]) && mutipleNodes.count(nodes[nbNodes-1]))
+                  int nbNodes = grid->getDownArray(cellType)->getNodes(downId, nodes);
+                  for (int i=0; i< nbNodes; i=i+nbNodes-1) // i=0 , i=nbNodes-1
+                    if (mutipleNodes.count(nodes[i]))
+                      if (!mutipleNodesToFace.count(nodes[i]))
+                        mutipleNodesToFace[nodes[i]] = mutipleNodes[nodes[i]];
+               }
+              else // shared face (between two volumes)
+                {
+                  int nbEdges = grid->getDownArray(cellType)->getNumberOfDownCells(downId);
+                  const int* downEdgeIds = grid->getDownArray(cellType)->getDownCells(downId);
+                  const unsigned char* edgeType = grid->getDownArray(cellType)->getDownTypes(downId);
+                  for (int ie =0; ie < nbEdges; ie++)
                     {
-                      vector<int> vn0 = mutipleNodes[nodes[0]];
-                      vector<int> vn1 = mutipleNodes[nodes[nbNodes - 1]];
-                      sort( vn0.begin(), vn0.end() );
-                      sort( vn1.begin(), vn1.end() );
-                      if (vn0 == vn1)
+                      int nodes[3];
+                      int nbNodes = grid->getDownArray(edgeType[ie])->getNodes(downEdgeIds[ie], nodes);
+                      if (mutipleNodes.count(nodes[0]) && mutipleNodes.count(nodes[nbNodes-1]))
                         {
-                          //MESSAGE(" detect edgesMultiDomains " << nodes[0] << " " << nodes[nbNodes - 1]);
-                          double *coords = grid->GetPoint(nodes[0]);
-                          gp_Pnt p0(coords[0], coords[1], coords[2]);
-                          coords = grid->GetPoint(nodes[nbNodes - 1]);
-                          gp_Pnt p1(coords[0], coords[1], coords[2]);
-                          gp_Pnt gref;
-                          int vtkVolIds[1000];  // an edge can belong to a lot of volumes
-                          map<int, SMDS_VtkVolume*> domvol; // domain --> a volume with the edge
-                          map<int, double> angleDom; // oriented angles between planes defined by edge and volume centers
-                          int nbvol = grid->GetParentVolumes(vtkVolIds, downEdgeIds[ie], edgeType[ie]);
-                          for (int id=0; id < vn0.size(); id++)
+                          vector<int> vn0 = mutipleNodes[nodes[0]];
+                          vector<int> vn1 = mutipleNodes[nodes[nbNodes - 1]];
+                          sort( vn0.begin(), vn0.end() );
+                          sort( vn1.begin(), vn1.end() );
+                          if (vn0 == vn1)
                             {
-                              int idom = vn0[id];
-                              for (int ivol=0; ivol<nbvol; ivol++)
+                              //MESSAGE(" detect edgesMultiDomains " << nodes[0] << " " << nodes[nbNodes - 1]);
+                              double *coords = grid->GetPoint(nodes[0]);
+                              gp_Pnt p0(coords[0], coords[1], coords[2]);
+                              coords = grid->GetPoint(nodes[nbNodes - 1]);
+                              gp_Pnt p1(coords[0], coords[1], coords[2]);
+                              gp_Pnt gref;
+                              int vtkVolIds[1000];  // an edge can belong to a lot of volumes
+                              map<int, SMDS_VtkVolume*> domvol; // domain --> a volume with the edge
+                              map<int, double> angleDom; // oriented angles between planes defined by edge and volume centers
+                              int nbvol = grid->GetParentVolumes(vtkVolIds, downEdgeIds[ie], edgeType[ie]);
+                              for (int id=0; id < vn0.size(); id++)
                                 {
-                                  int smdsId = meshDS->fromVtkToSmds(vtkVolIds[ivol]);
-                                  SMDS_MeshElement* elem = (SMDS_MeshElement*)meshDS->FindElement(smdsId);
-                                  if (theElems[idom].count(elem))
+                                  int idom = vn0[id];
+                                  for (int ivol=0; ivol<nbvol; ivol++)
                                     {
-                                      SMDS_VtkVolume* svol = dynamic_cast<SMDS_VtkVolume*>(elem);
-                                      domvol[idom] = svol;
-                                      //MESSAGE("  domain " << idom << " volume " << elem->GetID());
-                                      double values[3];
-                                      vtkIdType npts = 0;
-                                      vtkIdType* pts = 0;
-                                      grid->GetCellPoints(vtkVolIds[ivol], npts, pts);
-                                      SMDS_VtkVolume::gravityCenter(grid, pts, npts, values);
-                                      if (id ==0)
+                                      int smdsId = meshDS->fromVtkToSmds(vtkVolIds[ivol]);
+                                      SMDS_MeshElement* elem = (SMDS_MeshElement*)meshDS->FindElement(smdsId);
+                                      if (theElems[idom].count(elem))
                                         {
-                                          gref.SetXYZ(gp_XYZ(values[0], values[1], values[2]));
-                                          angleDom[idom] = 0;
+                                          SMDS_VtkVolume* svol = dynamic_cast<SMDS_VtkVolume*>(elem);
+                                          domvol[idom] = svol;
+                                          //MESSAGE("  domain " << idom << " volume " << elem->GetID());
+                                          double values[3];
+                                          vtkIdType npts = 0;
+                                          vtkIdType* pts = 0;
+                                          grid->GetCellPoints(vtkVolIds[ivol], npts, pts);
+                                          SMDS_VtkVolume::gravityCenter(grid, pts, npts, values);
+                                          if (id ==0)
+                                            {
+                                              gref.SetXYZ(gp_XYZ(values[0], values[1], values[2]));
+                                              angleDom[idom] = 0;
+                                            }
+                                          else
+                                            {
+                                              gp_Pnt g(values[0], values[1], values[2]);
+                                              angleDom[idom] = OrientedAngle(p0, p1, gref, g); // -pi<angle<+pi
+                                              //MESSAGE("  angle=" << angleDom[idom]);
+                                            }
+                                          break;
                                         }
-                                      else
-                                        {
-                                          gp_Pnt g(values[0], values[1], values[2]);
-                                          angleDom[idom] = OrientedAngle(p0, p1, gref, g); // -pi<angle<+pi
-                                          //MESSAGE("  angle=" << angleDom[idom]);
-                                        }
-                                      break;
                                     }
                                 }
+                              map<double, int> sortedDom; // sort domains by angle
+                              for (map<int, double>::iterator ia = angleDom.begin(); ia != angleDom.end(); ++ia)
+                                sortedDom[ia->second] = ia->first;
+                              vector<int> vnodes;
+                              vector<int> vdom;
+                              for (map<double, int>::iterator ib = sortedDom.begin(); ib != sortedDom.end(); ++ib)
+                                {
+                                  vdom.push_back(ib->second);
+                                  //MESSAGE("  ordered domain " << ib->second << "  angle " << ib->first);
+                                }
+                              for (int ino = 0; ino < nbNodes; ino++)
+                                vnodes.push_back(nodes[ino]);
+                              edgesMultiDomains[vnodes] = vdom; // nodes vector --> ordered domains
                             }
-                          map<double, int> sortedDom; // sort domains by angle
-                          for (map<int, double>::iterator ia = angleDom.begin(); ia != angleDom.end(); ++ia)
-                            sortedDom[ia->second] = ia->first;
-                          vector<int> vnodes;
-                          vector<int> vdom;
-                          for (map<double, int>::iterator ib = sortedDom.begin(); ib != sortedDom.end(); ++ib)
-                            {
-                              vdom.push_back(ib->second);
-                              //MESSAGE("  ordered domain " << ib->second << "  angle " << ib->first);
-                            }
-                          for (int ino = 0; ino < nbNodes; ino++)
-                            vnodes.push_back(nodes[ino]);
-                          edgesMultiDomains[vnodes] = vdom; // nodes vector --> ordered domains
                         }
                     }
                 }
@@ -10998,7 +11013,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
           int vtkVolId = itdom->second;
           itdom++;
           int dom2 = itdom->first;
-          SMDS_MeshVolume *vol = grid->extrudeVolumeFromFace(vtkVolId, dom1, dom2, oldNodes, nodeDomains,
+          SMDS_MeshCell *vol = grid->extrudeVolumeFromFace(vtkVolId, dom1, dom2, oldNodes, nodeDomains,
                                                              nodeQuadDomains);
           stringstream grpname;
           grpname << "j_";
@@ -11009,7 +11024,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
           int idg;
           string namegrp = grpname.str();
           if (!mapOfJunctionGroups.count(namegrp))
-            mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Volume, namegrp.c_str(), idg);
+            mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(vol->GetType(), namegrp.c_str(), idg);
           SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
           if (sgrp)
             sgrp->Add(vol->GetID());
@@ -11017,10 +11032,37 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
     }
 
   // --- create volumes on multiple domain intersection if requested
+  //     iterate on mutipleNodesToFace
   //     iterate on edgesMultiDomains
 
   if (createJointElems)
     {
+      // --- iterate on mutipleNodesToFace
+
+      std::map<int, std::vector<int> >::iterator itn =  mutipleNodesToFace.begin();
+      for (; itn != mutipleNodesToFace.end(); ++itn)
+        {
+          int node = itn->first;
+          vector<int> orderDom = itn->second;
+          vector<vtkIdType> orderedNodes;
+          for (int idom = 0; idom <orderDom.size(); idom++)
+            orderedNodes.push_back( nodeDomains[node][orderDom[idom]] );
+            SMDS_MeshFace* face = this->GetMeshDS()->AddFaceFromVtkIds(orderedNodes);
+
+            stringstream grpname;
+            grpname << "m2j_";
+            grpname << 0 << "_" << 0;
+            int idg;
+            string namegrp = grpname.str();
+            if (!mapOfJunctionGroups.count(namegrp))
+              mapOfJunctionGroups[namegrp] = this->myMesh->AddGroup(SMDSAbs_Face, namegrp.c_str(), idg);
+            SMESHDS_Group *sgrp = dynamic_cast<SMESHDS_Group*>(mapOfJunctionGroups[namegrp]->GetGroupDS());
+            if (sgrp)
+              sgrp->Add(face->GetID());
+        }
+
+      // --- iterate on edgesMultiDomains
+
       std::map<std::vector<int>, std::vector<int> >::iterator ite = edgesMultiDomains.begin();
       for (; ite != edgesMultiDomains.end(); ++ite)
         {
@@ -11052,7 +11094,7 @@ bool SMESH_MeshEditor::DoubleNodesOnGroupBoundaries( const std::vector<TIDSorted
             }
           else
             {
-              //MESSAGE("Quadratic multiple joints not implemented");
+              MESSAGE("Quadratic multiple joints not implemented");
               // TODO quadratic nodes
             }
         }
@@ -11417,6 +11459,8 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
   SMESH_MeshEditor tgtEditor2( tgtEditor.GetMesh() );
   presentEditor = toAddExistingBondary ? &tgtEditor : &tgtEditor2;
 
+  SMESH_MesherHelper helper( *myMesh );
+  const TopAbs_ShapeEnum missShapeType = ( missType==SMDSAbs_Face ? TopAbs_FACE : TopAbs_EDGE );
   SMDS_VolumeTool vTool;
   TIDSortedElemSet avoidSet;
   const TIDSortedElemSet emptySet, *elemSet = aroundElements ? &elements : &emptySet;
@@ -11550,8 +11594,37 @@ int SMESH_MeshEditor::MakeBoundaryMesh(const TIDSortedElemSet& elements,
                                                                    missType,
                                                                    /*noMedium=*/false))
           continue;
-        tgtEditor.AddElement(nodes, missType, !iQuad && nodes.size()/(iQuad+1)>4);
+        SMDS_MeshElement* elem = 
+          tgtEditor.AddElement(nodes, missType, !iQuad && nodes.size()/(iQuad+1)>4);
         ++nbAddedBnd;
+
+        // try to set a new element to a shape
+        if ( myMesh->HasShapeToMesh() )
+        {
+          bool ok = true;
+          set< pair<TopAbs_ShapeEnum, int > > mediumShapes;
+          const int nbN = nodes.size() / (iQuad+1 );
+          for ( inode = 0; inode < nbN && ok; ++inode )
+          {
+            pair<int, TopAbs_ShapeEnum> i_stype =
+              helper.GetMediumPos( nodes[inode], nodes[(inode+1)%nbN]);
+            if (( ok = ( i_stype.first > 0 && i_stype.second >= TopAbs_FACE )))
+              mediumShapes.insert( make_pair ( i_stype.second, i_stype.first ));
+          }
+          if ( ok && mediumShapes.size() > 1 )
+          {
+            set< pair<TopAbs_ShapeEnum, int > >::iterator stype_i = mediumShapes.begin();
+            pair<TopAbs_ShapeEnum, int> stype_i_0 = *stype_i;
+            for ( ++stype_i; stype_i != mediumShapes.end() && ok; ++stype_i )
+            {
+              if (( ok = ( stype_i->first != stype_i_0.first )))
+                ok = helper.IsSubShape( aMesh->IndexToShape( stype_i->second ),
+                                        aMesh->IndexToShape( stype_i_0.second ));
+            }
+          }
+          if ( ok && mediumShapes.begin()->first == missShapeType )
+            aMesh->SetMeshElementOnShape( elem, mediumShapes.begin()->second );
+        }
       }
 
     // ----------------------------------