Salome HOME
debugging session
[modules/med.git] / src / MEDCoupling / MEDCouplingUMesh.cxx
1 // Copyright (C) 2007-2013  CEA/DEN, EDF R&D
2 //
3 // This library is free software; you can redistribute it and/or
4 // modify it under the terms of the GNU Lesser General Public
5 // License as published by the Free Software Foundation; either
6 // version 2.1 of the License.
7 //
8 // This library is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
11 // Lesser General Public License for more details.
12 //
13 // You should have received a copy of the GNU Lesser General Public
14 // License along with this library; if not, write to the Free Software
15 // Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
16 //
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
18 //
19 // Author : Anthony Geay (CEA/DEN)
20
21 #include "MEDCouplingUMesh.hxx"
22 #include "MEDCoupling1GTUMesh.hxx"
23 #include "MEDCouplingMemArray.txx"
24 #include "MEDCouplingFieldDouble.hxx"
25 #include "CellModel.hxx"
26 #include "VolSurfUser.txx"
27 #include "InterpolationUtils.hxx"
28 #include "PointLocatorAlgos.txx"
29 #include "BBTree.txx"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMeshQuality.hxx"
34 #include "InterpKernelCellSimplify.hxx"
35 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
36 #include "MEDCouplingAutoRefCountObjectPtr.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
42
43 #include <sstream>
44 #include <fstream>
45 #include <numeric>
46 #include <cstring>
47 #include <limits>
48 #include <list>
49
50 using namespace ParaMEDMEM;
51
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
53
54 const INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::MEDMEM_ORDER[N_MEDMEM_ORDER] = { INTERP_KERNEL::NORM_POINT1, INTERP_KERNEL::NORM_SEG2, INTERP_KERNEL::NORM_SEG3, INTERP_KERNEL::NORM_SEG4, INTERP_KERNEL::NORM_POLYL, INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_TRI7, INTERP_KERNEL::NORM_QUAD8, INTERP_KERNEL::NORM_QUAD9, INTERP_KERNEL::NORM_POLYGON, INTERP_KERNEL::NORM_QPOLYG, INTERP_KERNEL::NORM_TETRA4, INTERP_KERNEL::NORM_PYRA5, INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXA8, INTERP_KERNEL::NORM_HEXGP12, INTERP_KERNEL::NORM_TETRA10, INTERP_KERNEL::NORM_PYRA13, INTERP_KERNEL::NORM_PENTA15, INTERP_KERNEL::NORM_HEXA20, INTERP_KERNEL::NORM_HEXA27, INTERP_KERNEL::NORM_POLYHED };
55
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
57 {
58   return new MEDCouplingUMesh;
59 }
60
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const char *meshName, int meshDim)
62 {
63   MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64   ret->setName(meshName);
65   ret->setMeshDimension(meshDim);
66   return ret;
67 }
68
69 /*!
70  * Returns a new MEDCouplingMesh which is a full copy of \a this one. No data is shared
71  * between \a this and the new mesh.
72  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
73  *          delete this mesh using decrRef() as it is no more needed. 
74  */
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
76 {
77   return clone(true);
78 }
79
80 /*!
81  * Returns a new MEDCouplingMesh which is a copy of \a this one.
82  *  \param [in] recDeepCpy - if \a true, the copy is deep, else all data arrays of \a
83  * this mesh are shared by the new mesh.
84  *  \return MEDCouplingMesh * - a new instance of MEDCouplingMesh. The caller is to
85  *          delete this mesh using decrRef() as it is no more needed. 
86  */
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
88 {
89   return new MEDCouplingUMesh(*this,recDeepCpy);
90 }
91
92 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other) throw(INTERP_KERNEL::Exception)
93 {
94   if(!other)
95     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
96   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
97   if(!otherC)
98     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
99   MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
100   setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
101 }
102
103 std::size_t MEDCouplingUMesh::getHeapMemorySize() const
104 {
105   std::size_t ret=0;
106   if(_nodal_connec)
107     ret+=_nodal_connec->getHeapMemorySize();
108   if(_nodal_connec_index)
109     ret+=_nodal_connec_index->getHeapMemorySize();
110   return MEDCouplingPointSet::getHeapMemorySize()+ret;
111 }
112
113 void MEDCouplingUMesh::updateTime() const
114 {
115   MEDCouplingPointSet::updateTime();
116   if(_nodal_connec)
117     {
118       updateTimeWith(*_nodal_connec);
119     }
120   if(_nodal_connec_index)
121     {
122       updateTimeWith(*_nodal_connec_index);
123     }
124 }
125
126 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
127 {
128 }
129
130 /*!
131  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
132  * then \a this mesh is most probably is writable, exchangeable and available for most
133  * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
134  * this method to check that all is in order with \a this mesh.
135  *  \throw If the mesh dimension is not set.
136  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
137  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
138  *  \throw If the connectivity data array has more than one component.
139  *  \throw If the connectivity data array has a named component.
140  *  \throw If the connectivity index data array has more than one component.
141  *  \throw If the connectivity index data array has a named component.
142  */
143 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
144 {
145   if(_mesh_dim<-1)
146    throw INTERP_KERNEL::Exception("No mesh dimension specified !");
147   if(_mesh_dim!=-1)
148     MEDCouplingPointSet::checkCoherency();
149   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
150     {
151       if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
152         {
153           std::ostringstream message;
154           message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
155           throw INTERP_KERNEL::Exception(message.str().c_str());
156         }
157     }
158   if(_nodal_connec)
159     {
160       if(_nodal_connec->getNumberOfComponents()!=1)
161         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
162       if(_nodal_connec->getInfoOnComponent(0)!="")
163         throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
164     }
165   else
166     if(_mesh_dim!=-1)
167       throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
168   if(_nodal_connec_index)
169     {
170       if(_nodal_connec_index->getNumberOfComponents()!=1)
171         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
172       if(_nodal_connec_index->getInfoOnComponent(0)!="")
173         throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
174     }
175   else
176     if(_mesh_dim!=-1)
177       throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
178 }
179
180 /*!
181  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
182  * then \a this mesh is most probably is writable, exchangeable and available for all
183  * algorithms. <br> In addition to the checks performed by checkCoherency(), this
184  * method thoroughly checks the nodal connectivity.
185  *  \param [in] eps - a not used parameter.
186  *  \throw If the mesh dimension is not set.
187  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
188  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
189  *  \throw If the connectivity data array has more than one component.
190  *  \throw If the connectivity data array has a named component.
191  *  \throw If the connectivity index data array has more than one component.
192  *  \throw If the connectivity index data array has a named component.
193  *  \throw If number of nodes defining an element does not correspond to the type of element.
194  *  \throw If the nodal connectivity includes an invalid node id.
195  */
196 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
197 {
198   checkCoherency();
199   if(_mesh_dim==-1)
200     return ;
201   int meshDim=getMeshDimension();
202   int nbOfNodes=getNumberOfNodes();
203   int nbOfCells=getNumberOfCells();
204   const int *ptr=_nodal_connec->getConstPointer();
205   const int *ptrI=_nodal_connec_index->getConstPointer();
206   for(int i=0;i<nbOfCells;i++)
207     {
208       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
209       if((int)cm.getDimension()!=meshDim)
210         {
211           std::ostringstream oss;
212           oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
213           throw INTERP_KERNEL::Exception(oss.str().c_str());
214         }
215       int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
216       if(!cm.isDynamic())
217         if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
218           {
219             std::ostringstream oss;
220             oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " <<  cm.getNumberOfNodes();
221             oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
222             throw INTERP_KERNEL::Exception(oss.str().c_str());
223           }
224       for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
225         {
226           int nodeId=*w;
227           if(nodeId>=0)
228             {
229               if(nodeId>=nbOfNodes)
230                 {
231                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
232                   throw INTERP_KERNEL::Exception(oss.str().c_str());
233                 }
234             }
235           else if(nodeId<-1)
236             {
237               std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
238               throw INTERP_KERNEL::Exception(oss.str().c_str());
239             }
240           else
241             {
242               if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
243                 {
244                   std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
245                   throw INTERP_KERNEL::Exception(oss.str().c_str());
246                 }
247             }
248         }
249     }
250 }
251
252
253 /*!
254  * Checks if \a this mesh is well defined. If no exception is thrown by this method,
255  * then \a this mesh is most probably is writable, exchangeable and available for all
256  * algorithms. <br> This method performs the same checks as checkCoherency1() does. 
257  *  \param [in] eps - a not used parameter.
258  *  \throw If the mesh dimension is not set.
259  *  \throw If the coordinates array is not set (if mesh dimension != -1 ).
260  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
261  *  \throw If the connectivity data array has more than one component.
262  *  \throw If the connectivity data array has a named component.
263  *  \throw If the connectivity index data array has more than one component.
264  *  \throw If the connectivity index data array has a named component.
265  *  \throw If number of nodes defining an element does not correspond to the type of element.
266  *  \throw If the nodal connectivity includes an invalid node id.
267  */
268 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
269 {
270   checkCoherency1(eps);
271 }
272
273 /*!
274  * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
275  * elements contained in the mesh. For more info on the mesh dimension see
276  * \ref MEDCouplingUMeshPage.
277  *  \param [in] meshDim - a new mesh dimension.
278  *  \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
279  */
280 void MEDCouplingUMesh::setMeshDimension(int meshDim)
281 {
282   if(meshDim<-1 || meshDim>3)
283     throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
284   _mesh_dim=meshDim;
285   declareAsNew();
286 }
287
288 /*!
289  * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
290  * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
291  * If a nodal connectivity previouly existed before the call of this method, it will be reset.
292  *
293  *  \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
294  *
295  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
296  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
297  */
298 void MEDCouplingUMesh::allocateCells(int nbOfCells)
299 {
300   if(nbOfCells<0)
301     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
302   if(_nodal_connec_index)
303     {
304       _nodal_connec_index->decrRef();
305     }
306   if(_nodal_connec)
307     {
308       _nodal_connec->decrRef();
309     }
310   _nodal_connec_index=DataArrayInt::New();
311   _nodal_connec_index->reserve(nbOfCells+1);
312   _nodal_connec_index->pushBackSilent(0);
313   _nodal_connec=DataArrayInt::New();
314   _nodal_connec->reserve(2*nbOfCells);
315   _types.clear();
316   declareAsNew();
317 }
318
319 /*!
320  * Appends a cell to the connectivity array. For deeper understanding what is
321  * happening see \ref MEDCouplingUMeshNodalConnectivity.
322  *  \param [in] type - type of cell to add.
323  *  \param [in] size - number of nodes constituting this cell.
324  *  \param [in] nodalConnOfCell - the connectivity of the cell to add.
325  * 
326  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
327  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
328  */
329 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
330 {
331   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
332   if(_nodal_connec_index==0)
333     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
334   if((int)cm.getDimension()==_mesh_dim)
335     {
336       if(!cm.isDynamic())
337         if(size!=(int)cm.getNumberOfNodes())
338           {
339             std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
340             oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
341             throw INTERP_KERNEL::Exception(oss.str().c_str());
342           }
343       int idx=_nodal_connec_index->back();
344       int val=idx+size+1;
345       _nodal_connec_index->pushBackSilent(val);
346       _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
347       _types.insert(type);
348     }
349   else
350     {
351       std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
352       oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
353       oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
354       throw INTERP_KERNEL::Exception(oss.str().c_str());
355     }
356 }
357
358 /*!
359  * Compacts data arrays to release unused memory. This method is to be called after
360  * finishing cell insertion using \a this->insertNextCell().
361  * 
362  *  \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
363  *  \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
364  */
365 void MEDCouplingUMesh::finishInsertingCells()
366 {
367   _nodal_connec->pack();
368   _nodal_connec_index->pack();
369   _nodal_connec->declareAsNew();
370   _nodal_connec_index->declareAsNew();
371   updateTime();
372 }
373
374 /*!
375  * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
376  * Useful for python users.
377  */
378 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
379 {
380   return new MEDCouplingUMeshCellIterator(this);
381 }
382
383 /*!
384  * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
385  * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
386  * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
387  * Useful for python users.
388  */
389 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
390 {
391   if(!checkConsecutiveCellTypes())
392     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
393   return new MEDCouplingUMeshCellByTypeEntry(this);
394 }
395
396 /*!
397  * Returns a set of all cell types available in \a this mesh.
398  * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
399  * \warning this method does not throw any exception even if \a this is not defined.
400  */
401 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
402 {
403   return _types;
404 }
405
406 /*!
407  * This method is a method that compares \a this and \a other.
408  * This method compares \b all attributes, even names and component names.
409  */
410 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
411 {
412   if(!other)
413     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
414   std::ostringstream oss; oss.precision(15);
415   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
416   if(!otherC)
417     {
418       reason="mesh given in input is not castable in MEDCouplingUMesh !";
419       return false;
420     }
421   if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
422     return false;
423   if(_mesh_dim!=otherC->_mesh_dim)
424     {
425       oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" <<  otherC->_mesh_dim;
426       reason=oss.str();
427       return false;
428     }
429   if(_types!=otherC->_types)
430     {
431       oss << "umesh geometric type mismatch :\nThis geometric types are :";
432       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
433         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
434       oss << "\nOther geometric types are :";
435       for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
436         { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
437       reason=oss.str();
438       return false;
439     }
440   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
441     if(_nodal_connec==0 || otherC->_nodal_connec==0)
442       {
443         reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
444         return false;
445       }
446   if(_nodal_connec!=otherC->_nodal_connec)
447     if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
448       {
449         reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
450         return false;
451       }
452   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
453     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
454       {
455         reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
456         return false;
457       }
458   if(_nodal_connec_index!=otherC->_nodal_connec_index)
459     if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
460       {
461         reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
462         return false;
463       }
464   return true;
465 }
466
467 /*!
468  * Checks if data arrays of this mesh (node coordinates, nodal
469  * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
470  * not considered.
471  *  \param [in] other - the mesh to compare with.
472  *  \param [in] prec - precision value used to compare node coordinates.
473  *  \return bool - \a true if the two meshes are same.
474  */
475 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
476 {
477   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
478   if(!otherC)
479     return false;
480   if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
481     return false;
482   if(_mesh_dim!=otherC->_mesh_dim)
483     return false;
484   if(_types!=otherC->_types)
485     return false;
486   if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
487     if(_nodal_connec==0 || otherC->_nodal_connec==0)
488       return false;
489   if(_nodal_connec!=otherC->_nodal_connec)
490     if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
491       return false;
492   if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
493     if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
494       return false;
495   if(_nodal_connec_index!=otherC->_nodal_connec_index)
496     if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
497       return false;
498   return true;
499 }
500
501 /*!
502  * Checks if \a this and \a other meshes are geometrically equivalent with high
503  * probability, else an exception is thrown. The meshes are considered equivalent if
504  * (1) meshes contain the same number of nodes and the same number of elements of the
505  * same types (2) three cells of the two meshes (first, last and middle) are based
506  * on coincident nodes (with a specified precision).
507  *  \param [in] other - the mesh to compare with.
508  *  \param [in] prec - the precision used to compare nodes of the two meshes.
509  *  \throw If the two meshes do not match.
510  */
511 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
512 {
513  MEDCouplingPointSet::checkFastEquivalWith(other,prec);
514  const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
515   if(!otherC)
516     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !"); 
517 }
518
519 /*!
520  * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
521  * cells each node belongs to.
522  * \warning For speed reasons, this method does not check if node ids in the nodal
523  *          connectivity correspond to the size of node coordinates array.
524  * \param [in,out] revNodal - an array holding ids of cells sharing each node.
525  * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
526  *        dividing cell ids in \a revNodal into groups each referring to one
527  *        node. Its every element (except the last one) is an index pointing to the
528  *         first id of a group of cells. For example cells sharing the node #1 are 
529  *        described by following range of indices: 
530  *        [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
531  *        \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
532  *        Number of cells sharing the *i*-th node is
533  *        \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
534  * \throw If the coordinates array is not set.
535  * \throw If the nodal connectivity of cells is not defined.
536  * 
537  * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
538  * \ref  py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
539  */
540 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
541 {
542   checkFullyDefined();
543   int nbOfNodes=getNumberOfNodes();
544   int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
545   revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
546   std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
547   const int *conn=_nodal_connec->getConstPointer();
548   const int *connIndex=_nodal_connec_index->getConstPointer();
549   int nbOfCells=getNumberOfCells();
550   int nbOfEltsInRevNodal=0;
551   for(int eltId=0;eltId<nbOfCells;eltId++)
552     {
553       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
554       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
555       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
556         if(*iter>=0)//for polyhedrons
557           {
558             nbOfEltsInRevNodal++;
559             revNodalIndxPtr[(*iter)+1]++;
560           }
561     }
562   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
563   int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
564   revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
565   std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
566   for(int eltId=0;eltId<nbOfCells;eltId++)
567     {
568       const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
569       const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
570       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
571         if(*iter>=0)//for polyhedrons
572           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
573     }
574 }
575
576 /// @cond INTERNAL
577
578 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
579 {
580   return id;
581 }
582
583 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
584 {
585   if(!compute)
586     return id+1;
587   else
588     {
589       if(cm.getOrientationStatus(nb,conn1,conn2))
590         return id+1;
591       else
592         return -(id+1);
593     }
594 }
595
596 class MinusOneSonsGenerator
597 {
598 public:
599   MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
600   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
601   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
602   static const int DELTA=1;
603 private:
604   const INTERP_KERNEL::CellModel& _cm;
605 };
606
607 class MinusOneSonsGeneratorBiQuadratic
608 {
609 public:
610   MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
611   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
612   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
613   static const int DELTA=1;
614 private:
615   const INTERP_KERNEL::CellModel& _cm;
616 };
617
618 class MinusTwoSonsGenerator
619 {
620 public:
621   MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
622   unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
623   unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
624   static const int DELTA=2;
625 private:
626   const INTERP_KERNEL::CellModel& _cm;
627 };
628
629 /// @endcond
630
631 /*!
632  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
633  * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
634  * describing correspondence between cells of \a this and the result meshes are
635  * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
636  * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
637  * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
638  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
639  * \warning For speed reasons, this method does not check if node ids in the nodal
640  *          connectivity correspond to the size of node coordinates array.
641  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
642  *          to write this mesh to the MED file, its cells must be sorted using
643  *          sortCellsInMEDFileFrmt().
644  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
645  *         each cell of \a this mesh.
646  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
647  *        dividing cell ids in \a desc into groups each referring to one
648  *        cell of \a this mesh. Its every element (except the last one) is an index
649  *        pointing to the first id of a group of cells. For example cells of the
650  *        result mesh bounding the cell #1 of \a this mesh are described by following
651  *        range of indices:
652  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
653  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
654  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
655  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
656  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
657  *         by each cell of the result mesh.
658  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
659  *        in the result mesh,
660  *        dividing cell ids in \a revDesc into groups each referring to one
661  *        cell of the result mesh the same way as \a descIndx divides \a desc.
662  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
663  *        delete this mesh using decrRef() as it is no more needed.
664  *  \throw If the coordinates array is not set.
665  *  \throw If the nodal connectivity of cells is node defined.
666  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
667  *         revDescIndx == NULL.
668  * 
669  *  \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
670  *  \ref  py_mcumesh_buildDescendingConnectivity "Here is a Python example".
671  * \sa buildDescendingConnectivity2()
672  */
673 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
674 {
675   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
676 }
677
678 /*!
679  * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
680  * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
681  * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
682  * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
683  * \sa MEDCouplingUMesh::buildDescendingConnectivity
684  */
685 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
686 {
687   checkFullyDefined();
688   if(getMeshDimension()!=3)
689     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
690   return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
691 }
692
693 /*!
694  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
695  * this->getMeshDimension(), that bound cells of \a this mesh. In
696  * addition arrays describing correspondence between cells of \a this and the result
697  * meshes are returned. The arrays \a desc and \a descIndx describe the descending
698  * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
699  *  mesh. This method differs from buildDescendingConnectivity() in that apart
700  * from cell ids, \a desc returns mutual orientation of cells in \a this and the
701  * result meshes. So a positive id means that order of nodes in corresponding cells
702  * of two meshes is same, and a negative id means a reverse order of nodes. Since a
703  * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
704  * i.e. cell ids are one-based.
705  * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
706  * i.e. enumerate cells of  \a this mesh bounded by each cell of the result mesh. 
707  * \warning For speed reasons, this method does not check if node ids in the nodal
708  *          connectivity correspond to the size of node coordinates array.
709  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
710  *          to write this mesh to the MED file, its cells must be sorted using
711  *          sortCellsInMEDFileFrmt().
712  *  \param [in,out] desc - the array containing cell ids of the result mesh bounding
713  *         each cell of \a this mesh.
714  *  \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
715  *        dividing cell ids in \a desc into groups each referring to one
716  *        cell of \a this mesh. Its every element (except the last one) is an index
717  *        pointing to the first id of a group of cells. For example cells of the
718  *        result mesh bounding the cell #1 of \a this mesh are described by following
719  *        range of indices:
720  *        [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
721  *        \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
722  *        Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
723  *        \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
724  *  \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
725  *         by each cell of the result mesh.
726  *  \param [in,out] revDescIndx - the array, of length one more than number of cells
727  *        in the result mesh,
728  *        dividing cell ids in \a revDesc into groups each referring to one
729  *        cell of the result mesh the same way as \a descIndx divides \a desc.
730  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
731  *        shares the node coordinates array with \a this mesh. The caller is to
732  *        delete this mesh using decrRef() as it is no more needed.
733  *  \throw If the coordinates array is not set.
734  *  \throw If the nodal connectivity of cells is node defined.
735  *  \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
736  *         revDescIndx == NULL.
737  * 
738  *  \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
739  *  \ref  py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
740  * \sa buildDescendingConnectivity()
741  */
742 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
743 {
744   return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
745 }
746
747 /*!
748  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
749  * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
750  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
751  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
752  *
753  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
754  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
755  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
756  */
757 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
758 {
759   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
760   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
761   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
762   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
763   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
764   meshDM1=0;
765   ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
766 }
767
768 /*!
769  * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
770  * This method is useful for users that want to reduce along a criterion the set of neighbours cell. This is typically the case to extract a set a neighbours,
771  * excluding a set of meshdim-1 cells in input descending connectivity.
772  * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
773  * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
774  * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
775  *
776  * \param [in] desc descending connectivity array.
777  * \param [in] descIndx descending connectivity index array used to walk through \b desc.
778  * \param [in] revDesc reverse descending connectivity array.
779  * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
780  * \param [out] neighbors is an array storing all the neighbors of all cells in \b this. This array is newly allocated and should be dealt by the caller. \b neighborsIndx 2nd output
781  *                        parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
782  * \param [out] neighborsIndx is an array of size this->getNumberOfCells()+1 newly allocated and should be dealt by the caller. This arrays allow to use the first output parameter \b neighbors.
783  */
784 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
785                                                   DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
786 {
787   if(!desc || !descIndx || !revDesc || !revDescIndx)
788     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
789   const int *descPtr=desc->getConstPointer();
790   const int *descIPtr=descIndx->getConstPointer();
791   const int *revDescPtr=revDesc->getConstPointer();
792   const int *revDescIPtr=revDescIndx->getConstPointer();
793   //
794   int nbCells=descIndx->getNumberOfTuples()-1;
795   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
796   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
797   int *out1Ptr=out1->getPointer();
798   *out1Ptr++=0;
799   out0->reserve(desc->getNumberOfTuples());
800   for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
801     {
802       for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
803         {
804           std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
805           s.erase(i);
806           out0->insertAtTheEnd(s.begin(),s.end());
807         }
808       *out1Ptr=out0->getNumberOfTuples();
809     }
810   neighbors=out0.retn();
811   neighborsIndx=out1.retn();
812 }
813
814 /// @cond INTERNAL
815
816 /*!
817  * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
818  * For speed reasons no check of this will be done.
819  */
820 template<class SonsGenerator>
821 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
822 {
823   if(!desc || !descIndx || !revDesc || !revDescIndx)
824     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
825   checkConnectivityFullyDefined();
826   int nbOfCells=getNumberOfCells();
827   int nbOfNodes=getNumberOfNodes();
828   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
829   int *revNodalIndxPtr=revNodalIndx->getPointer();
830   const int *conn=_nodal_connec->getConstPointer();
831   const int *connIndex=_nodal_connec_index->getConstPointer();
832   std::string name="Mesh constituent of "; name+=getName();
833   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
834   ret->setCoords(getCoords());
835   ret->allocateCells(2*nbOfCells);
836   descIndx->alloc(nbOfCells+1,1);
837   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
838   int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
839   for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
840     {
841       int pos=connIndex[eltId];
842       int posP1=connIndex[eltId+1];
843       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
844       SonsGenerator sg(cm);
845       unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
846       INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
847       for(unsigned i=0;i<nbOfSons;i++)
848         {
849           INTERP_KERNEL::NormalizedCellType cmsId;
850           unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
851           for(unsigned k=0;k<nbOfNodesSon;k++)
852             if(tmp[k]>=0)
853               revNodalIndxPtr[tmp[k]+1]++;
854           ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
855           revDesc2->pushBackSilent(eltId);
856         }
857       descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
858     }
859   int nbOfCellsM1=ret->getNumberOfCells();
860   std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
861   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
862   std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
863   int *revNodalPtr=revNodal->getPointer();
864   const int *connM1=ret->getNodalConnectivity()->getConstPointer();
865   const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
866   for(int eltId=0;eltId<nbOfCellsM1;eltId++)
867     {
868       const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
869       const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
870       for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
871         if(*iter>=0)//for polyhedrons
872           *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
873     }
874   //
875   DataArrayInt *commonCells=0,*commonCellsI=0;
876   FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
877   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
878   const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
879   int newNbOfCellsM1=-1;
880   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
881                                                                                                             commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
882   std::vector<bool> isImpacted(nbOfCellsM1,false);
883   for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
884     for(int work2=work[0];work2!=work[1];work2++)
885       isImpacted[commonCellsPtr[work2]]=true;
886   const int *o2nM1Ptr=o2nM1->getConstPointer();
887   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
888   const int *n2oM1Ptr=n2oM1->getConstPointer();
889   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
890   ret2->copyTinyInfoFrom(this);
891   desc->alloc(descIndx->back(),1);
892   int *descPtr=desc->getPointer();
893   const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
894   for(int i=0;i<nbOfCellsM1;i++,descPtr++)
895     {
896       if(!isImpacted[i])
897         *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
898       else
899         {
900           if(i!=n2oM1Ptr[o2nM1Ptr[i]])
901             {
902               const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
903               *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
904             }
905           else
906             *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
907         }
908     }
909   revDesc->reserve(newNbOfCellsM1);
910   revDescIndx->alloc(newNbOfCellsM1+1,1);
911   int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
912   const int *revDesc2Ptr=revDesc2->getConstPointer();
913   for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
914     {
915       int oldCellIdM1=n2oM1Ptr[i];
916       if(!isImpacted[oldCellIdM1])
917         {
918           revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
919           revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
920         }
921       else
922         {
923           for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
924             revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
925           revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
926           commonCellsIPtr++;
927         }
928     }
929   //
930   return ret2.retn();
931 }
932
933 struct MEDCouplingAccVisit
934 {
935   MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
936   int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
937   int _new_nb_of_nodes;
938 };
939
940 /// @endcond
941
942 /*!
943  * Converts specified cells to either polygons (if \a this is a 2D mesh) or
944  * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
945  * array of cell ids. Pay attention that after conversion all algorithms work slower
946  * with \a this mesh than before conversion. <br> If an exception is thrown during the
947  * conversion due presence of invalid ids in the array of cells to convert, as a
948  * result \a this mesh contains some already converted elements. In this case the 2D
949  * mesh remains valid but 3D mesh becomes \b inconsistent!
950  *  \warning This method can significantly modify the order of geometric types in \a this,
951  *          hence, to write this mesh to the MED file, its cells must be sorted using
952  *          sortCellsInMEDFileFrmt().
953  *  \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
954  *  \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
955  *         cellIdsToConvertBg.
956  *  \throw If the coordinates array is not set.
957  *  \throw If the nodal connectivity of cells is node defined.
958  *  \throw If dimension of \a this mesh is not either 2 or 3.
959  *
960  *  \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
961  *  \ref  py_mcumesh_convertToPolyTypes "Here is a Python example".
962  */
963 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
964 {
965   checkFullyDefined();
966   int dim=getMeshDimension();
967   if(dim<2 || dim>3)
968     throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
969   int nbOfCells=getNumberOfCells();
970   if(dim==2)
971     {
972       const int *connIndex=_nodal_connec_index->getConstPointer();
973       int *conn=_nodal_connec->getPointer();
974       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
975         {
976           if(*iter>=0 && *iter<nbOfCells)
977             {
978               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
979               if(!cm.isQuadratic())
980                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
981               else
982                 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
983             }
984           else
985             {
986               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
987               oss << " in range [0," << nbOfCells << ") !";
988               throw INTERP_KERNEL::Exception(oss.str().c_str());
989             }
990         }
991     }
992   else
993     {
994       int *connIndex=_nodal_connec_index->getPointer();
995       int connIndexLgth=_nodal_connec_index->getNbOfElems();
996       const int *connOld=_nodal_connec->getConstPointer();
997       int connOldLgth=_nodal_connec->getNbOfElems();
998       std::vector<int> connNew(connOld,connOld+connOldLgth);
999       for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1000         {
1001           if(*iter>=0 && *iter<nbOfCells)
1002             {
1003               int pos=connIndex[*iter];
1004               int posP1=connIndex[(*iter)+1];
1005               int lgthOld=posP1-pos-1;
1006               const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1007               connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1008               unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1009               int *tmp=new int[nbOfFaces*lgthOld];
1010               int *work=tmp;
1011               for(int j=0;j<(int)nbOfFaces;j++)
1012                 {
1013                   INTERP_KERNEL::NormalizedCellType type;
1014                   unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1015                   work+=offset;
1016                   *work++=-1;
1017                 }
1018               std::size_t newLgth=std::distance(tmp,work)-1;
1019               std::size_t delta=newLgth-lgthOld;
1020               std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1021               connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1022               std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1023               delete [] tmp;
1024             }
1025           else
1026             {
1027               std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1028               oss << " in range [0," << nbOfCells << ") !";
1029               throw INTERP_KERNEL::Exception(oss.str().c_str());
1030             }
1031         }
1032       _nodal_connec->alloc((int)connNew.size(),1);
1033       int *newConnPtr=_nodal_connec->getPointer();
1034       std::copy(connNew.begin(),connNew.end(),newConnPtr);
1035     }
1036   computeTypes();
1037 }
1038
1039 /*!
1040  * Converts all cells to either polygons (if \a this is a 2D mesh) or
1041  * polyhedrons (if \a this is a 3D mesh).
1042  *  \warning As this method is purely for user-friendliness and no optimization is
1043  *          done to avoid construction of a useless vector, this method can be costly
1044  *          in memory.
1045  *  \throw If the coordinates array is not set.
1046  *  \throw If the nodal connectivity of cells is node defined.
1047  *  \throw If dimension of \a this mesh is not either 2 or 3.
1048  */
1049 void MEDCouplingUMesh::convertAllToPoly()
1050 {
1051   int nbOfCells=getNumberOfCells();
1052   std::vector<int> cellIds(nbOfCells);
1053   for(int i=0;i<nbOfCells;i++)
1054     cellIds[i]=i;
1055   convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1056 }
1057
1058 /*!
1059  * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1060  * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1061  * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1062  * base facet of the volume and the second half of nodes describes an opposite facet
1063  * having the same number of nodes as the base one. This method converts such
1064  * connectivity to a valid polyhedral format where connectivity of each facet is
1065  * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1066  * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1067  * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1068  * a correct orientation of the first facet of a polyhedron, else orientation of a
1069  * corrected cell is reverse.<br>
1070  * This method is useful to build an extruded unstructured mesh with polyhedrons as
1071  * it releases the user from boring description of polyhedra connectivity in the valid
1072  * format.
1073  *  \throw If \a this->getMeshDimension() != 3.
1074  *  \throw If \a this->getSpaceDimension() != 3.
1075  *  \throw If the nodal connectivity of cells is not defined.
1076  *  \throw If the coordinates array is not set.
1077  *  \throw If \a this mesh contains polyhedrons with the valid connectivity.
1078  *  \throw If \a this mesh contains polyhedrons with odd number of nodes.
1079  *
1080  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1081  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1082  */
1083 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
1084 {
1085   checkFullyDefined();
1086   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1087     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1088   int nbOfCells=getNumberOfCells();
1089   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1090   newCi->alloc(nbOfCells+1,1);
1091   int *newci=newCi->getPointer();
1092   const int *ci=_nodal_connec_index->getConstPointer();
1093   const int *c=_nodal_connec->getConstPointer();
1094   newci[0]=0;
1095   for(int i=0;i<nbOfCells;i++)
1096     {
1097       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1098       if(type==INTERP_KERNEL::NORM_POLYHED)
1099         {
1100           if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1101             {
1102               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1103               throw INTERP_KERNEL::Exception(oss.str().c_str());
1104             }
1105           std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1106           if(n2%2!=0)
1107             {
1108               std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron with 1 face but there is a mismatch of number of nodes in face should be even !";
1109               throw INTERP_KERNEL::Exception(oss.str().c_str());
1110             }
1111           int n1=(int)(n2/2);
1112           newci[i+1]=7*n1+2+newci[i];//6*n1 (nodal length) + n1+2 (number of faces) - 1 (number of '-1' separator is equal to number of faces -1) + 1 (for cell type)
1113         }
1114       else
1115         newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1116     }
1117   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1118   newC->alloc(newci[nbOfCells],1);
1119   int *newc=newC->getPointer();
1120   for(int i=0;i<nbOfCells;i++)
1121     {
1122       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1123       if(type==INTERP_KERNEL::NORM_POLYHED)
1124         {
1125           std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1126           newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1127           *newc++=-1;
1128           for(std::size_t j=0;j<n1;j++)
1129             {
1130               newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1131               newc[n1+5*j]=-1;
1132               newc[n1+5*j+1]=c[ci[i]+1+j];
1133               newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1134               newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1135               newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1136             }
1137           newc+=n1*6;
1138         }
1139       else
1140         newc=std::copy(c+ci[i],c+ci[i+1],newc);
1141     }
1142   _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1143   _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1144 }
1145
1146
1147 /*!
1148  * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1149  * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1150  * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1151  *          to write this mesh to the MED file, its cells must be sorted using
1152  *          sortCellsInMEDFileFrmt().
1153  * \return \c true if at least one cell has been converted, \c false else. In the
1154  *         last case the nodal connectivity remains unchanged.
1155  * \throw If the coordinates array is not set.
1156  * \throw If the nodal connectivity of cells is not defined.
1157  * \throw If \a this->getMeshDimension() < 0.
1158  */
1159 bool MEDCouplingUMesh::unPolyze()
1160 {
1161   checkFullyDefined();
1162   int mdim=getMeshDimension();
1163   if(mdim<0)
1164     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1165   if(mdim<=1)
1166     return false;
1167   int nbOfCells=getNumberOfCells();
1168   if(nbOfCells<1)
1169     return false;
1170   int initMeshLgth=getMeshLength();
1171   int *conn=_nodal_connec->getPointer();
1172   int *index=_nodal_connec_index->getPointer();
1173   int posOfCurCell=0;
1174   int newPos=0;
1175   int lgthOfCurCell;
1176   bool ret=false;
1177   for(int i=0;i<nbOfCells;i++)
1178     {
1179       lgthOfCurCell=index[i+1]-posOfCurCell;
1180       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1181       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1182       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1183       int newLgth;
1184       if(cm.isDynamic())
1185         {
1186           switch(cm.getDimension())
1187             {
1188             case 2:
1189               {
1190                 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1191                 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1192                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1193                 break;
1194               }
1195             case 3:
1196               {
1197                 int nbOfFaces,lgthOfPolyhConn;
1198                 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1199                 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1200                 break;
1201               }
1202             case 1:
1203               {
1204                 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1205                 break;
1206               }
1207             }
1208           ret=ret || (newType!=type);
1209           conn[newPos]=newType;
1210           newPos+=newLgth+1;
1211           posOfCurCell=index[i+1];
1212           index[i+1]=newPos;
1213         }
1214       else
1215         {
1216           std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1217           newPos+=lgthOfCurCell;
1218           posOfCurCell+=lgthOfCurCell;
1219           index[i+1]=newPos;
1220         }
1221     }
1222   if(newPos!=initMeshLgth)
1223     _nodal_connec->reAlloc(newPos);
1224   if(ret)
1225     computeTypes();
1226   return ret;
1227 }
1228
1229 /*!
1230  * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1231  * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1232  * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells. 
1233  *
1234  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not. This epsilon is used to recenter around origin to have maximal 
1235  *             precision.
1236  */
1237 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1238 {
1239   checkFullyDefined();
1240   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1241     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1242   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1243   coords->recenterForMaxPrecision(eps);
1244   //
1245   int nbOfCells=getNumberOfCells();
1246   const int *conn=_nodal_connec->getConstPointer();
1247   const int *index=_nodal_connec_index->getConstPointer();
1248   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1249   connINew->alloc(nbOfCells+1,1);
1250   int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1251   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1252   bool changed=false;
1253   for(int i=0;i<nbOfCells;i++,connINewPtr++)
1254     {
1255       if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1256         {
1257           SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1258           changed=true;
1259         }
1260       else
1261         connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1262       *connINewPtr=connNew->getNumberOfTuples();
1263     }
1264   if(changed)
1265     setConnectivity(connNew,connINew,false);
1266 }
1267
1268 /*!
1269  * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1270  * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1271  * the format of returned DataArrayInt instance.
1272  * 
1273  * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1274  * \sa MEDCouplingUMesh::getNodeIdsInUse
1275  */
1276 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1277 {
1278   checkConnectivityFullyDefined();
1279   int nbOfCells=getNumberOfCells();
1280   const int *connIndex=_nodal_connec_index->getConstPointer();
1281   const int *conn=_nodal_connec->getConstPointer();
1282   const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1283   int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1284   std::vector<bool> retS(maxElt,false);
1285   for(int i=0;i<nbOfCells;i++)
1286     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1287       if(conn[j]>=0)
1288         retS[conn[j]]=true;
1289   int sz=0;
1290   for(int i=0;i<maxElt;i++)
1291     if(retS[i])
1292       sz++;
1293   DataArrayInt *ret=DataArrayInt::New();
1294   ret->alloc(sz,1);
1295   int *retPtr=ret->getPointer();
1296   for(int i=0;i<maxElt;i++)
1297     if(retS[i])
1298       *retPtr++=i;
1299   return ret;
1300 }
1301
1302 /*!
1303  * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1304  * \sa MEDCouplingUMesh::getNodeIdsInUse
1305  */
1306 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1307 {
1308   int nbOfNodes=(int)nodeIdsInUse.size();
1309   int nbOfCells=getNumberOfCells();
1310   const int *connIndex=_nodal_connec_index->getConstPointer();
1311   const int *conn=_nodal_connec->getConstPointer();
1312   for(int i=0;i<nbOfCells;i++)
1313     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1314       if(conn[j]>=0)
1315         {
1316           if(conn[j]<nbOfNodes)
1317             nodeIdsInUse[conn[j]]=true;
1318           else
1319             {
1320               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1321               throw INTERP_KERNEL::Exception(oss.str().c_str());
1322             }
1323         }
1324 }
1325
1326 /*!
1327  * Finds nodes not used in any cell and returns an array giving a new id to every node
1328  * by excluding the unused nodes, for which the array holds -1. The result array is
1329  * a mapping in "Old to New" mode. 
1330  *  \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1331  *  \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1332  *          this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1333  *          if the node is unused or a new id else. The caller is to delete this
1334  *          array using decrRef() as it is no more needed.  
1335  *  \throw If the coordinates array is not set.
1336  *  \throw If the nodal connectivity of cells is not defined.
1337  *  \throw If the nodal connectivity includes an invalid id.
1338  *
1339  *  \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1340  *  \ref  py_mcumesh_getNodeIdsInUse "Here is a Python example".
1341  * \sa computeNodeIdsAlg()
1342  */
1343 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1344 {
1345   nbrOfNodesInUse=-1;
1346   int nbOfNodes=getNumberOfNodes();
1347   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1348   ret->alloc(nbOfNodes,1);
1349   int *traducer=ret->getPointer();
1350   std::fill(traducer,traducer+nbOfNodes,-1);
1351   int nbOfCells=getNumberOfCells();
1352   const int *connIndex=_nodal_connec_index->getConstPointer();
1353   const int *conn=_nodal_connec->getConstPointer();
1354   for(int i=0;i<nbOfCells;i++)
1355     for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1356       if(conn[j]>=0)
1357         {
1358           if(conn[j]<nbOfNodes)
1359             traducer[conn[j]]=1;
1360           else
1361             {
1362               std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i  << " presence of node id " <<  conn[j] << " not in [0," << nbOfNodes << ") !";
1363               throw INTERP_KERNEL::Exception(oss.str().c_str());
1364             }
1365         }
1366   nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1367   std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1368   return ret.retn();
1369 }
1370
1371 /*!
1372  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1373  * For each cell in \b this the number of nodes constituting cell is computed.
1374  * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1375  * So for pohyhedrons some nodes can be counted several times in the returned result.
1376  * 
1377  * \return a newly allocated array
1378  */
1379 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1380 {
1381   checkConnectivityFullyDefined();
1382   int nbOfCells=getNumberOfCells();
1383   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1384   ret->alloc(nbOfCells,1);
1385   int *retPtr=ret->getPointer();
1386   const int *conn=getNodalConnectivity()->getConstPointer();
1387   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1388   for(int i=0;i<nbOfCells;i++,retPtr++)
1389     {
1390       if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1391         *retPtr=connI[i+1]-connI[i]-1;
1392       else
1393         *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1394     }
1395   return ret.retn();
1396 }
1397
1398 /*!
1399  * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1400  * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1401  * 
1402  * \return a newly allocated array
1403  */
1404 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception)
1405 {
1406   checkConnectivityFullyDefined();
1407   int nbOfCells=getNumberOfCells();
1408   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1409   ret->alloc(nbOfCells,1);
1410   int *retPtr=ret->getPointer();
1411   const int *conn=getNodalConnectivity()->getConstPointer();
1412   const int *connI=getNodalConnectivityIndex()->getConstPointer();
1413   for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1414     {
1415       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1416       *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1417     }
1418   return ret.retn();
1419 }
1420
1421 /*!
1422  * Removes unused nodes (the node coordinates array is shorten) and returns an array
1423  * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1424  * array mean that the corresponding old node is no more used. 
1425  *  \return DataArrayInt * - a new instance of DataArrayInt of length \a
1426  *           this->getNumberOfNodes() before call of this method. The caller is to
1427  *           delete this array using decrRef() as it is no more needed. 
1428  *  \throw If the coordinates array is not set.
1429  *  \throw If the nodal connectivity of cells is not defined.
1430  *  \throw If the nodal connectivity includes an invalid id.
1431  *
1432  *  \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1433  *  \ref  py_mcumesh_zipCoordsTraducer "Here is a Python example".
1434  */
1435 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1436 {
1437   return MEDCouplingPointSet::zipCoordsTraducer();
1438 }
1439
1440 /*!
1441  * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1442  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1443  */
1444 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1445 {
1446   switch(compType)
1447     {
1448     case 0:
1449       return AreCellsEqual0(conn,connI,cell1,cell2);
1450     case 1:
1451       return AreCellsEqual1(conn,connI,cell1,cell2);
1452     case 2:
1453       return AreCellsEqual2(conn,connI,cell1,cell2);
1454     case 3:
1455       return AreCellsEqual3(conn,connI,cell1,cell2);
1456     case 7:
1457       return AreCellsEqual7(conn,connI,cell1,cell2);
1458     }
1459   throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1460 }
1461
1462 /*!
1463  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1464  */
1465 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1466 {
1467   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1468     return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1469   return 0;
1470 }
1471
1472 /*!
1473  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1474  */
1475 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1476 {
1477   int sz=connI[cell1+1]-connI[cell1];
1478   if(sz==connI[cell2+1]-connI[cell2])
1479     {
1480       if(conn[connI[cell1]]==conn[connI[cell2]])
1481         {
1482           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1483           unsigned dim=cm.getDimension();
1484           if(dim!=3)
1485             {
1486               if(dim!=1)
1487                 {
1488                   int sz1=2*(sz-1);
1489                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1490                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1491                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1492                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1493                   return work!=tmp+sz1?1:0;
1494                 }
1495               else
1496                 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1497             }
1498           else
1499             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1500         }
1501     }
1502   return 0;
1503 }
1504
1505 /*!
1506  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1507  */
1508 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1509 {
1510   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1511     {
1512       if(conn[connI[cell1]]==conn[connI[cell2]])
1513         {
1514           std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1515           std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1516           return s1==s2?1:0;
1517         }
1518     }
1519   return 0;
1520 }
1521
1522 /*!
1523  * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1524  */
1525 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1526 {
1527   if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1528     {
1529       std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1530       std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1531       return s1==s2?1:0;
1532     }
1533   return 0;
1534 }
1535
1536 /*!
1537  * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1538  */
1539 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1540 {
1541   int sz=connI[cell1+1]-connI[cell1];
1542   if(sz==connI[cell2+1]-connI[cell2])
1543     {
1544       if(conn[connI[cell1]]==conn[connI[cell2]])
1545         {
1546           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1547           unsigned dim=cm.getDimension();
1548           if(dim!=3)
1549             {
1550               if(dim!=1)
1551                 {
1552                   int sz1=2*(sz-1);
1553                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1554                   int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1555                   std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1556                   work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1557                   if(work!=tmp+sz1)
1558                     return 1;
1559                   else
1560                     {
1561                       std::reverse_iterator<int *> it1((int *)tmp+sz1);
1562                       std::reverse_iterator<int *> it2((int *)tmp);
1563                       if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1564                         return 2;
1565                       else
1566                         return 0;
1567                     }
1568                   
1569                   return work!=tmp+sz1?1:0;
1570                 }
1571               else
1572                 {//case of SEG2 and SEG3
1573                   if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1574                     return 1;
1575                   if(!cm.isQuadratic())
1576                     {
1577                       std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1578                       std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1579                       if(std::equal(it1,it2,conn+connI[cell2]+1))
1580                         return 2;
1581                       return 0;
1582                     }
1583                   else
1584                     {
1585                       if(conn[connI[cell1]+1]==conn[connI[cell2]+2] && conn[connI[cell1]+2]==conn[connI[cell2]+1] && conn[connI[cell1]+3]==conn[connI[cell2]+3])
1586                         return 2;
1587                       return 0;
1588                     }
1589                 }
1590             }
1591           else
1592             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1593         }
1594     }
1595   return 0;
1596 }
1597
1598 /*!
1599  * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1600  * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1601  * and result remains unchanged.
1602  * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1603  * If in 'candidates' pool -1 value is considered as an empty value.
1604  * WARNING this method returns only ONE set of result !
1605  */
1606 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1607 {
1608   if(candidates.size()<1)
1609     return false;
1610   bool ret=false;
1611   std::vector<int>::const_iterator iter=candidates.begin();
1612   int start=(*iter++);
1613   for(;iter!=candidates.end();iter++)
1614     {
1615       int status=AreCellsEqual(conn,connI,start,*iter,compType);
1616       if(status!=0)
1617         {
1618           if(!ret)
1619             {
1620               result->pushBackSilent(start);
1621               ret=true;
1622             }
1623           if(status==1)
1624             result->pushBackSilent(*iter);
1625           else
1626             result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1627         }
1628     }
1629   return ret;
1630 }
1631
1632 /*!
1633  * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1634  * This method keeps the coordiantes of \a this. This method is time consuming and is called 
1635  *
1636  * \param [in] compType input specifying the technique used to compare cells each other.
1637  *   - 0 : exactly. A cell is detected to be the same if and only if the connectivity is exactly the same without permutation and types same too. This is the strongest policy.
1638  *   - 1 : permutation same orientation. cell1 and cell2 are considered equal if the connectivity of cell2 can be deduced by those of cell1 by direct permutation (with exactly the same orientation)
1639  * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1640  *   - 2 : nodal. cell1 and cell2 are equal if and only if cell1 and cell2 have same type and have the same nodes constituting connectivity. This is the laziest policy. This policy
1641  * can be used for users not sensitive to orientation of cell
1642  * \param [in] startCellId specifies the cellId starting from which the equality computation will be carried out. By default it is 0, which it means that all cells in \a this will be scanned.
1643  * \param [out] commonCells
1644  * \param [out] commonCellsI
1645  * \return the correspondance array old to new in a newly allocated array.
1646  * 
1647  */
1648 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1649 {
1650   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1651   getReverseNodalConnectivity(revNodal,revNodalI);
1652   FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1653 }
1654
1655 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1656                                           DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1657 {
1658   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1659   int nbOfCells=nodalI->getNumberOfTuples()-1;
1660   commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1661   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1662   const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1663   std::vector<bool> isFetched(nbOfCells,false);
1664   if(startCellId==0)
1665     {
1666       for(int i=0;i<nbOfCells;i++)
1667         {
1668           if(!isFetched[i])
1669             {
1670               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1671               std::vector<int> v,v2;
1672               if(connOfNode!=connPtr+connIPtr[i+1])
1673                 {
1674                   const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1675                   v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1676                   connOfNode++;
1677                 }
1678               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1679                 if(*connOfNode>=0)
1680                   {
1681                     v=v2;
1682                     const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1683                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1684                     v2.resize(std::distance(v2.begin(),it));
1685                   }
1686               if(v2.size()>1)
1687                 {
1688                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1689                     {
1690                       int pos=commonCellsI->back();
1691                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1692                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1693                         isFetched[*it]=true;
1694                     }
1695                 }
1696             }
1697         }
1698     }
1699   else
1700     {
1701       for(int i=startCellId;i<nbOfCells;i++)
1702         {
1703           if(!isFetched[i])
1704             {
1705               const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1706               std::vector<int> v,v2;
1707               if(connOfNode!=connPtr+connIPtr[i+1])
1708                 {
1709                   v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1710                   connOfNode++;
1711                 }
1712               for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1713                 if(*connOfNode>=0)
1714                   {
1715                     v=v2;
1716                     std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1717                     v2.resize(std::distance(v2.begin(),it));
1718                   }
1719               if(v2.size()>1)
1720                 {
1721                   if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1722                     {
1723                       int pos=commonCellsI->back();
1724                       commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1725                       for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1726                         isFetched[*it]=true;
1727                     }
1728                 }
1729             }
1730         }
1731     }
1732   commonCellsArr=commonCells.retn();
1733   commonCellsIArr=commonCellsI.retn();
1734 }
1735
1736 /*!
1737  * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1738  * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1739  * than \a other->getNumberOfCells() in the returned array means that there is no
1740  * corresponding cell in \a this mesh.
1741  * It is expected that \a this and \a other meshes share the same node coordinates
1742  * array, if it is not so an exception is thrown. 
1743  *  \param [in] other - the mesh to compare with.
1744  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
1745  *         valid values [0,1,2], see zipConnectivityTraducer().
1746  *  \param [out] arr - a new instance of DataArrayInt returning correspondence
1747  *         between cells of the two meshes. It contains \a other->getNumberOfCells()
1748  *         values. The caller is to delete this array using
1749  *         decrRef() as it is no more needed.
1750  *  \return bool - \c true if all cells of \a other mesh are present in the \a this
1751  *         mesh.
1752  *
1753  *  \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1754  *  \ref  py_mcumesh_areCellsIncludedIn "Here is a Python example".
1755  *  \sa checkDeepEquivalOnSameNodesWith()
1756  *  \sa checkGeoEquivalWith()
1757  */
1758 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1759 {
1760   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1761   int nbOfCells=getNumberOfCells();
1762   static const int possibleCompType[]={0,1,2};
1763   if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1764     {
1765       std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1766       std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1767       oss << " !";
1768       throw INTERP_KERNEL::Exception(oss.str().c_str());
1769     }
1770   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1771   arr=o2n->substr(nbOfCells);
1772   arr->setName(other->getName());
1773   int tmp;
1774   if(other->getNumberOfCells()==0)
1775     return true;
1776   return arr->getMaxValue(tmp)<nbOfCells;
1777 }
1778
1779 /*!
1780  * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1781  * This method tries to determine if \b other is fully included in \b this.
1782  * The main difference is that this method is not expected to throw exception.
1783  * This method has two outputs :
1784  *
1785  * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1786  * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1787  */
1788 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1789 {
1790   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1791   DataArrayInt *commonCells=0,*commonCellsI=0;
1792   int thisNbCells=getNumberOfCells();
1793   mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1794   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1795   const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1796   int otherNbCells=other->getNumberOfCells();
1797   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1798   arr2->alloc(otherNbCells,1);
1799   arr2->fillWithZero();
1800   int *arr2Ptr=arr2->getPointer();
1801   int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1802   for(int i=0;i<nbOfCommon;i++)
1803     {
1804       int start=commonCellsPtr[commonCellsIPtr[i]];
1805       if(start<thisNbCells)
1806         {
1807           for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1808             {
1809               int sig=commonCellsPtr[j]>0?1:-1;
1810               int val=std::abs(commonCellsPtr[j])-1;
1811               if(val>=thisNbCells)
1812                 arr2Ptr[val-thisNbCells]=sig*(start+1);
1813             }
1814         }
1815     }
1816   arr2->setName(other->getName());
1817   if(arr2->presenceOfValue(0))
1818     return false;
1819   arr=arr2.retn();
1820   return true;
1821 }
1822
1823 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1824 {
1825   if(!other)
1826     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1827   const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1828   if(!otherC)
1829     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1830   std::vector<const MEDCouplingUMesh *> ms(2);
1831   ms[0]=this;
1832   ms[1]=otherC;
1833   return MergeUMeshesOnSameCoords(ms);
1834 }
1835
1836 /*!
1837  * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1838  * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1839  * cellIds is not given explicitely but by a range python like.
1840  * 
1841  * \param keepCoords that specifies if you want or not to keep coords as this or zip it (see ParaMEDMEM::MEDCouplingUMesh::zipCoords). If true zipCoords is \b NOT called, if false, zipCoords is called.
1842  * \return a newly allocated
1843  * 
1844  * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1845  * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1846  */
1847 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1848 {
1849   if(getMeshDimension()!=-1)
1850     return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1851   else
1852     {
1853       int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1854       if(newNbOfCells!=1)
1855         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1856       if(start!=0)
1857         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1858       incrRef();
1859       return const_cast<MEDCouplingUMesh *>(this);
1860     }
1861 }
1862
1863 /*!
1864  * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1865  * The result mesh shares or not the node coordinates array with \a this mesh depending
1866  * on \a keepCoords parameter.
1867  *  \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1868  *           to write this mesh to the MED file, its cells must be sorted using
1869  *           sortCellsInMEDFileFrmt().
1870  *  \param [in] begin - an array of cell ids to include to the new mesh.
1871  *  \param [in] end - a pointer to last-plus-one-th element of \a begin.
1872  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1873  *         array of \a this mesh, else "free" nodes are removed from the result mesh
1874  *         by calling zipCoords().
1875  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1876  *         to delete this mesh using decrRef() as it is no more needed. 
1877  *  \throw If the coordinates array is not set.
1878  *  \throw If the nodal connectivity of cells is not defined.
1879  *  \throw If any cell id in the array \a begin is not valid.
1880  *
1881  *  \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1882  *  \ref  py_mcumesh_buildPartOfMySelf "Here is a Python example".
1883  */
1884 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1885 {
1886   if(getMeshDimension()!=-1)
1887     return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1888   else
1889     {
1890       if(end-begin!=1)
1891         throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1892       if(begin[0]!=0)
1893         throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1894       incrRef();
1895       return const_cast<MEDCouplingUMesh *>(this);
1896     }
1897 }
1898
1899 /*!
1900  * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1901  *
1902  * This method allows to partially modify some cells in \b this (whose list is specified by [ \b cellIdsBg, \b cellIdsEnd ) ) with cells coming in \b otherOnSameCoordsThanThis.
1903  * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1904  * The number of cells of \b this will remain the same with this method.
1905  *
1906  * \param [in] begin begin of cell ids (included) of cells in this to assign
1907  * \param [in] end end of cell ids (excluded) of cells in this to assign
1908  * \param [in] otherOnSameCoordsThanThis an another mesh with same meshdimension than \b this with exactly the same number of cells than cell ids list in [\b cellIdsBg, \b cellIdsEnd ).
1909  *             Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1910  */
1911 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1912 {
1913   checkConnectivityFullyDefined();
1914   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1915   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1916     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1917   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1918     {
1919       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1920       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1921       throw INTERP_KERNEL::Exception(oss.str().c_str());
1922     }
1923   int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1924   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1925     {
1926       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1927       throw INTERP_KERNEL::Exception(oss.str().c_str());
1928     }
1929   int nbOfCells=getNumberOfCells();
1930   bool easyAssign=true;
1931   const int *connI=_nodal_connec_index->getConstPointer();
1932   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1933   for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1934     {
1935       if(*it>=0 && *it<nbOfCells)
1936         {
1937           easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1938         }
1939       else
1940         {
1941           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1942           throw INTERP_KERNEL::Exception(oss.str().c_str());
1943         }
1944     }
1945   if(easyAssign)
1946     {
1947       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1948       computeTypes();
1949     }
1950   else
1951     {
1952       DataArrayInt *arrOut=0,*arrIOut=0;
1953       MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
1954                                                arrOut,arrIOut);
1955       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
1956       setConnectivity(arrOut,arrIOut,true);
1957     }
1958 }
1959
1960 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1961 {
1962   checkConnectivityFullyDefined();
1963   otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1964   if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1965     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1966   if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1967     {
1968       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1969       oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1970       throw INTERP_KERNEL::Exception(oss.str().c_str());
1971     }
1972   int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
1973   if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1974     {
1975       std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" <<  nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1976       throw INTERP_KERNEL::Exception(oss.str().c_str());
1977     }
1978   int nbOfCells=getNumberOfCells();
1979   bool easyAssign=true;
1980   const int *connI=_nodal_connec_index->getConstPointer();
1981   const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1982   int it=start;
1983   for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
1984     {
1985       if(it>=0 && it<nbOfCells)
1986         {
1987           easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
1988         }
1989       else
1990         {
1991           std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
1992           throw INTERP_KERNEL::Exception(oss.str().c_str());
1993         }
1994     }
1995   if(easyAssign)
1996     {
1997       MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1998       computeTypes();
1999     }
2000   else
2001     {
2002       DataArrayInt *arrOut=0,*arrIOut=0;
2003       MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2004                                                 arrOut,arrIOut);
2005       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2006       setConnectivity(arrOut,arrIOut,true);
2007     }
2008 }                      
2009
2010 /*!
2011  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2012  * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2013  * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2014  * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2015  *
2016  * \param [in] begin input start of array of node ids.
2017  * \param [in] end input end of array of node ids.
2018  * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2019  * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2020  */
2021 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2022 {
2023   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2024   checkConnectivityFullyDefined();
2025   int tmp=-1;
2026   int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2027   std::vector<bool> fastFinder(sz,false);
2028   for(const int *work=begin;work!=end;work++)
2029     if(*work>=0 && *work<sz)
2030       fastFinder[*work]=true;
2031   int nbOfCells=getNumberOfCells();
2032   const int *conn=getNodalConnectivity()->getConstPointer();
2033   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2034   for(int i=0;i<nbOfCells;i++)
2035     {
2036       int ref=0,nbOfHit=0;
2037       for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2038         if(*work2>=0)
2039           {
2040             ref++;
2041             if(fastFinder[*work2])
2042               nbOfHit++;
2043           }
2044       if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2045         cellIdsKept->pushBackSilent(i);
2046     }
2047   cellIdsKeptArr=cellIdsKept.retn();
2048 }
2049
2050 /*!
2051  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2052  * this->getMeshDimension(), that bound some cells of \a this mesh.
2053  * The cells of lower dimension to include to the result mesh are selected basing on
2054  * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2055  * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2056  * ==\c false, a cell is copied if any its node is in the array of node ids. The
2057  * created mesh shares the node coordinates array with \a this mesh. 
2058  *  \param [in] begin - the array of node ids.
2059  *  \param [in] end - a pointer to the (last+1)-th element of \a begin.
2060  *  \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2061  *         array \a begin are added, else cells whose any node is in the
2062  *         array \a begin are added.
2063  *  \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2064  *         to delete this mesh using decrRef() as it is no more needed. 
2065  *  \throw If the coordinates array is not set.
2066  *  \throw If the nodal connectivity of cells is not defined.
2067  *  \throw If any node id in \a begin is not valid.
2068  *
2069  *  \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2070  *  \ref  py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2071  */
2072 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2073 {
2074   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2075   desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2076   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2077   desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2078   return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2079 }
2080
2081 /*!
2082  * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2083  * this->getMeshDimension(), which bound only one cell of \a this mesh.
2084  *  \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2085  *         array of \a this mesh, else "free" nodes are removed from the result mesh
2086  *         by calling zipCoords().
2087  *  \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2088  *         to delete this mesh using decrRef() as it is no more needed. 
2089  *  \throw If the coordinates array is not set.
2090  *  \throw If the nodal connectivity of cells is not defined.
2091  *
2092  *  \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2093  *  \ref  py_mcumesh_buildBoundaryMesh "Here is a Python example".
2094  */
2095 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2096 {
2097   DataArrayInt *desc=DataArrayInt::New();
2098   DataArrayInt *descIndx=DataArrayInt::New();
2099   DataArrayInt *revDesc=DataArrayInt::New();
2100   DataArrayInt *revDescIndx=DataArrayInt::New();
2101   //
2102   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2103   revDesc->decrRef();
2104   desc->decrRef();
2105   descIndx->decrRef();
2106   int nbOfCells=meshDM1->getNumberOfCells();
2107   const int *revDescIndxC=revDescIndx->getConstPointer();
2108   std::vector<int> boundaryCells;
2109   for(int i=0;i<nbOfCells;i++)
2110     if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2111       boundaryCells.push_back(i);
2112   revDescIndx->decrRef();
2113   MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2114   return ret;
2115 }
2116
2117 /*!
2118  * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2119  * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2120  * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown. 
2121  */
2122 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2123 {
2124   checkFullyDefined();
2125   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2126   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2127   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2128   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2129   //
2130   buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2131   desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2132   //
2133   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2134   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2135   const int *revDescPtr=revDesc->getConstPointer();
2136   const int *revDescIndxPtr=revDescIndx->getConstPointer();
2137   int nbOfCells=getNumberOfCells();
2138   std::vector<bool> ret1(nbOfCells,false);
2139   int sz=0;
2140   for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2141     if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2142       { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2143   //
2144   DataArrayInt *ret2=DataArrayInt::New();
2145   ret2->alloc(sz,1);
2146   int *ret2Ptr=ret2->getPointer();
2147   sz=0;
2148   for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2149     if(*it)
2150       *ret2Ptr++=sz;
2151   ret2->setName("BoundaryCells");
2152   return ret2;
2153 }
2154
2155 /*!
2156  * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2157  * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2158  * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2159  * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2160  *
2161  * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2162  * This method method returns cells ids set s = s1 + s2 where :
2163  * 
2164  *  - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2165  *  - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2166  *
2167  * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2168  *        are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2169  *
2170  * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2171  * \param [out] cellIdsRk1 a newly allocated array containing cells ids of s1+s2 \b into \b cellIdsRk0 subset. To get absolute ids of s1+s2 simply invoke
2172  *              cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2173  */
2174 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2175 {
2176   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2177     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2178   checkConnectivityFullyDefined();
2179   otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2180   if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2181     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2182   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2183   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2184   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2185   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2186   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2187   const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2188   DataArrayInt *idsOtherInConsti=0;
2189   bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2190   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2191   if(!b)
2192     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2193   std::set<int> s1;
2194   for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2195     s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2196   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2197   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2198   DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2199   ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2200   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2201   ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2202   neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2203   RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2204   neighThisPartAuto=0;
2205   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2206   const int li[2]={0,1};
2207   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2208   s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2209   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2210   s_renum1->sort();
2211   //
2212   cellIdsRk0=s0arr.retn();
2213   cellIdsRk1=s_renum1.retn();
2214 }
2215
2216 /*!
2217  * This method computes the skin of \b this. That is to say the consituting meshdim-1 mesh is built and only the boundary subpart is
2218  * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2219  * 
2220  * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2221  */
2222 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2223 {
2224   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2225   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2226   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2227   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2228   //
2229   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2230   revDesc=0; desc=0; descIndx=0;
2231   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2232   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2233   return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2234 }
2235
2236 /*!
2237  * Finds nodes lying on the boundary of \a this mesh.
2238  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2239  *          nodes. The caller is to delete this array using decrRef() as it is no
2240  *          more needed.
2241  *  \throw If the coordinates array is not set.
2242  *  \throw If the nodal connectivity of cells is node defined.
2243  *
2244  *  \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2245  *  \ref  py_mcumesh_findBoundaryNodes "Here is a Python example".
2246  */
2247 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2248 {
2249   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2250   return skin->computeFetchedNodeIds();
2251 }
2252
2253 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2254 {
2255   incrRef();
2256   return const_cast<MEDCouplingUMesh *>(this);
2257 }
2258
2259 /*!
2260  * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2261  * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2262  * This method searches for nodes needed to be duplicated. These nodes are nodes fetched by \b otherDimM1OnSameCoords which are not part of the boundary of \b otherDimM1OnSameCoords.
2263  * If a node is in the boundary of \b this \b and in the boundary of \b otherDimM1OnSameCoords this node is considerd as needed to be duplicated.
2264  * When the set of node ids \b nodeIdsToDuplicate is computed, cell ids in \b this is searched so that their connectivity includes at least 1 node in \b nodeIdsToDuplicate.
2265  *
2266  * \param [in] otherDimM1OnSameCoords a mesh lying on the same coords than \b this and with a mesh dimension equal to those of \b this minus 1. WARNING this input
2267  *             parameter is altered during the call.
2268  * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2269  * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2270  * \param [out] cellIdsNotModified cell ids int \b this that lies on \b otherDimM1OnSameCoords mesh whose connectivity do \b not need to be modified as it is the case for \b cellIdsNeededToBeRenum.
2271  *
2272  * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2273  */
2274 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2275                                             DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2276 {
2277   checkFullyDefined();
2278   otherDimM1OnSameCoords.checkFullyDefined();
2279   if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2280     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2281   if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2282     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2283   DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2284   findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2285   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2286   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2287   s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2288   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2289   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2290   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2291   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2292   cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2293   //
2294   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2295   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2296   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2297   DataArrayInt *idsTmp=0;
2298   bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2299   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2300   if(!b)
2301     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2302   MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2303   DataArrayInt *tmp0=0,*tmp1=0;
2304   ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2305   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2306   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2308   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2309   cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2310   cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2311   //
2312   cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2313   cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2314   nodeIdsToDuplicate=s3.retn();
2315 }
2316
2317 /*!
2318  * This method operates a modification of the connectivity and coords in \b this.
2319  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2320  * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2321  * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2322  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2323  * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2324  * 
2325  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2326  * 
2327  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2328  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2329  */
2330 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2331 {
2332   int nbOfNodes=getNumberOfNodes();
2333   duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2334   duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2335 }
2336
2337 /*!
2338  * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2339  * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2340  * This method is a generalization of shiftNodeNumbersInConn().
2341  *  \warning This method performs no check of validity of new ids. **Use it with care !**
2342  *  \param [in] newNodeNumbersO2N - a permutation array, of length \a
2343  *         this->getNumberOfNodes(), in "Old to New" mode. 
2344  *         See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2345  *  \throw If the nodal connectivity of cells is not defined.
2346  *
2347  *  \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2348  *  \ref  py_mcumesh_renumberNodesInConn "Here is a Python example".
2349  */
2350 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2351 {
2352   checkConnectivityFullyDefined();
2353   int *conn=getNodalConnectivity()->getPointer();
2354   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2355   int nbOfCells=getNumberOfCells();
2356   for(int i=0;i<nbOfCells;i++)
2357     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2358       {
2359         int& node=conn[iconn];
2360         if(node>=0)//avoid polyhedron separator
2361           {
2362             node=newNodeNumbersO2N[node];
2363           }
2364       }
2365   _nodal_connec->declareAsNew();
2366   updateTime();
2367 }
2368
2369 /*!
2370  * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2371  * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2372  * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2373  * 
2374  * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2375  */
2376 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2377 {
2378   checkConnectivityFullyDefined();
2379   int *conn=getNodalConnectivity()->getPointer();
2380   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2381   int nbOfCells=getNumberOfCells();
2382   for(int i=0;i<nbOfCells;i++)
2383     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2384       {
2385         int& node=conn[iconn];
2386         if(node>=0)//avoid polyhedron separator
2387           {
2388             node+=delta;
2389           }
2390       }
2391   _nodal_connec->declareAsNew();
2392   updateTime();
2393 }
2394
2395 /*!
2396  * This method operates a modification of the connectivity in \b this.
2397  * Coordinates are \b NOT considered here and will remain unchanged by this method. this->_coords can ever been null for the needs of this method.
2398  * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this 
2399  * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2400  * More explicitely the renumber array in nodes is not explicitely given in old2new to avoid to build a big array of renumbering whereas typically few node ids needs to be
2401  * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2402  * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2403  * 
2404  * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2405  * As an another consequense after the call of this method \b this can be transiently non cohrent.
2406  * 
2407  * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2408  * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2409  * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ). 
2410  */
2411 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2412 {
2413   checkConnectivityFullyDefined();
2414   std::map<int,int> m;
2415   int val=offset;
2416   for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2417     m[*work]=val;
2418   int *conn=getNodalConnectivity()->getPointer();
2419   const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2420   int nbOfCells=getNumberOfCells();
2421   for(int i=0;i<nbOfCells;i++)
2422     for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2423       {
2424         int& node=conn[iconn];
2425         if(node>=0)//avoid polyhedron separator
2426           {
2427             std::map<int,int>::iterator it=m.find(node);
2428             if(it!=m.end())
2429               node=(*it).second;
2430           }
2431       }
2432   updateTime();
2433 }
2434
2435 /*!
2436  * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2437  *
2438  * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2439  * After the call of this method the number of cells remains the same as before.
2440  *
2441  * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2442  * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2443  * be strictly in [0;this->getNumberOfCells()).
2444  *
2445  * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2446  * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2447  * should be contained in[0;this->getNumberOfCells()).
2448  * 
2449  * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2450  */
2451 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2452 {
2453   checkConnectivityFullyDefined();
2454   int nbCells=getNumberOfCells();
2455   const int *array=old2NewBg;
2456   if(check)
2457     array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2458   //
2459   const int *conn=_nodal_connec->getConstPointer();
2460   const int *connI=_nodal_connec_index->getConstPointer();
2461   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2462   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2463   const int *n2oPtr=n2o->begin();
2464   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2465   newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2466   newConn->copyStringInfoFrom(*_nodal_connec);
2467   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2468   newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2469   newConnI->copyStringInfoFrom(*_nodal_connec_index);
2470   //
2471   int *newC=newConn->getPointer();
2472   int *newCI=newConnI->getPointer();
2473   int loc=0;
2474   newCI[0]=loc;
2475   for(int i=0;i<nbCells;i++)
2476     {
2477       int pos=n2oPtr[i];
2478       int nbOfElts=connI[pos+1]-connI[pos];
2479       newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2480       loc+=nbOfElts;
2481       newCI[i+1]=loc;
2482     }
2483   //
2484   setConnectivity(newConn,newConnI);
2485   if(check)
2486     free(const_cast<int *>(array));
2487 }
2488
2489 /*!
2490  * Finds cells whose bounding boxes intersect a given bounding box.
2491  *  \param [in] bbox - an array defining the bounding box via coordinates of its
2492  *         extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2493  *         zMax (if in 3D). 
2494  *  \param [in] eps - a factor used to increase size of the bounding box of cell
2495  *         before comparing it with \a bbox. This factor is multiplied by the maximal
2496  *         extent of the bounding box of cell to produce an addition to this bounding box.
2497  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2498  *         cells. The caller is to delete this array using decrRef() as it is no more
2499  *         needed. 
2500  *  \throw If the coordinates array is not set.
2501  *  \throw If the nodal connectivity of cells is not defined.
2502  *
2503  *  \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2504  *  \ref  py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2505  */
2506 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2507 {
2508   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2509   if(getMeshDimension()==-1)
2510     {
2511       elems->pushBackSilent(0);
2512       return elems.retn();
2513     }
2514   int dim=getSpaceDimension();
2515   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2516   const int* conn      = getNodalConnectivity()->getConstPointer();
2517   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2518   const double* coords = getCoords()->getConstPointer();
2519   int nbOfCells=getNumberOfCells();
2520   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2521     {
2522       for (int i=0; i<dim; i++)
2523         {
2524           elem_bb[i*2]=std::numeric_limits<double>::max();
2525           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2526         }
2527
2528       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2529         {
2530           int node= conn[inode];
2531           if(node>=0)//avoid polyhedron separator
2532             {
2533               for (int idim=0; idim<dim; idim++)
2534                 {
2535                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2536                     {
2537                       elem_bb[idim*2] = coords[node*dim+idim] ;
2538                     }
2539                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2540                     {
2541                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2542                     }
2543                 }
2544             }
2545         }
2546       if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2547         elems->pushBackSilent(ielem);
2548     }
2549   return elems.retn();
2550 }
2551
2552 /*!
2553  * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2554  * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2555  * added in 'elems' parameter.
2556  */
2557 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2558 {
2559   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2560   if(getMeshDimension()==-1)
2561     {
2562       elems->pushBackSilent(0);
2563       return elems.retn();
2564     }
2565   int dim=getSpaceDimension();
2566   INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2567   const int* conn      = getNodalConnectivity()->getConstPointer();
2568   const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2569   const double* coords = getCoords()->getConstPointer();
2570   int nbOfCells=getNumberOfCells();
2571   for ( int ielem=0; ielem<nbOfCells;ielem++ )
2572     {
2573       for (int i=0; i<dim; i++)
2574         {
2575           elem_bb[i*2]=std::numeric_limits<double>::max();
2576           elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2577         }
2578
2579       for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2580         {
2581           int node= conn[inode];
2582           if(node>=0)//avoid polyhedron separator
2583             {
2584               for (int idim=0; idim<dim; idim++)
2585                 {
2586                   if ( coords[node*dim+idim] < elem_bb[idim*2] )
2587                     {
2588                       elem_bb[idim*2] = coords[node*dim+idim] ;
2589                     }
2590                   if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2591                     {
2592                       elem_bb[idim*2+1] = coords[node*dim+idim] ;
2593                     }
2594                 }
2595             }
2596         }
2597       if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2598         elems->pushBackSilent(ielem);
2599     }
2600   return elems.retn();
2601 }
2602
2603 /*!
2604  * Returns a type of a cell by its id.
2605  *  \param [in] cellId - the id of the cell of interest.
2606  *  \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2607  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2608  */
2609 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2610 {
2611   const int *ptI=_nodal_connec_index->getConstPointer();
2612   const int *pt=_nodal_connec->getConstPointer();
2613   if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2614     return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2615   else
2616     {
2617       std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2618       throw INTERP_KERNEL::Exception(oss.str().c_str());
2619     }
2620 }
2621
2622 /*!
2623  * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2624  * This method does not throw exception if geometric type \a type is not in \a this.
2625  * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2626  * The coordinates array is not considered here.
2627  *
2628  * \param [in] type the geometric type
2629  * \return cell ids in this having geometric type \a type.
2630  */
2631 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2632 {
2633   
2634   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2635   ret->alloc(0,1);
2636   checkConnectivityFullyDefined();
2637   int nbCells=getNumberOfCells();
2638   int mdim=getMeshDimension();
2639   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2640   if(mdim!=(int)cm.getDimension())
2641     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2642   const int *ptI=_nodal_connec_index->getConstPointer();
2643   const int *pt=_nodal_connec->getConstPointer();
2644   for(int i=0;i<nbCells;i++)
2645     {
2646       if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2647         ret->pushBackSilent(i);
2648     }
2649   return ret.retn();
2650 }
2651
2652 /*!
2653  * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2654  */
2655 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2656 {
2657   const int *ptI=_nodal_connec_index->getConstPointer();
2658   const int *pt=_nodal_connec->getConstPointer();
2659   int nbOfCells=getNumberOfCells();
2660   int ret=0;
2661   for(int i=0;i<nbOfCells;i++)
2662     if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2663       ret++;
2664   return ret;
2665 }
2666
2667 /*!
2668  * Returns the nodal connectivity of a given cell.
2669  * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2670  * all returned node ids can be used in getCoordinatesOfNode().
2671  *  \param [in] cellId - an id of the cell of interest.
2672  *  \param [in,out] conn - a vector where the node ids are appended. It is not
2673  *         cleared before the appending.
2674  *  \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2675  */
2676 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2677 {
2678   const int *ptI=_nodal_connec_index->getConstPointer();
2679   const int *pt=_nodal_connec->getConstPointer();
2680   for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2681     if(*w>=0)
2682       conn.push_back(*w);
2683 }
2684
2685 std::string MEDCouplingUMesh::simpleRepr() const
2686 {
2687   static const char msg0[]="No coordinates specified !";
2688   std::ostringstream ret;
2689   ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2690   ret << "Description of mesh : \"" << getDescription() << "\"\n";
2691   int tmpp1,tmpp2;
2692   double tt=getTime(tmpp1,tmpp2);
2693   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2694   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
2695   if(_mesh_dim>=-1)
2696     { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2697   else
2698     { ret << " Mesh dimension has not been set or is invalid !"; }
2699   if(_coords!=0)
2700     {
2701       const int spaceDim=getSpaceDimension();
2702       ret << spaceDim << "\nInfo attached on space dimension : ";
2703       for(int i=0;i<spaceDim;i++)
2704         ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2705       ret << "\n";
2706     }
2707   else
2708     ret << msg0 << "\n";
2709   ret << "Number of nodes : ";
2710   if(_coords!=0)
2711     ret << getNumberOfNodes() << "\n";
2712   else
2713     ret << msg0 << "\n";
2714   ret << "Number of cells : ";
2715   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2716     ret << getNumberOfCells() << "\n";
2717   else
2718     ret << "No connectivity specified !" << "\n";
2719   ret << "Cell types present : ";
2720   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2721     {
2722       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2723       ret << cm.getRepr() << " ";
2724     }
2725   ret << "\n";
2726   return ret.str();
2727 }
2728
2729 std::string MEDCouplingUMesh::advancedRepr() const
2730 {
2731   std::ostringstream ret;
2732   ret << simpleRepr();
2733   ret << "\nCoordinates array : \n___________________\n\n";
2734   if(_coords)
2735     _coords->reprWithoutNameStream(ret);
2736   else
2737     ret << "No array set !\n";
2738   ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2739   reprConnectivityOfThisLL(ret);
2740   return ret.str();
2741 }
2742
2743 /*!
2744  * This method returns a C++ code that is a dump of \a this.
2745  * This method will throw if this is not fully defined.
2746  */
2747 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2748 {
2749   static const char coordsName[]="coords";
2750   static const char connName[]="conn";
2751   static const char connIName[]="connI";
2752   checkFullyDefined();
2753   std::ostringstream ret; ret << "// coordinates" << std::endl;
2754   _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2755   _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2756   _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2757   ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2758   ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2759   ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2760   ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2761   return ret.str();
2762 }
2763
2764 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2765 {
2766   std::ostringstream ret;
2767   reprConnectivityOfThisLL(ret);
2768   return ret.str();
2769 }
2770
2771 /*!
2772  * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2773  * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2774  * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2775  * some algos).
2776  * 
2777  * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2778  * This method analyzes the 3 arrays of \a this. For each the following behaviour is done : if the array is null a newly one is created
2779  * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2780  */
2781 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2782 {
2783   int mdim=getMeshDimension();
2784   if(mdim<0)
2785     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2786   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2787   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2788   bool needToCpyCT=true;
2789   if(!_nodal_connec)
2790     {
2791       tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2792       needToCpyCT=false;
2793     }
2794   else
2795     {
2796       tmp1=_nodal_connec;
2797       tmp1->incrRef();
2798     }
2799   if(!_nodal_connec_index)
2800     {
2801       tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2802       needToCpyCT=false;
2803     }
2804   else
2805     {
2806       tmp2=_nodal_connec_index;
2807       tmp2->incrRef();
2808     }
2809   ret->setConnectivity(tmp1,tmp2,false);
2810   if(needToCpyCT)
2811     ret->_types=_types;
2812   if(!_coords)
2813     {
2814       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2815       ret->setCoords(coords);
2816     }
2817   else
2818     ret->setCoords(_coords);
2819   return ret.retn();
2820 }
2821
2822 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2823 {
2824   if(_nodal_connec!=0 && _nodal_connec_index!=0)
2825     {
2826       int nbOfCells=getNumberOfCells();
2827       const int *c=_nodal_connec->getConstPointer();
2828       const int *ci=_nodal_connec_index->getConstPointer();
2829       for(int i=0;i<nbOfCells;i++)
2830         {
2831           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2832           stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2833           std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2834           stream << "\n";
2835         }
2836     }
2837   else
2838     stream << "Connectivity not defined !\n";
2839 }
2840
2841 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2842 {
2843   const int *ptI=_nodal_connec_index->getConstPointer();
2844   const int *pt=_nodal_connec->getConstPointer();
2845   if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2846     return ptI[cellId+1]-ptI[cellId]-1;
2847   else
2848     return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2849 }
2850
2851 /*!
2852  * Returns types of cells of the specified part of \a this mesh.
2853  * This method avoids computing sub-mesh explicitely to get its types.
2854  *  \param [in] begin - an array of cell ids of interest.
2855  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2856  *  \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2857  *         describing the cell types. 
2858  *  \throw If the coordinates array is not set.
2859  *  \throw If the nodal connectivity of cells is not defined.
2860  *  \sa getAllTypes()
2861  */
2862 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2863 {
2864   checkFullyDefined();
2865   std::set<INTERP_KERNEL::NormalizedCellType> ret;
2866   const int *conn=_nodal_connec->getConstPointer();
2867   const int *connIndex=_nodal_connec_index->getConstPointer();
2868   for(const int *w=begin;w!=end;w++)
2869     ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2870   return ret;
2871 }
2872
2873 /*!
2874  * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2875  * a set of types of cells constituting \a this mesh. 
2876  * This method is for advanced users having prepared their connectivity before. For
2877  * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2878  *  \param [in] conn - the nodal connectivity array. 
2879  *  \param [in] connIndex - the nodal connectivity index array.
2880  *  \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2881  *         mesh is updated.
2882  */
2883 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2884 {
2885   DataArrayInt::SetArrayIn(conn,_nodal_connec);
2886   DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2887   if(isComputingTypes)
2888     computeTypes();
2889   declareAsNew();
2890 }
2891
2892 /*!
2893  * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2894  * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2895  */
2896 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2897                                                                                  _nodal_connec(0),_nodal_connec_index(0),
2898                                                                                 _types(other._types)
2899 {
2900   if(other._nodal_connec)
2901     _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2902   if(other._nodal_connec_index)
2903     _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2904 }
2905
2906 MEDCouplingUMesh::~MEDCouplingUMesh()
2907 {
2908   if(_nodal_connec)
2909     _nodal_connec->decrRef();
2910   if(_nodal_connec_index)
2911     _nodal_connec_index->decrRef();
2912 }
2913
2914 /*!
2915  * Recomputes a set of cell types of \a this mesh. For more info see
2916  * \ref MEDCouplingUMeshNodalConnectivity.
2917  */
2918 void MEDCouplingUMesh::computeTypes()
2919 {
2920   if(_nodal_connec && _nodal_connec_index)
2921     {
2922       _types.clear();
2923       const int *conn=_nodal_connec->getConstPointer();
2924       const int *connIndex=_nodal_connec_index->getConstPointer();
2925       int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2926       if (nbOfElem > 0)
2927         for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
2928           _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2929     }
2930 }
2931
2932 /*!
2933  * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2934  */
2935 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2936 {
2937   if(!_nodal_connec_index || !_nodal_connec || !_coords)
2938     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2939 }
2940
2941 /*!
2942  * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2943  */
2944 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2945 {
2946   if(!_nodal_connec_index || !_nodal_connec)
2947     throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
2948 }
2949
2950 /*!
2951  * Returns a number of cells constituting \a this mesh. 
2952  *  \return int - the number of cells in \a this mesh.
2953  *  \throw If the nodal connectivity of cells is not defined.
2954  */
2955 int MEDCouplingUMesh::getNumberOfCells() const
2956
2957   if(_nodal_connec_index)
2958     return _nodal_connec_index->getNumberOfTuples()-1;
2959   else
2960     if(_mesh_dim==-1)
2961       return 1;
2962     else
2963       throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
2964 }
2965
2966 /*!
2967  * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
2968  * mesh. For more info see \ref MEDCouplingMeshesPage.
2969  *  \return int - the dimension of \a this mesh.
2970  *  \throw If the mesh dimension is not defined using setMeshDimension().
2971  */
2972 int MEDCouplingUMesh::getMeshDimension() const
2973 {
2974   if(_mesh_dim<-1)
2975     throw INTERP_KERNEL::Exception("No mesh dimension specified !");
2976   return _mesh_dim;
2977 }
2978
2979 /*!
2980  * Returns a length of the nodal connectivity array.
2981  * This method is for test reason. Normally the integer returned is not useable by
2982  * user.  For more info see \ref MEDCouplingUMeshNodalConnectivity.
2983  *  \return int - the length of the nodal connectivity array.
2984  */
2985 int MEDCouplingUMesh::getMeshLength() const
2986 {
2987   return _nodal_connec->getNbOfElems();
2988 }
2989
2990 /*!
2991  * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
2992  */
2993 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
2994 {
2995   MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
2996   tinyInfo.push_back(getMeshDimension());
2997   tinyInfo.push_back(getNumberOfCells());
2998   if(_nodal_connec)
2999     tinyInfo.push_back(getMeshLength());
3000   else
3001     tinyInfo.push_back(-1);
3002 }
3003
3004 /*!
3005  * First step of unserialization process.
3006  */
3007 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3008 {
3009   return tinyInfo[6]<=0;
3010 }
3011
3012 /*!
3013  * Second step of serialization process.
3014  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3015  */
3016 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3017 {
3018   MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3019   if(tinyInfo[5]!=-1)
3020     a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3021 }
3022
3023 /*!
3024  * Third and final step of serialization process.
3025  */
3026 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3027 {
3028   MEDCouplingPointSet::serialize(a1,a2);
3029   if(getMeshDimension()>-1)
3030     {
3031       a1=DataArrayInt::New();
3032       a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3033       int *ptA1=a1->getPointer();
3034       const int *conn=getNodalConnectivity()->getConstPointer();
3035       const int *index=getNodalConnectivityIndex()->getConstPointer();
3036       ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3037       std::copy(conn,conn+getMeshLength(),ptA1);
3038     }
3039   else
3040     a1=0;
3041 }
3042
3043 /*!
3044  * Second and final unserialization process.
3045  * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3046  */
3047 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3048 {
3049   MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3050   setMeshDimension(tinyInfo[5]);
3051   if(tinyInfo[7]!=-1)
3052     {
3053       // Connectivity
3054       const int *recvBuffer=a1->getConstPointer();
3055       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3056       myConnecIndex->alloc(tinyInfo[6]+1,1);
3057       std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3058       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3059       myConnec->alloc(tinyInfo[7],1);
3060       std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3061       setConnectivity(myConnec, myConnecIndex);
3062     }
3063 }
3064
3065 /*!
3066  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3067  * CellIds are given using range specified by a start an end and step.
3068  */
3069 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3070 {
3071   checkFullyDefined();
3072   int ncell=getNumberOfCells();
3073   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3074   ret->_mesh_dim=_mesh_dim;
3075   ret->setCoords(_coords);
3076   int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3077   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3078   int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3079   int work=start;
3080   const int *conn=_nodal_connec->getConstPointer();
3081   const int *connIndex=_nodal_connec_index->getConstPointer();
3082   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3083     {
3084       if(work>=0 && work<ncell)
3085         {
3086           newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3087         }
3088       else
3089         {
3090           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3091           throw INTERP_KERNEL::Exception(oss.str().c_str());
3092         }
3093     }
3094   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3095   int *newConnPtr=newConn->getPointer();
3096   std::set<INTERP_KERNEL::NormalizedCellType> types;
3097   work=start;
3098   for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3099     {
3100       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3101       newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3102     }
3103   ret->setConnectivity(newConn,newConnI,false);
3104   ret->_types=types;
3105   ret->copyTinyInfoFrom(this);
3106   return ret.retn();
3107 }
3108
3109 /*!
3110  * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3111  * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3112  * The return newly allocated mesh will share the same coordinates as \a this.
3113  */
3114 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3115 {
3116   checkFullyDefined();
3117   int ncell=getNumberOfCells();
3118   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3119   ret->_mesh_dim=_mesh_dim;
3120   ret->setCoords(_coords);
3121   std::size_t nbOfElemsRet=std::distance(begin,end);
3122   int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3123   connIndexRet[0]=0;
3124   const int *conn=_nodal_connec->getConstPointer();
3125   const int *connIndex=_nodal_connec_index->getConstPointer();
3126   int newNbring=0;
3127   for(const int *work=begin;work!=end;work++,newNbring++)
3128     {
3129       if(*work>=0 && *work<ncell)
3130         connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3131       else
3132         {
3133           free(connIndexRet);
3134           std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3135           throw INTERP_KERNEL::Exception(oss.str().c_str());
3136         }
3137     }
3138   int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3139   int *connRetWork=connRet;
3140   std::set<INTERP_KERNEL::NormalizedCellType> types;
3141   for(const int *work=begin;work!=end;work++)
3142     {
3143       types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3144       connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3145     }
3146   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3147   connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3148   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3149   connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3150   ret->setConnectivity(connRetArr,connIndexRetArr,false);
3151   ret->_types=types;
3152   ret->copyTinyInfoFrom(this);
3153   return ret.retn();
3154 }
3155
3156 /*!
3157  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3158  * mesh.<br>
3159  * For 1D cells, the returned field contains lengths.<br>
3160  * For 2D cells, the returned field contains areas.<br>
3161  * For 3D cells, the returned field contains volumes.
3162  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3163  *         orientation, i.e. the volume is always positive.
3164  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3165  *         and one time . The caller is to delete this field using decrRef() as it is no
3166  *         more needed.
3167  */
3168 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3169 {
3170   std::string name="MeasureOfMesh_";
3171   name+=getName();
3172   int nbelem=getNumberOfCells();
3173   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3174   field->setName(name.c_str());
3175   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3176   array->alloc(nbelem,1);
3177   double *area_vol=array->getPointer();
3178   field->setArray(array) ; array=0;
3179   field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3180   field->synchronizeTimeWithMesh();
3181   if(getMeshDimension()!=-1)
3182     {
3183       int ipt;
3184       INTERP_KERNEL::NormalizedCellType type;
3185       int dim_space=getSpaceDimension();
3186       const double *coords=getCoords()->getConstPointer();
3187       const int *connec=getNodalConnectivity()->getConstPointer();
3188       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3189       for(int iel=0;iel<nbelem;iel++)
3190         {
3191           ipt=connec_index[iel];
3192           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3193           area_vol[iel]=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[iel+1]-ipt-1,coords,dim_space);
3194         }
3195       if(isAbs)
3196         std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3197     }
3198   else
3199     {
3200       area_vol[0]=std::numeric_limits<double>::max();
3201     }
3202   return field.retn();
3203 }
3204
3205 /*!
3206  * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3207  * mesh.<br>
3208  * For 1D cells, the returned array contains lengths.<br>
3209  * For 2D cells, the returned array contains areas.<br>
3210  * For 3D cells, the returned array contains volumes.
3211  * This method avoids building explicitly a part of \a this mesh to perform the work.
3212  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3213  *         orientation, i.e. the volume is always positive.
3214  *  \param [in] begin - an array of cell ids of interest.
3215  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3216  *  \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3217  *          delete this array using decrRef() as it is no more needed.
3218  * 
3219  *  \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3220  *  \ref  py_mcumesh_getPartMeasureField "Here is a Python example".
3221  *  \sa getMeasureField()
3222  */
3223 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3224 {
3225   std::string name="PartMeasureOfMesh_";
3226   name+=getName();
3227   int nbelem=(int)std::distance(begin,end);
3228   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3229   array->setName(name.c_str());
3230   array->alloc(nbelem,1);
3231   double *area_vol=array->getPointer();
3232   if(getMeshDimension()!=-1)
3233     {
3234       int ipt;
3235       INTERP_KERNEL::NormalizedCellType type;
3236       int dim_space=getSpaceDimension();
3237       const double *coords=getCoords()->getConstPointer();
3238       const int *connec=getNodalConnectivity()->getConstPointer();
3239       const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3240       for(const int *iel=begin;iel!=end;iel++)
3241         {
3242           ipt=connec_index[*iel];
3243           type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3244           *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3245         }
3246       if(isAbs)
3247         std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3248     }
3249   else
3250     {
3251       area_vol[0]=std::numeric_limits<double>::max();
3252     }
3253   return array.retn();
3254 }
3255
3256 /*!
3257  * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3258  * \a this one. The returned field contains the dual cell volume for each corresponding
3259  * node in \a this mesh. In other words, the field returns the getMeasureField() of
3260  *  the dual mesh in P1 sens of \a this.<br>
3261  * For 1D cells, the returned field contains lengths.<br>
3262  * For 2D cells, the returned field contains areas.<br>
3263  * For 3D cells, the returned field contains volumes.
3264  * This method is useful to check "P1*" conservative interpolators.
3265  *  \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3266  *         orientation, i.e. the volume is always positive.
3267  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3268  *          nodes and one time. The caller is to delete this array using decrRef() as
3269  *          it is no more needed.
3270  */
3271 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3272 {
3273   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3274   std::string name="MeasureOnNodeOfMesh_";
3275   name+=getName();
3276   int nbNodes=getNumberOfNodes();
3277   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3278   double cst=1./((double)getMeshDimension()+1.);
3279   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3280   array->alloc(nbNodes,1);
3281   double *valsToFill=array->getPointer();
3282   std::fill(valsToFill,valsToFill+nbNodes,0.);
3283   const double *values=tmp->getArray()->getConstPointer();
3284   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3285   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3286   getReverseNodalConnectivity(da,daInd);
3287   const int *daPtr=da->getConstPointer();
3288   const int *daIPtr=daInd->getConstPointer();
3289   for(int i=0;i<nbNodes;i++)
3290     for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3291       valsToFill[i]+=cst*values[*cell];
3292   ret->setMesh(this);
3293   ret->setArray(array);
3294   return ret.retn();
3295 }
3296
3297 /*!
3298  * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3299  * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3300  * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3301  * and are normalized.
3302  * <br> \a this can be either 
3303  * - a  2D mesh in 2D or 3D space or 
3304  * - an 1D mesh in 2D space.
3305  * 
3306  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3307  *          cells and one time. The caller is to delete this field using decrRef() as
3308  *          it is no more needed.
3309  *  \throw If the nodal connectivity of cells is not defined.
3310  *  \throw If the coordinates array is not set.
3311  *  \throw If the mesh dimension is not set.
3312  *  \throw If the mesh and space dimension is not as specified above.
3313  */
3314 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3315 {
3316   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3317     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3318   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3319   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3320   int nbOfCells=getNumberOfCells();
3321   int nbComp=getMeshDimension()+1;
3322   array->alloc(nbOfCells,nbComp);
3323   double *vals=array->getPointer();
3324   const int *connI=_nodal_connec_index->getConstPointer();
3325   const int *conn=_nodal_connec->getConstPointer();
3326   const double *coords=_coords->getConstPointer();
3327   if(getMeshDimension()==2)
3328     {
3329       if(getSpaceDimension()==3)
3330         {
3331           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3332           const double *locPtr=loc->getConstPointer();
3333           for(int i=0;i<nbOfCells;i++,vals+=3)
3334             {
3335               int offset=connI[i];
3336               INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3337               double n=INTERP_KERNEL::norm<3>(vals);
3338               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3339             }
3340         }
3341       else
3342         {
3343           MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3344           const double *isAbsPtr=isAbs->getArray()->begin();
3345           for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3346             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3347         }
3348     }
3349   else//meshdimension==1
3350     {
3351       double tmp[2];
3352       for(int i=0;i<nbOfCells;i++)
3353         {
3354           int offset=connI[i];
3355           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3356           double n=INTERP_KERNEL::norm<2>(tmp);
3357           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3358           *vals++=-tmp[1];
3359           *vals++=tmp[0];
3360         }
3361     }
3362   ret->setArray(array);
3363   ret->setMesh(this);
3364   ret->synchronizeTimeWithSupport();
3365   return ret.retn();
3366 }
3367
3368 /*!
3369  * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3370  * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3371  * and are normalized.
3372  * <br> \a this can be either 
3373  * - a  2D mesh in 2D or 3D space or 
3374  * - an 1D mesh in 2D space.
3375  * 
3376  * This method avoids building explicitly a part of \a this mesh to perform the work.
3377  *  \param [in] begin - an array of cell ids of interest.
3378  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3379  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3380  *          cells and one time. The caller is to delete this field using decrRef() as
3381  *          it is no more needed.
3382  *  \throw If the nodal connectivity of cells is not defined.
3383  *  \throw If the coordinates array is not set.
3384  *  \throw If the mesh dimension is not set.
3385  *  \throw If the mesh and space dimension is not as specified above.
3386  *  \sa buildOrthogonalField()
3387  *
3388  *  \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3389  *  \ref  py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3390  */
3391 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3392 {
3393   if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3394     throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3395   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3396   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3397   std::size_t nbelems=std::distance(begin,end);
3398   int nbComp=getMeshDimension()+1;
3399   array->alloc((int)nbelems,nbComp);
3400   double *vals=array->getPointer();
3401   const int *connI=_nodal_connec_index->getConstPointer();
3402   const int *conn=_nodal_connec->getConstPointer();
3403   const double *coords=_coords->getConstPointer();
3404   if(getMeshDimension()==2)
3405     {
3406       if(getSpaceDimension()==3)
3407         {
3408           MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3409           const double *locPtr=loc->getConstPointer();
3410           for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3411             {
3412               int offset=connI[*i];
3413               INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3414               double n=INTERP_KERNEL::norm<3>(vals);
3415               std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3416             }
3417         }
3418       else
3419         {
3420           for(std::size_t i=0;i<nbelems;i++)
3421             { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3422         }
3423     }
3424   else//meshdimension==1
3425     {
3426       double tmp[2];
3427       for(const int *i=begin;i!=end;i++)
3428         {
3429           int offset=connI[*i];
3430           std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3431           double n=INTERP_KERNEL::norm<2>(tmp);
3432           std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3433           *vals++=-tmp[1];
3434           *vals++=tmp[0];
3435         }
3436     }
3437   ret->setArray(array);
3438   ret->setMesh(this);
3439   ret->synchronizeTimeWithSupport();
3440   return ret.retn();
3441 }
3442
3443 /*!
3444  * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3445  * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3446  * and are \b not normalized.
3447  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3448  *          cells and one time. The caller is to delete this field using decrRef() as
3449  *          it is no more needed.
3450  *  \throw If the nodal connectivity of cells is not defined.
3451  *  \throw If the coordinates array is not set.
3452  *  \throw If \a this->getMeshDimension() != 1.
3453  *  \throw If \a this mesh includes cells of type other than SEG2.
3454  */
3455 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3456 {
3457    if(getMeshDimension()!=1)
3458     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3459    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3460      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3461    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3462    MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3463    int nbOfCells=getNumberOfCells();
3464    int spaceDim=getSpaceDimension();
3465    array->alloc(nbOfCells,spaceDim);
3466    double *pt=array->getPointer();
3467    const double *coo=getCoords()->getConstPointer();
3468    std::vector<int> conn;
3469    conn.reserve(2);
3470    for(int i=0;i<nbOfCells;i++)
3471      {
3472        conn.resize(0);
3473        getNodeIdsOfCell(i,conn);
3474        pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3475      }
3476    ret->setArray(array);
3477    ret->setMesh(this);
3478    ret->synchronizeTimeWithSupport();
3479    return ret.retn();   
3480 }
3481
3482 /*!
3483  * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3484  * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3485  * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3486  * from. If a result face is shared by two 3D cells, then the face in included twice in
3487  * the result mesh.
3488  *  \param [in] origin - 3 components of a point defining location of the plane.
3489  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3490  *         must be greater than 1e-6.
3491  *  \param [in] eps - half-thickness of the plane.
3492  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3493  *         producing correspondent 2D cells. The caller is to delete this array
3494  *         using decrRef() as it is no more needed.
3495  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3496  *         not share the node coordinates array with \a this mesh. The caller is to
3497  *         delete this mesh using decrRef() as it is no more needed.  
3498  *  \throw If the coordinates array is not set.
3499  *  \throw If the nodal connectivity of cells is not defined.
3500  *  \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3501  *  \throw If magnitude of \a vec is less than 1e-6.
3502  *  \throw If the plane does not intersect any 3D cell of \a this mesh.
3503  *  \throw If \a this includes quadratic cells.
3504  */
3505 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3506 {
3507   checkFullyDefined();
3508   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3509     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3510   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3511   if(candidates->empty())
3512     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3513   std::vector<int> nodes;
3514   DataArrayInt *cellIds1D=0;
3515   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3516   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3517   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3518   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3519   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3520   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3521   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3522   revDesc2=0; revDescIndx2=0;
3523   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3524   revDesc1=0; revDescIndx1=0;
3525   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3526   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3527   //
3528   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3529   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3530     cut3DCurve[*it]=-1;
3531   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3532   std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3533   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3534                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3535                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3536   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3537   connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3538   subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3539   if(cellIds2->empty())
3540     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3541   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3542   ret->setCoords(mDesc1->getCoords());
3543   ret->setConnectivity(conn,connI,true);
3544   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3545   return ret.retn();
3546 }
3547
3548 /*!
3549  * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3550 addition to the mesh, returns a new DataArrayInt, of length equal to the number of 1D cells in the result mesh, holding, for each cell in the result mesh, an id of a 2D cell it comes
3551 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3552 the result mesh.
3553  *  \param [in] origin - 3 components of a point defining location of the plane.
3554  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3555  *         must be greater than 1e-6.
3556  *  \param [in] eps - half-thickness of the plane.
3557  *  \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3558  *         producing correspondent segments. The caller is to delete this array
3559  *         using decrRef() as it is no more needed.
3560  *  \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3561  *         mesh in 3D space. This mesh does not share the node coordinates array with
3562  *         \a this mesh. The caller is to delete this mesh using decrRef() as it is
3563  *         no more needed. 
3564  *  \throw If the coordinates array is not set.
3565  *  \throw If the nodal connectivity of cells is not defined.
3566  *  \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3567  *  \throw If magnitude of \a vec is less than 1e-6.
3568  *  \throw If the plane does not intersect any 2D cell of \a this mesh.
3569  *  \throw If \a this includes quadratic cells.
3570  */
3571 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3572 {
3573   checkFullyDefined();
3574   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3575     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3576   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3577   if(candidates->empty())
3578     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3579   std::vector<int> nodes;
3580   DataArrayInt *cellIds1D=0;
3581   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3582   subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3583   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3584   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3585   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3586   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3587   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3588   mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3589   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3590   //
3591   std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3592   for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3593     cut3DCurve[*it]=-1;
3594   mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3595   int ncellsSub=subMesh->getNumberOfCells();
3596   std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3597   AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3598                               mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3599                               desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3600   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3601   conn->alloc(0,1);
3602   const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3603   const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3604   for(int i=0;i<ncellsSub;i++)
3605     {
3606       if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3607         {
3608           if(cut3DSurf[i].first!=-2)
3609             {
3610               conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3611               connI->pushBackSilent(conn->getNumberOfTuples());
3612               cellIds2->pushBackSilent(i);
3613             }
3614           else
3615             {
3616               int cellId3DSurf=cut3DSurf[i].second;
3617               int offset=nodalI[cellId3DSurf]+1;
3618               int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3619               for(int j=0;j<nbOfEdges;j++)
3620                 {
3621                   conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3622                   connI->pushBackSilent(conn->getNumberOfTuples());
3623                   cellIds2->pushBackSilent(cellId3DSurf);
3624                 }
3625             }
3626         }
3627     }
3628   if(cellIds2->empty())
3629     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3630   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3631   ret->setCoords(mDesc1->getCoords());
3632   ret->setConnectivity(conn,connI,true);
3633   cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3634   return ret.retn();
3635 }
3636
3637 /*!
3638  * Finds cells whose bounding boxes intersect a given plane.
3639  *  \param [in] origin - 3 components of a point defining location of the plane.
3640  *  \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3641  *         must be greater than 1e-6.
3642  *  \param [in] eps - half-thickness of the plane.
3643  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3644  *         cells. The caller is to delete this array using decrRef() as it is no more
3645  *         needed.
3646  *  \throw If the coordinates array is not set.
3647  *  \throw If the nodal connectivity of cells is not defined.
3648  *  \throw If \a this->getSpaceDimension() != 3.
3649  *  \throw If magnitude of \a vec is less than 1e-6.
3650  *  \sa buildSlice3D()
3651  */
3652 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3653 {
3654   checkFullyDefined();
3655   if(getSpaceDimension()!=3)
3656     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3657   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3658   if(normm<1e-6)
3659     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3660   double vec2[3];
3661   vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3662   double angle=acos(vec[2]/normm);
3663   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3664   double bbox[6];
3665   if(angle>eps)
3666     {
3667       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3668       MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3669       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3670       mw->setCoords(coo);
3671       mw->getBoundingBox(bbox);
3672       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3673       cellIds=mw->getCellsInBoundingBox(bbox,eps);
3674     }
3675   else
3676     {
3677       getBoundingBox(bbox);
3678       bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3679       cellIds=getCellsInBoundingBox(bbox,eps);
3680     }
3681   return cellIds.retn();
3682 }
3683
3684 /*!
3685  * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3686  * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3687  * No consideration of coordinate is done by this method.
3688  * A 1D mesh is said contiguous if : a cell i with nodal connectivity (k,p) the cell i+1 the nodal connectivity should be (p,m)
3689  * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3690  */
3691 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3692 {
3693   if(getMeshDimension()!=1)
3694     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3695   int nbCells=getNumberOfCells();
3696   if(nbCells<1)
3697     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3698   const int *connI=_nodal_connec_index->getConstPointer();
3699   const int *conn=_nodal_connec->getConstPointer();
3700   int ref=conn[connI[0]+2];
3701   for(int i=1;i<nbCells;i++)
3702     {
3703       if(conn[connI[i]+1]!=ref)
3704         return false;
3705       ref=conn[connI[i]+2];
3706     }
3707   return true;
3708 }
3709
3710 /*!
3711  * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3712  * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3713  * \param pt reference point of the line
3714  * \param v normalized director vector of the line
3715  * \param eps max precision before throwing an exception
3716  * \param res output of size this->getNumberOfCells
3717  */
3718 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3719 {
3720   if(getMeshDimension()!=1)
3721     throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3722    if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3723      throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3724    if(getSpaceDimension()!=3)
3725      throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3726    MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3727    const double *fPtr=f->getArray()->getConstPointer();
3728    double tmp[3];
3729    for(int i=0;i<getNumberOfCells();i++)
3730      {
3731        const double *tmp1=fPtr+3*i;
3732        tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3733        tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3734        tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3735        double n1=INTERP_KERNEL::norm<3>(tmp);
3736        n1/=INTERP_KERNEL::norm<3>(tmp1);
3737        if(n1>eps)
3738          throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3739      }
3740    const double *coo=getCoords()->getConstPointer();
3741    for(int i=0;i<getNumberOfNodes();i++)
3742      {
3743        std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3744        std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3745        res[i]=std::accumulate(tmp,tmp+3,0.);
3746      }
3747 }
3748
3749 /*!
3750  * This method computes the distance from a point \a pt to \a this and the first \a cellId in \a this corresponding to the returned distance. 
3751  * \a this is expected to be a mesh so that its space dimension is equal to its
3752  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3753  * Distance from \a ptBg to \a ptEnd is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates).
3754  
3755  * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
3756  * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
3757  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3758  *
3759  * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3760  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3761  *
3762  * \param [in] ptBg the start pointer (included) of the coordinates of the point
3763  * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3764  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3765  * \return the positive value of the distance.
3766  * \throw if distance from \a ptBg to \a ptEnd is not equal to the space dimension. An exception is also thrown if mesh dimension of \a this is not equal to space
3767  * dimension - 1.
3768  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3769  */
3770 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
3771 {
3772   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3773   if(meshDim!=spaceDim-1)
3774     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3775   if(meshDim!=2 && meshDim!=1)
3776     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3777   checkFullyDefined();
3778   if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3779     { std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoint : input point has to have dimension equal to the space dimension of this (" << spaceDim << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
3780   DataArrayInt *ret1=0;
3781   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3782   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3783   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3784   cellId=*ret1Safe->begin();
3785   return *ret0->begin();
3786 }
3787
3788 /*!
3789  * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3790  *  to \a this  and the first \a cellId in \a this corresponding to the returned distance. 
3791  * WARNING, if there is some orphan nodes in \a this (nodes not fetched by any cells in \a this ( see MEDCouplingUMesh::zipCoords ) ) these nodes will ** not ** been taken
3792  * into account in this method. Only cells and nodes lying on them are considered in the algorithm (even if one of these orphan nodes is closer than returned distance).
3793  * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3794  * 
3795  * \a this is expected to be a mesh so that its space dimension is equal to its
3796  * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3797  * Number of components of \a pts is expected to be equal to the space dimension. \a this is also expected to be fully defined (connectivity and coordinates).
3798  *
3799  * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3800  * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3801  *
3802  * \param [in] pts the list of points in which each tuple represents a point
3803  * \param [out] cellIds a newly allocated object that tells for each point in \a pts the first cell id in \a this that minimizes the distance.
3804  * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3805  * \throw if number of components of \a pts is not equal to the space dimension.
3806  * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3807  * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3808  */
3809 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
3810 {
3811   if(!pts)
3812     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3813   pts->checkAllocated();
3814   int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3815   if(meshDim!=spaceDim-1)
3816     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3817   if(meshDim!=2 && meshDim!=1)
3818     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3819   if(pts->getNumberOfComponents()!=spaceDim)
3820     {
3821       std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3822       throw INTERP_KERNEL::Exception(oss.str().c_str());
3823     }
3824   checkFullyDefined();
3825   int nbCells=getNumberOfCells();
3826   if(nbCells==0)
3827     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3828   int nbOfPts=pts->getNumberOfTuples();
3829   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3830   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3831   const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3832   double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3833   std::vector<double> bbox;
3834   getBoundingBoxForBBTree(bbox);
3835   switch(spaceDim)
3836     {
3837     case 3:
3838       {
3839         BBTreeDst<3> myTree(&bbox[0],0,0,nbCells);
3840         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3841           {
3842             double x=std::numeric_limits<double>::max();
3843             std::vector<int> elems;
3844             myTree.getMinDistanceOfMax(ptsPtr,x);
3845             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3846             DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3847           }
3848         break;
3849       }
3850     case 2:
3851       {
3852         BBTreeDst<2> myTree(&bbox[0],0,0,nbCells);
3853         for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3854           {
3855             double x=std::numeric_limits<double>::max();
3856             std::vector<int> elems;
3857             myTree.getMinDistanceOfMax(ptsPtr,x);
3858             myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3859             DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3860           }
3861         break;
3862       }
3863     default:
3864       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3865     }
3866   cellIds=ret1.retn();
3867   return ret0.retn();
3868 }
3869
3870 /*!
3871  * \param [in] pt the start pointer (included) of the coordinates of the point
3872  * \param [in] cellIdsBg the start pointer (included) of cellIds
3873  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3874  * \param [in] nc nodal connectivity
3875  * \param [in] ncI nodal connectivity index
3876  * \param [in,out] ret0 the min distance between \a this and the external input point
3877  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3878  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3879  */
3880 void MEDCouplingUMesh::DistanceToPoint3DSurfAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId) throw(INTERP_KERNEL::Exception)
3881 {
3882   cellId=-1;
3883   ret0=std::numeric_limits<double>::max();
3884   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3885     {
3886       switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3887         {
3888         case INTERP_KERNEL::NORM_TRI3:
3889           {
3890             double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3891             if(tmp<ret0)
3892               { ret0=tmp; cellId=*zeCell; }
3893             break;
3894           }
3895         case INTERP_KERNEL::NORM_QUAD4:
3896         case INTERP_KERNEL::NORM_POLYGON:
3897           {
3898             double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3899             if(tmp<ret0)
3900               { ret0=tmp; cellId=*zeCell; }
3901             break;
3902           }
3903         default:
3904           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3905         }
3906     }
3907 }
3908
3909 /*!
3910  * \param [in] pt the start pointer (included) of the coordinates of the point
3911  * \param [in] cellIdsBg the start pointer (included) of cellIds
3912  * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3913  * \param [in] nc nodal connectivity
3914  * \param [in] ncI nodal connectivity index
3915  * \param [in,out] ret0 the min distance between \a this and the external input point
3916  * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3917  * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3918  */
3919 void MEDCouplingUMesh::DistanceToPoint2DCurveAlg(const double *pt, const int *cellIdsBg, const int *cellIdsEnd, const double *coords, const int *nc, const int *ncI, double& ret0, int& cellId) throw(INTERP_KERNEL::Exception)
3920 {
3921   cellId=-1;
3922   ret0=std::numeric_limits<double>::max();
3923   for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3924     {
3925        switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3926         {
3927         case INTERP_KERNEL::NORM_SEG2:
3928           {
3929             std::size_t uselessEntry=0;
3930             double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
3931             tmp=sqrt(tmp);
3932             if(tmp<ret0)
3933               { ret0=tmp; cellId=*zeCell; }
3934             break;
3935           }
3936         default:
3937           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3938         }
3939     }
3940 }
3941
3942 /*!
3943  * Finds cells in contact with a ball (i.e. a point with precision). 
3944  * \warning This method is suitable if the caller intends to evaluate only one
3945  *          point, for more points getCellsContainingPoints() is recommended as it is
3946  *          faster. 
3947  *  \param [in] pos - array of coordinates of the ball central point.
3948  *  \param [in] eps - ball radius.
3949  *  \return int - a smallest id of cells being in contact with the ball, -1 in case
3950  *         if there are no such cells.
3951  *  \throw If the coordinates array is not set.
3952  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
3953  */
3954 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
3955 {
3956   std::vector<int> elts;
3957   getCellsContainingPoint(pos,eps,elts);
3958   if(elts.empty())
3959     return -1;
3960   return elts.front();
3961 }
3962
3963 /*!
3964  * Finds cells in contact with a ball (i.e. a point with precision).
3965  * \warning This method is suitable if the caller intends to evaluate only one
3966  *          point, for more points getCellsContainingPoints() is recommended as it is
3967  *          faster. 
3968  *  \param [in] pos - array of coordinates of the ball central point.
3969  *  \param [in] eps - ball radius.
3970  *  \param [in,out] elts - vector returning ids of the found cells. It is cleared
3971  *         before inserting ids.
3972  *  \throw If the coordinates array is not set.
3973  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
3974  *
3975  *  \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
3976  *  \ref  py_mcumesh_getCellsContainingPoint "Here is a Python example".
3977  */
3978 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
3979 {
3980   std::vector<int> eltsIndex;
3981   getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
3982 }
3983
3984 /// @cond INTERNAL
3985
3986 namespace ParaMEDMEM
3987 {
3988   template<const int SPACEDIMM>
3989   class DummyClsMCUG
3990   {
3991   public:
3992     static const int MY_SPACEDIM=SPACEDIMM;
3993     static const int MY_MESHDIM=8;
3994     typedef int MyConnType;
3995     static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
3996     // begin
3997     // useless, but for windows compilation ...
3998     const double* getCoordinatesPtr() const { return 0; }
3999     const int* getConnectivityPtr() const { return 0; }
4000     const int* getConnectivityIndexPtr() const { return 0; }
4001     INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4002     // end
4003   };
4004
4005   INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4006   {
4007     INTERP_KERNEL::Edge *ret=0;
4008     switch(typ)
4009       {
4010       case INTERP_KERNEL::NORM_SEG2:
4011         {
4012           ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4013           break;
4014         }
4015       case INTERP_KERNEL::NORM_SEG3:
4016         {
4017           INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4018           INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4019           INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4020           bool colinearity=inters.areColinears();
4021           delete e1; delete e2;
4022           if(colinearity)
4023             ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4024           else
4025             ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4026           mapp2[bg[2]].second=false;
4027           break;
4028         }
4029       default:
4030         throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4031       }
4032     return ret;
4033   }
4034
4035   /*!
4036    * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed be the sub set of cells in 'candidates' and the global mesh 'mDesc'.
4037    * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4038    * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4039    */
4040   INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4041   {
4042     mapp.clear();
4043     std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;//bool is for a flag specifying if node is boundary (true) or only a middle for SEG3.
4044     const double *coo=mDesc->getCoords()->getConstPointer();
4045     const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4046     const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4047     std::set<int> s;
4048     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4049       s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4050     for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4051       {
4052         INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4053         mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4054       }
4055     INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4056     for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4057       {
4058         INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4059         ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4060       }
4061     for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4062       {
4063         if((*it2).second.second)
4064           mapp[(*it2).second.first]=(*it2).first;
4065         ((*it2).second.first)->decrRef();
4066       }
4067     return ret;
4068   }
4069
4070   INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4071   {
4072     if(nodeId>=offset2)
4073       {
4074         int locId=nodeId-offset2;
4075         return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4076       }
4077     if(nodeId>=offset1)
4078       {
4079         int locId=nodeId-offset1;
4080         return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4081       }
4082     return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4083   }
4084
4085   void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4086                                         const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4087                                         /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4088   {
4089     for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4090       {
4091         int eltId1=abs(*desc1)-1;
4092         for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4093           {
4094             std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4095             if(it==mappRev.end())
4096               {
4097                 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4098                 mapp[node]=*it1;
4099                 mappRev[*it1]=node;
4100               }
4101           }
4102       }
4103   }
4104 }
4105
4106 /// @endcond
4107
4108 template<int SPACEDIM>
4109 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4110                                                    double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4111 {
4112   std::vector<double> bbox;
4113   eltsIndex.resize(nbOfPoints+1);
4114   eltsIndex[0]=0;
4115   elts.clear();
4116   getBoundingBoxForBBTree(bbox);
4117   int nbOfCells=getNumberOfCells();
4118   const int *conn=_nodal_connec->getConstPointer();
4119   const int *connI=_nodal_connec_index->getConstPointer();
4120   double bb[2*SPACEDIM];
4121   BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4122   for(int i=0;i<nbOfPoints;i++)
4123     {
4124       eltsIndex[i+1]=eltsIndex[i];
4125       for(int j=0;j<SPACEDIM;j++)
4126         {
4127           bb[2*j]=pos[SPACEDIM*i+j];
4128           bb[2*j+1]=pos[SPACEDIM*i+j];
4129         }
4130       std::vector<int> candidates;
4131       myTree.getIntersectingElems(bb,candidates);
4132       for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4133         {
4134           int sz=connI[(*iter)+1]-connI[*iter]-1;
4135           if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4136                                                                                                (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4137                                                                                                coords,conn+connI[*iter]+1,sz,eps))
4138             {
4139               eltsIndex[i+1]++;
4140               elts.push_back(*iter);
4141             }
4142         }
4143     }
4144 }
4145 /*!
4146  * Finds cells in contact with several balls (i.e. points with precision).
4147  * This method is an extension of getCellContainingPoint() and
4148  * getCellsContainingPoint() for the case of multiple points.
4149  *  \param [in] pos - an array of coordinates of points in full interlace mode :
4150  *         X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4151  *         this->getSpaceDimension() * \a nbOfPoints 
4152  *  \param [in] nbOfPoints - number of points to locate within \a this mesh.
4153  *  \param [in] eps - radius of balls (i.e. the precision).
4154  *  \param [in,out] elts - vector returning ids of found cells.
4155  *  \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4156  *         dividing cell ids in \a elts into groups each referring to one
4157  *         point. Its every element (except the last one) is an index pointing to the
4158  *         first id of a group of cells. For example cells in contact with the *i*-th
4159  *         point are described by following range of indices:
4160  *         [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4161  *         \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4162  *         Number of cells in contact with the *i*-th point is
4163  *         \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4164  *  \throw If the coordinates array is not set.
4165  *  \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4166  *
4167  *  \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4168  *  \ref  py_mcumesh_getCellsContainingPoints "Here is a Python example".
4169  */
4170 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4171                                                 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4172 {
4173   int spaceDim=getSpaceDimension();
4174   int mDim=getMeshDimension();
4175   if(spaceDim==3)
4176     {
4177       if(mDim==3)
4178         {
4179           const double *coords=_coords->getConstPointer();
4180           getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4181         }
4182       /*else if(mDim==2)
4183         {
4184           
4185         }*/
4186       else
4187         throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4188     }
4189   else if(spaceDim==2)
4190     {
4191       if(mDim==2)
4192         {
4193           const double *coords=_coords->getConstPointer();
4194           getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4195         }
4196       else
4197         throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4198     }
4199   else if(spaceDim==1)
4200     {
4201       if(mDim==1)
4202         {
4203           const double *coords=_coords->getConstPointer();
4204           getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4205         }
4206       else
4207         throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4208     }
4209   else
4210     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4211 }
4212
4213 /*!
4214  * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4215  * least two its edges intersect each other anywhere except their extremities. An
4216  * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4217  *  \param [in,out] cells - a vector returning ids of the found cells. It is not
4218  *         cleared before filling in.
4219  *  \param [in] eps - precision.
4220  *  \throw If \a this->getMeshDimension() != 2.
4221  *  \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4222  */
4223 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4224 {
4225   const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4226   if(getMeshDimension()!=2)
4227     throw INTERP_KERNEL::Exception(msg);
4228   int spaceDim=getSpaceDimension();
4229   if(spaceDim!=2 && spaceDim!=3)
4230     throw INTERP_KERNEL::Exception(msg);
4231   const int *conn=_nodal_connec->getConstPointer();
4232   const int *connI=_nodal_connec_index->getConstPointer();
4233   int nbOfCells=getNumberOfCells();
4234   std::vector<double> cell2DinS2;
4235   for(int i=0;i<nbOfCells;i++)
4236     {
4237       int offset=connI[i];
4238       int nbOfNodesForCell=connI[i+1]-offset-1;
4239       if(nbOfNodesForCell<=3)
4240         continue;
4241       bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4242       project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4243       if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4244         cells.push_back(i);
4245       cell2DinS2.clear();
4246     }
4247 }
4248
4249 /*!
4250  * This method is typically requested to unbutterfly 2D linear cells in \b this.
4251  *
4252  * This method expects that space dimension is equal to 2 and mesh dimension is equal to 2 too. If it is not the case an INTERP_KERNEL::Exception will be thrown.
4253  * This method works only for linear 2D cells. If there is any of non linear cells (INTERP_KERNEL::NORM_QUAD8 for example) an INTERP_KERNEL::Exception will be thrown too.
4254  * 
4255  * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4256  * This convex envelop is computed using Jarvis march algorithm.
4257  * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4258  * Only connectivity of some cells could be modified if those cells were not representing a convex envelop. If a cell already equals its convex envelop (regardless orientation)
4259  * its connectivity will remain unchanged. If the computation leads to a modification of nodal connectivity of a cell its geometric type will be modified to INTERP_KERNEL::NORM_POLYGON.
4260  *
4261  * \return a newly allocated array containing cellIds that have been modified if any. If no cells have been impacted by this method NULL is returned.
4262  */
4263 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4264 {
4265   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4266     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D  works only for meshDim=2 and spaceDim=2 !");
4267   checkFullyDefined();
4268   const double *coords=getCoords()->getConstPointer();
4269   int nbOfCells=getNumberOfCells();
4270   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4271   nodalConnecIndexOut->alloc(nbOfCells+1,1);
4272   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4273   int *workIndexOut=nodalConnecIndexOut->getPointer();
4274   *workIndexOut=0;
4275   const int *nodalConnecIn=_nodal_connec->getConstPointer();
4276   const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4277   std::set<INTERP_KERNEL::NormalizedCellType> types;
4278   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4279   isChanged->alloc(0,1);
4280   for(int i=0;i<nbOfCells;i++,workIndexOut++)
4281     {
4282       int pos=nodalConnecOut->getNumberOfTuples();
4283       if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4284         isChanged->pushBackSilent(i);
4285       types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4286       workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4287     }
4288   if(isChanged->empty())
4289     return 0;
4290   setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4291   _types=types;
4292   return isChanged.retn();
4293 }
4294
4295 /*!
4296  * This method is \b NOT const because it can modify \a this.
4297  * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4298  * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4299  * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4300  * \b 1 for translation and rotation around point of 'mesh1D'.
4301  * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.  
4302  */
4303 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4304 {
4305   checkFullyDefined();
4306   mesh1D->checkFullyDefined();
4307   if(!mesh1D->isContiguous1D())
4308     throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4309   if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4310     throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4311   if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4312     throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4313   if(mesh1D->getMeshDimension()!=1)
4314     throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4315   bool isQuad=false;
4316   if(isPresenceOfQuadratic())
4317     {
4318       if(mesh1D->isFullyQuadratic())
4319         isQuad=true;
4320       else
4321         throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4322     }
4323   zipCoords();
4324   int oldNbOfNodes=getNumberOfNodes();
4325   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4326   switch(policy)
4327     {
4328     case 0:
4329       {
4330         newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4331         break;
4332       }
4333     case 1:
4334       {
4335         newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4336         break;
4337       }
4338     default:
4339       throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4340     }
4341   setCoords(newCoords);
4342   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4343   updateTime();
4344   return ret.retn();
4345 }
4346
4347 /*!
4348  * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4349  * If it is not the case an exception will be thrown.
4350  * This method is non const because the coordinate of \a this can be appended with some new points issued from
4351  * intersection of plane defined by ('origin','vec').
4352  * This method has one in/out parameter : 'cut3DCurve'.
4353  * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4354  * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4355  * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4356  * This method will throw an exception if \a this contains a non linear segment.
4357  */
4358 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4359 {
4360   checkFullyDefined();
4361   if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4362     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4363   int ncells=getNumberOfCells();
4364   int nnodes=getNumberOfNodes();
4365   double vec2[3],vec3[3],vec4[3];
4366   double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4367   if(normm<1e-6)
4368     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4369   vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4370   const int *conn=_nodal_connec->getConstPointer();
4371   const int *connI=_nodal_connec_index->getConstPointer();
4372   const double *coo=_coords->getConstPointer();
4373   std::vector<double> addCoo;
4374   for(int i=0;i<ncells;i++)
4375     {
4376       if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4377         {
4378           if(cut3DCurve[i]==-2)
4379             {
4380               int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4381               vec3[0]=coo[3*endd]-coo[3*st]; vec3[1]=coo[3*endd+1]-coo[3*st+1]; vec3[2]=coo[3*endd+2]-coo[3*st+2];
4382               double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4383               double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4384               if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4385                 {
4386                   const double *st2=coo+3*st;
4387                   vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4388                   double pos=-(vec4[0]*vec2[0]+vec4[1]*vec2[1]+vec4[2]*vec2[2])/((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2]));
4389                   if(pos>eps && pos<1-eps)
4390                     {
4391                       int nNode=((int)addCoo.size())/3;
4392                       vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4393                       addCoo.insert(addCoo.end(),vec4,vec4+3);
4394                       cut3DCurve[i]=nnodes+nNode;
4395                     }
4396                 }
4397             }
4398         }
4399       else
4400         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4401     }
4402   if(!addCoo.empty())
4403     {
4404       int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4405       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4406       coo2->alloc(newNbOfNodes,3);
4407       double *tmp=coo2->getPointer();
4408       tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4409       std::copy(addCoo.begin(),addCoo.end(),tmp);
4410       DataArrayDouble::SetArrayIn(coo2,_coords);
4411     }
4412 }
4413
4414 /*!
4415  * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4416  * \param mesh1D is the input 1D mesh used for translation computation.
4417  * \return newCoords new coords filled by this method. 
4418  */
4419 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4420 {
4421   int oldNbOfNodes=getNumberOfNodes();
4422   int nbOf1DCells=mesh1D->getNumberOfCells();
4423   int spaceDim=getSpaceDimension();
4424   DataArrayDouble *ret=DataArrayDouble::New();
4425   std::vector<bool> isQuads;
4426   int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4427   ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4428   double *retPtr=ret->getPointer();
4429   const double *coords=getCoords()->getConstPointer();
4430   double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4431   std::vector<int> v;
4432   std::vector<double> c;
4433   double vec[3];
4434   v.reserve(3);
4435   c.reserve(6);
4436   for(int i=0;i<nbOf1DCells;i++)
4437     {
4438       v.resize(0);
4439       mesh1D->getNodeIdsOfCell(i,v);
4440       c.resize(0);
4441       mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4442       mesh1D->getCoordinatesOfNode(v[0],c);
4443       std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4444       for(int j=0;j<oldNbOfNodes;j++)
4445         work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4446       if(isQuad)
4447         {
4448           c.resize(0);
4449           mesh1D->getCoordinatesOfNode(v[1],c);
4450           mesh1D->getCoordinatesOfNode(v[0],c);
4451           std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4452           for(int j=0;j<oldNbOfNodes;j++)
4453             work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4454         }
4455     }
4456   ret->copyStringInfoFrom(*getCoords());
4457   return ret;
4458 }
4459
4460 /*!
4461  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4462  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4463  * \return newCoords new coords filled by this method. 
4464  */
4465 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4466 {
4467   if(mesh1D->getSpaceDimension()==2)
4468     return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4469   if(mesh1D->getSpaceDimension()==3)
4470     return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4471   throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4472 }
4473
4474 /*!
4475  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4476  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4477  * \return newCoords new coords filled by this method. 
4478  */
4479 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4480 {
4481   if(isQuad)
4482     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4483   int oldNbOfNodes=getNumberOfNodes();
4484   int nbOf1DCells=mesh1D->getNumberOfCells();
4485   if(nbOf1DCells<2)
4486     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4487   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4488   int nbOfLevsInVec=nbOf1DCells+1;
4489   ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4490   double *retPtr=ret->getPointer();
4491   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4492   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4493   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4494   tmp->setCoords(tmp2);
4495   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4496   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4497   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4498   for(int i=1;i<nbOfLevsInVec;i++)
4499     {
4500       const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4501       const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4502       const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4503       const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4504       tmp->translate(vec);
4505       double tmp3[2],radius,alpha,alpha0;
4506       const double *p0=i+1<nbOfLevsInVec?begin:third;
4507       const double *p1=i+1<nbOfLevsInVec?end:begin;
4508       const double *p2=i+1<nbOfLevsInVec?third:end;
4509       INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4510       double cosangle=i+1<nbOfLevsInVec?(p0[0]-tmp3[0])*(p1[0]-tmp3[0])+(p0[1]-tmp3[1])*(p1[1]-tmp3[1]):(p2[0]-tmp3[0])*(p1[0]-tmp3[0])+(p2[1]-tmp3[1])*(p1[1]-tmp3[1]);
4511       double angle=acos(cosangle/(radius*radius));
4512       tmp->rotate(end,0,angle);
4513       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4514     }
4515   return ret.retn();
4516 }
4517
4518 /*!
4519  * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4520  * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4521  * \return newCoords new coords filled by this method. 
4522  */
4523 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4524 {
4525   if(isQuad)
4526     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4527   int oldNbOfNodes=getNumberOfNodes();
4528   int nbOf1DCells=mesh1D->getNumberOfCells();
4529   if(nbOf1DCells<2)
4530     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4531   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4532   int nbOfLevsInVec=nbOf1DCells+1;
4533   ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4534   double *retPtr=ret->getPointer();
4535   retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4536   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4537   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4538   tmp->setCoords(tmp2);
4539   const double *coo1D=mesh1D->getCoords()->getConstPointer();
4540   const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4541   const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4542   for(int i=1;i<nbOfLevsInVec;i++)
4543     {
4544       const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4545       const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4546       const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4547       const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4548       tmp->translate(vec);
4549       double tmp3[2],radius,alpha,alpha0;
4550       const double *p0=i+1<nbOfLevsInVec?begin:third;
4551       const double *p1=i+1<nbOfLevsInVec?end:begin;
4552       const double *p2=i+1<nbOfLevsInVec?third:end;
4553       double vecPlane[3]={
4554         (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4555         (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4556         (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4557       };
4558       double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4559       if(norm>1.e-7)
4560         {
4561           vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4562           double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4563           double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4564           double s2=norm2;
4565           double c2=cos(asin(s2));
4566           double m[3][3]={
4567             {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4568             {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4569             {-vec2[1]*s2, vec2[0]*s2, c2}
4570           };
4571           double p0r[3]={m[0][0]*p0[0]+m[0][1]*p0[1]+m[0][2]*p0[2], m[1][0]*p0[0]+m[1][1]*p0[1]+m[1][2]*p0[2], m[2][0]*p0[0]+m[2][1]*p0[1]+m[2][2]*p0[2]};
4572           double p1r[3]={m[0][0]*p1[0]+m[0][1]*p1[1]+m[0][2]*p1[2], m[1][0]*p1[0]+m[1][1]*p1[1]+m[1][2]*p1[2], m[2][0]*p1[0]+m[2][1]*p1[1]+m[2][2]*p1[2]};
4573           double p2r[3]={m[0][0]*p2[0]+m[0][1]*p2[1]+m[0][2]*p2[2], m[1][0]*p2[0]+m[1][1]*p2[1]+m[1][2]*p2[2], m[2][0]*p2[0]+m[2][1]*p2[1]+m[2][2]*p2[2]};
4574           INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4575           double cosangle=i+1<nbOfLevsInVec?(p0r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p0r[1]-tmp3[1])*(p1r[1]-tmp3[1]):(p2r[0]-tmp3[0])*(p1r[0]-tmp3[0])+(p2r[1]-tmp3[1])*(p1r[1]-tmp3[1]);
4576           double angle=acos(cosangle/(radius*radius));
4577           tmp->rotate(end,vecPlane,angle);
4578           
4579         }
4580       retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4581     }
4582   return ret.retn();
4583 }
4584
4585 /*!
4586  * This method is private because not easy to use for end user. This method is const contrary to
4587  * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4588  * the coords sorted slice by slice.
4589  * \param isQuad specifies presence of quadratic cells.
4590  */
4591 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4592 {
4593   int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4594   int nbOf2DCells=getNumberOfCells();
4595   int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4596   MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4597   const int *conn=_nodal_connec->getConstPointer();
4598   const int *connI=_nodal_connec_index->getConstPointer();
4599   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4600   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4601   newConnI->alloc(nbOf3DCells+1,1);
4602   int *newConnIPtr=newConnI->getPointer();
4603   *newConnIPtr++=0;
4604   std::vector<int> newc;
4605   for(int j=0;j<nbOf2DCells;j++)
4606     {
4607       AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4608       *newConnIPtr++=(int)newc.size();
4609     }
4610   newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4611   int *newConnPtr=newConn->getPointer();
4612   int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4613   newConnIPtr=newConnI->getPointer();
4614   for(int iz=0;iz<nbOf1DCells;iz++)
4615     {
4616       if(iz!=0)
4617         std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4618       for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4619         {
4620           int icell=(int)(iter-newc.begin());
4621           if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4622             {
4623               if(*iter!=-1)
4624                 *newConnPtr=(*iter)+iz*deltaPerLev;
4625               else
4626                 *newConnPtr=-1;
4627             }
4628           else
4629             *newConnPtr=(*iter);
4630         }
4631     }
4632   ret->setConnectivity(newConn,newConnI,true);
4633   ret->setCoords(getCoords());
4634   return ret;
4635 }
4636
4637 /*!
4638  * Checks if \a this mesh is constituted by only quadratic cells.
4639  *  \return bool - \c true if there are only quadratic cells in \a this mesh.
4640  *  \throw If the coordinates array is not set.
4641  *  \throw If the nodal connectivity of cells is not defined.
4642  */
4643 bool MEDCouplingUMesh::isFullyQuadratic() const
4644 {
4645   checkFullyDefined();
4646   bool ret=true;
4647   int nbOfCells=getNumberOfCells();
4648   for(int i=0;i<nbOfCells && ret;i++)
4649     {
4650       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4651       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4652       ret=cm.isQuadratic();
4653     }
4654   return ret;
4655 }
4656
4657 /*!
4658  * Checks if \a this mesh includes any quadratic cell.
4659  *  \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4660  *  \throw If the coordinates array is not set.
4661  *  \throw If the nodal connectivity of cells is not defined.
4662  */
4663 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4664 {
4665   checkFullyDefined();
4666   bool ret=false;
4667   int nbOfCells=getNumberOfCells();
4668   for(int i=0;i<nbOfCells && !ret;i++)
4669     {
4670       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4671       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4672       ret=cm.isQuadratic();
4673     }
4674   return ret;
4675 }
4676
4677 /*!
4678  * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4679  * this mesh, it remains unchanged.
4680  *  \throw If the coordinates array is not set.
4681  *  \throw If the nodal connectivity of cells is not defined.
4682  */
4683 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4684 {
4685   checkFullyDefined();
4686   int nbOfCells=getNumberOfCells();
4687   int delta=0;
4688   const int *iciptr=_nodal_connec_index->getConstPointer();
4689   for(int i=0;i<nbOfCells;i++)
4690     {
4691       INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4692       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4693       if(cm.isQuadratic())
4694         {
4695           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4696           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4697           if(!cml.isDynamic())
4698             delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4699           else
4700             delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4701         }
4702     }
4703   if(delta==0)
4704     return ;
4705   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4706   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4707   const int *icptr=_nodal_connec->getConstPointer();
4708   newConn->alloc(getMeshLength()-delta,1);
4709   newConnI->alloc(nbOfCells+1,1);
4710   int *ocptr=newConn->getPointer();
4711   int *ociptr=newConnI->getPointer();
4712   *ociptr=0;
4713   _types.clear();
4714   for(int i=0;i<nbOfCells;i++,ociptr++)
4715     {
4716       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4717       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4718       if(!cm.isQuadratic())
4719         {
4720           _types.insert(type);
4721           ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4722           ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4723         }
4724       else
4725         {
4726           INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4727           _types.insert(typel);
4728           const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4729           int newNbOfNodes=cml.getNumberOfNodes();
4730           if(cml.isDynamic())
4731             newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4732           *ocptr++=(int)typel;
4733           ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4734           ociptr[1]=ociptr[0]+newNbOfNodes+1;
4735         }
4736     }
4737   setConnectivity(newConn,newConnI,false);
4738 }
4739
4740 /*!
4741  * This method converts all linear cell in \a this to quadratic one.
4742  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4743  * type of cells expected. For example INTERP_KERNEL::NORM_TRI3 can be converted to INTERP_KERNEL::NORM_TRI6 if \a conversionType is equal to 0 (the default)
4744  * or to INTERP_KERNEL::NORM_TRI7 if \a conversionType is equal to 1. All non linear cells and polyhedron in \a this are let untouched.
4745  * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4746  * end of the existing coordinates.
4747  * 
4748  * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4749  *             corresponding quadratic cells. 1 is those creating the 'most' complex.
4750  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4751  * 
4752  * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4753  *
4754  * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4755  */
4756 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4757 {
4758   DataArrayInt *conn=0,*connI=0;
4759   DataArrayDouble *coords=0;
4760   std::set<INTERP_KERNEL::NormalizedCellType> types;
4761   checkFullyDefined();
4762   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4763   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4764   int meshDim=getMeshDimension();
4765   switch(conversionType)
4766     {
4767     case 0:
4768       switch(meshDim)
4769         {
4770         case 1:
4771           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4772           connSafe=conn; connISafe=connI; coordsSafe=coords;
4773           break;
4774         case 2:
4775           ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4776           connSafe=conn; connISafe=connI; coordsSafe=coords;
4777           break;
4778         case 3:
4779           ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4780           connSafe=conn; connISafe=connI; coordsSafe=coords;
4781           break;
4782         default:
4783           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4784         }
4785       break;
4786     case 1:
4787       {
4788         switch(meshDim)
4789         {
4790         case 1:
4791           ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4792           connSafe=conn; connISafe=connI; coordsSafe=coords;
4793           break;
4794         case 2:
4795           ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4796           connSafe=conn; connISafe=connI; coordsSafe=coords;
4797           break;
4798         case 3:
4799           ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4800           connSafe=conn; connISafe=connI; coordsSafe=coords;
4801           break;
4802         default:
4803           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4804         }
4805         break;
4806       }
4807     default:
4808       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4809     }
4810   setConnectivity(connSafe,connISafe,false);
4811   _types=types;
4812   setCoords(coordsSafe);
4813   return ret.retn();
4814 }
4815
4816 /*!
4817  * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4818  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4819  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4820  */
4821 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4822 {
4823   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4824   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4825   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4826   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4827   int nbOfCells=getNumberOfCells();
4828   int nbOfNodes=getNumberOfNodes();
4829   const int *cPtr=_nodal_connec->getConstPointer();
4830   const int *icPtr=_nodal_connec_index->getConstPointer();
4831   int lastVal=0,offset=nbOfNodes;
4832   for(int i=0;i<nbOfCells;i++,icPtr++)
4833     {
4834       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4835       if(type==INTERP_KERNEL::NORM_SEG2)
4836         {
4837           types.insert(INTERP_KERNEL::NORM_SEG3);
4838           newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4839           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4840           newConn->pushBackSilent(offset++);
4841           lastVal+=4;
4842           newConnI->pushBackSilent(lastVal);
4843           ret->pushBackSilent(i);
4844         }
4845       else
4846         {
4847           types.insert(type);
4848           lastVal+=(icPtr[1]-icPtr[0]);
4849           newConnI->pushBackSilent(lastVal);
4850           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4851         }
4852     }
4853   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4854   coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4855   return ret.retn();
4856 }
4857
4858 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2DAnd3D0(const MEDCouplingUMesh *m1D, const DataArrayInt *desc, const DataArrayInt *descI, DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4859 {
4860   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4861   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4862   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4863   //
4864   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4865   DataArrayInt *conn1D=0,*conn1DI=0;
4866   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4867   DataArrayDouble *coordsTmp=0;
4868   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4869   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4870   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4871   const int *c1DPtr=conn1D->begin();
4872   const int *c1DIPtr=conn1DI->begin();
4873   int nbOfCells=getNumberOfCells();
4874   const int *cPtr=_nodal_connec->getConstPointer();
4875   const int *icPtr=_nodal_connec_index->getConstPointer();
4876   int lastVal=0;
4877   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4878     {
4879       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4880       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4881       if(!cm.isQuadratic())
4882         {
4883           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4884           types.insert(typ2); newConn->pushBackSilent(typ2);
4885           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4886           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4887             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4888           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4889           newConnI->pushBackSilent(lastVal);
4890           ret->pushBackSilent(i);
4891         }
4892       else
4893         {
4894           types.insert(typ);
4895           lastVal+=(icPtr[1]-icPtr[0]);
4896           newConnI->pushBackSilent(lastVal);
4897           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4898         }
4899     }
4900   conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4901   return ret.retn();
4902 }
4903
4904 /*!
4905  * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4906  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4907  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4908  */
4909 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4910 {
4911   
4912   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4913   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4914   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4915 }
4916
4917 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4918 {
4919   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4920   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4921   //
4922   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4923   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4924   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4925   //
4926   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4927   const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4928   DataArrayInt *conn1D=0,*conn1DI=0;
4929   std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4930   DataArrayDouble *coordsTmp=0;
4931   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4932   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4933   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4934   const int *c1DPtr=conn1D->begin();
4935   const int *c1DIPtr=conn1DI->begin();
4936   int nbOfCells=getNumberOfCells();
4937   const int *cPtr=_nodal_connec->getConstPointer();
4938   const int *icPtr=_nodal_connec_index->getConstPointer();
4939   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4940   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4941     {
4942       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4943       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4944       if(!cm.isQuadratic())
4945         {
4946           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
4947           types.insert(typ2); newConn->pushBackSilent(typ2);
4948           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4949           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4950             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4951           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
4952           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
4953           newConnI->pushBackSilent(lastVal);
4954           ret->pushBackSilent(i);
4955         }
4956       else
4957         {
4958           types.insert(typ);
4959           lastVal+=(icPtr[1]-icPtr[0]);
4960           newConnI->pushBackSilent(lastVal);
4961           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4962         }
4963     }
4964   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4965   coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
4966   return ret.retn();
4967 }
4968
4969 /*!
4970  * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4971  * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4972  * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4973  */
4974 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4975 {
4976   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4977   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4978   return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4979 }
4980
4981 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4982 {
4983   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4984   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
4985   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
4986   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
4987   //
4988   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4989   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4990   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
4991   //
4992   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4993   const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
4994   DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
4995   std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
4996   DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
4997   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
4998   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4999   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5000   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5001   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5002   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5003   const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5004   int nbOfCells=getNumberOfCells();
5005   const int *cPtr=_nodal_connec->getConstPointer();
5006   const int *icPtr=_nodal_connec_index->getConstPointer();
5007   int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5008   for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5009     {
5010       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5011       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5012       if(!cm.isQuadratic())
5013         {
5014           INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5015           if(typ2==INTERP_KERNEL::NORM_ERROR)
5016             {
5017               std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5018               throw INTERP_KERNEL::Exception(oss.str().c_str());
5019             }
5020           types.insert(typ2); newConn->pushBackSilent(typ2);
5021           newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5022           for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5023             newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5024           for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5025             {
5026               int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5027               int tmpPos=newConn->getNumberOfTuples();
5028               newConn->pushBackSilent(nodeId2);
5029               ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5030             }
5031           newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5032           lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5033           newConnI->pushBackSilent(lastVal);
5034           ret->pushBackSilent(i);
5035         }
5036       else
5037         {
5038           types.insert(typ);
5039           lastVal+=(icPtr[1]-icPtr[0]);
5040           newConnI->pushBackSilent(lastVal);
5041           newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5042         }
5043     }
5044   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5045   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5046   coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5047   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5048   std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5049   int *c=newConn->getPointer();
5050   const int *cI(newConnI->begin());
5051   for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5052     c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5053   offset=coordsTmp2Safe->getNumberOfTuples();
5054   for(const int *elt=ret->begin();elt!=ret->end();elt++)
5055     c[cI[(*elt)+1]-1]+=offset;
5056   coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5057   return ret.retn();
5058 }
5059
5060 /*!
5061  * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5062  * so that the number of cells remains the same. Quadratic faces are converted to
5063  * polygons. This method works only for 2D meshes in
5064  * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5065  * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5066  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5067  *  \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5068  *         a polylinized edge constituting the input polygon.
5069  *  \throw If the coordinates array is not set.
5070  *  \throw If the nodal connectivity of cells is not defined.
5071  *  \throw If \a this->getMeshDimension() != 2.
5072  *  \throw If \a this->getSpaceDimension() != 2.
5073  */
5074 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5075 {
5076   checkFullyDefined();
5077   if(getMeshDimension()!=2 || getSpaceDimension()!=2)  
5078     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5079   double epsa=fabs(eps);
5080   if(epsa<std::numeric_limits<double>::min())
5081     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5082   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5083   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5084   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5085   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5086   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5087   revDesc1=0; revDescIndx1=0;
5088   mDesc->tessellate2DCurve(eps);
5089   subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5090   setCoords(mDesc->getCoords());
5091 }
5092
5093 /*!
5094  * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5095  * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5096  *  \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5097  *         a sub-divided edge.
5098  *  \throw If the coordinates array is not set.
5099  *  \throw If the nodal connectivity of cells is not defined.
5100  *  \throw If \a this->getMeshDimension() != 1.
5101  *  \throw If \a this->getSpaceDimension() != 2.
5102  */
5103 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5104 {
5105   checkFullyDefined();
5106   if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5107     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5108   double epsa=fabs(eps);
5109   if(epsa<std::numeric_limits<double>::min())
5110     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve : epsilon is null ! Please specify a higher epsilon. If too tiny it can lead to a huge amount of nodes and memory !");
5111   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5112   int nbCells=getNumberOfCells();
5113   int nbNodes=getNumberOfNodes();
5114   const int *conn=_nodal_connec->getConstPointer();
5115   const int *connI=_nodal_connec_index->getConstPointer();
5116   const double *coords=_coords->getConstPointer();
5117   std::vector<double> addCoo;
5118   std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5119   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5120   newConnI->alloc(nbCells+1,1);
5121   int *newConnIPtr=newConnI->getPointer();
5122   *newConnIPtr=0;
5123   int tmp1[3];
5124   INTERP_KERNEL::Node *tmp2[3];
5125   std::set<INTERP_KERNEL::NormalizedCellType> types;
5126   for(int i=0;i<nbCells;i++,newConnIPtr++)
5127     {
5128       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5129       if(cm.isQuadratic())
5130         {//assert(connI[i+1]-connI[i]-1==3)
5131           tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5132           tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5133           tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5134           tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5135           INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5136           if(eac)
5137             {
5138               eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5139               types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5140               delete eac;
5141               newConnIPtr[1]=(int)newConn.size();
5142             }
5143           else
5144             {
5145               types.insert(INTERP_KERNEL::NORM_SEG2);
5146               newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5147               newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5148               newConnIPtr[1]=newConnIPtr[0]+3;
5149             }
5150         }
5151       else
5152         {
5153           types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5154           newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5155           newConnIPtr[1]=newConnIPtr[0]+3;
5156         }
5157     }
5158   if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5159     return ;
5160   _types=types;
5161   DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5162   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5163   newConnArr->alloc((int)newConn.size(),1);
5164   std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5165   DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5166   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5167   newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5168   double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5169   std::copy(addCoo.begin(),addCoo.end(),work);
5170   DataArrayDouble::SetArrayIn(newCoords,_coords);
5171   updateTime();
5172 }
5173
5174 /*!
5175  * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5176  * In addition, returns an array mapping new cells to old ones. <br>
5177  * This method typically increases the number of cells in \a this mesh
5178  * but the number of nodes remains \b unchanged.
5179  * That's why the 3D splitting policies
5180  * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5181  *  \param [in] policy - specifies a pattern used for splitting.
5182  * The semantic of \a policy is:
5183  * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5184  * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5185  * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8  into 5 TETRA4 (for 3D mesh only).
5186  * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8  into 6 TETRA4 (for 3D mesh only).
5187  *  \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5188  *          an id of old cell producing it. The caller is to delete this array using
5189  *         decrRef() as it is no more needed. 
5190  *  \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5191  *  \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5192  *          and \a this->getMeshDimension() != 3. 
5193  *  \throw If \a policy is not one of the four discussed above.
5194  *  \throw If the nodal connectivity of cells is not defined.
5195  */
5196 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5197 {
5198   switch(policy)
5199     {
5200     case 0:
5201       return simplexizePol0();
5202     case 1:
5203       return simplexizePol1();
5204     case (int) INTERP_KERNEL::PLANAR_FACE_5:
5205       return simplexizePlanarFace5();
5206     case (int) INTERP_KERNEL::PLANAR_FACE_6:
5207       return simplexizePlanarFace6();
5208     default:
5209       throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexize : unrecognized policy ! Must be :\n  - 0 or 1 (only available for meshdim=2) \n  - PLANAR_FACE_5, PLANAR_FACE_6  (only for meshdim=3)");
5210     }
5211 }
5212
5213 /*!
5214  * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5215  * - 1D: INTERP_KERNEL::NORM_SEG2
5216  * - 2D: INTERP_KERNEL::NORM_TRI3
5217  * - 3D: INTERP_KERNEL::NORM_TETRA4.
5218  *
5219  * This method is useful for users that need to use P1 field services as
5220  * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5221  * All these methods need mesh support containing only simplex cells.
5222  *  \return bool - \c true if there are only simplex cells in \a this mesh.
5223  *  \throw If the coordinates array is not set.
5224  *  \throw If the nodal connectivity of cells is not defined.
5225  *  \throw If \a this->getMeshDimension() < 1.
5226  */
5227 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5228 {
5229   checkFullyDefined();
5230   int mdim=getMeshDimension();
5231   if(mdim<1 || mdim>3)
5232     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5233   int nbCells=getNumberOfCells();
5234   const int *conn=_nodal_connec->getConstPointer();
5235   const int *connI=_nodal_connec_index->getConstPointer();
5236   for(int i=0;i<nbCells;i++)
5237     {
5238       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5239       if(!cm.isSimplex())
5240         return false;
5241     }
5242   return true;
5243 }
5244
5245 /*!
5246  * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5247  */
5248 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5249 {
5250   checkConnectivityFullyDefined();
5251   if(getMeshDimension()!=2)
5252     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5253   int nbOfCells=getNumberOfCells();
5254   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5255   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5256   ret->alloc(nbOfCells+nbOfCutCells,1);
5257   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5258   int *retPt=ret->getPointer();
5259   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5260   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5261   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5262   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5263   int *pt=newConn->getPointer();
5264   int *ptI=newConnI->getPointer();
5265   ptI[0]=0;
5266   const int *oldc=_nodal_connec->getConstPointer();
5267   const int *ci=_nodal_connec_index->getConstPointer();
5268   for(int i=0;i<nbOfCells;i++,ci++)
5269     {
5270       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5271         {
5272           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5273                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5274           pt=std::copy(tmp,tmp+8,pt);
5275           ptI[1]=ptI[0]+4;
5276           ptI[2]=ptI[0]+8;
5277           *retPt++=i;
5278           *retPt++=i;
5279           ptI+=2;
5280         }
5281       else
5282         {
5283           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5284           ptI[1]=ptI[0]+ci[1]-ci[0];
5285           ptI++;
5286           *retPt++=i;
5287         }
5288     }
5289   _nodal_connec->decrRef();
5290   _nodal_connec=newConn.retn();
5291   _nodal_connec_index->decrRef();
5292   _nodal_connec_index=newConnI.retn();
5293   computeTypes();
5294   updateTime();
5295   return ret.retn();
5296 }
5297
5298 /*!
5299  * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5300  */
5301 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5302 {
5303   checkConnectivityFullyDefined();
5304   if(getMeshDimension()!=2)
5305     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5306   int nbOfCells=getNumberOfCells();
5307   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5308   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5309   ret->alloc(nbOfCells+nbOfCutCells,1);
5310   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5311   int *retPt=ret->getPointer();
5312   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5313   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5314   newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5315   newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5316   int *pt=newConn->getPointer();
5317   int *ptI=newConnI->getPointer();
5318   ptI[0]=0;
5319   const int *oldc=_nodal_connec->getConstPointer();
5320   const int *ci=_nodal_connec_index->getConstPointer();
5321   for(int i=0;i<nbOfCells;i++,ci++)
5322     {
5323       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5324         {
5325           const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5326                             (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5327           pt=std::copy(tmp,tmp+8,pt);
5328           ptI[1]=ptI[0]+4;
5329           ptI[2]=ptI[0]+8;
5330           *retPt++=i;
5331           *retPt++=i;
5332           ptI+=2;
5333         }
5334       else
5335         {
5336           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5337           ptI[1]=ptI[0]+ci[1]-ci[0];
5338           ptI++;
5339           *retPt++=i;
5340         }
5341     }
5342   _nodal_connec->decrRef();
5343   _nodal_connec=newConn.retn();
5344   _nodal_connec_index->decrRef();
5345   _nodal_connec_index=newConnI.retn();
5346   computeTypes();
5347   updateTime();
5348   return ret.retn();
5349 }
5350
5351 /*!
5352  * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5353  */
5354 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5355 {
5356   checkConnectivityFullyDefined();
5357   if(getMeshDimension()!=3)
5358     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5359   int nbOfCells=getNumberOfCells();
5360   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5361   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5362   ret->alloc(nbOfCells+4*nbOfCutCells,1);
5363   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5364   int *retPt=ret->getPointer();
5365   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5366   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5367   newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5368   newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5369   int *pt=newConn->getPointer();
5370   int *ptI=newConnI->getPointer();
5371   ptI[0]=0;
5372   const int *oldc=_nodal_connec->getConstPointer();
5373   const int *ci=_nodal_connec_index->getConstPointer();
5374   for(int i=0;i<nbOfCells;i++,ci++)
5375     {
5376       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5377         {
5378           for(int j=0;j<5;j++,pt+=5,ptI++)
5379             {
5380               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5381               pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_5_WO[4*j+3]+1];
5382               *retPt++=i;
5383               ptI[1]=ptI[0]+5;
5384             }
5385         }
5386       else
5387         {
5388           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5389           ptI[1]=ptI[0]+ci[1]-ci[0];
5390           ptI++;
5391           *retPt++=i;
5392         }
5393     }
5394   _nodal_connec->decrRef();
5395   _nodal_connec=newConn.retn();
5396   _nodal_connec_index->decrRef();
5397   _nodal_connec_index=newConnI.retn();
5398   computeTypes();
5399   updateTime();
5400   return ret.retn();
5401 }
5402
5403 /*!
5404  * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5405  */
5406 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5407 {
5408   checkConnectivityFullyDefined();
5409   if(getMeshDimension()!=3)
5410     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5411   int nbOfCells=getNumberOfCells();
5412   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5413   int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5414   ret->alloc(nbOfCells+5*nbOfCutCells,1);
5415   if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5416   int *retPt=ret->getPointer();
5417   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5418   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5419   newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5420   newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5421   int *pt=newConn->getPointer();
5422   int *ptI=newConnI->getPointer();
5423   ptI[0]=0;
5424   const int *oldc=_nodal_connec->getConstPointer();
5425   const int *ci=_nodal_connec_index->getConstPointer();
5426   for(int i=0;i<nbOfCells;i++,ci++)
5427     {
5428       if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5429         {
5430           for(int j=0;j<6;j++,pt+=5,ptI++)
5431             {
5432               pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5433               pt[1]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+0]+1]; pt[2]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+1]+1]; pt[3]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+2]+1]; pt[4]=oldc[ci[0]+INTERP_KERNEL::SPLIT_NODES_6_WO[4*j+3]+1];
5434               *retPt++=i;
5435               ptI[1]=ptI[0]+5;
5436             }
5437         }
5438       else
5439         {
5440           pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5441           ptI[1]=ptI[0]+ci[1]-ci[0];
5442           ptI++;
5443           *retPt++=i;
5444         }
5445     }
5446   _nodal_connec->decrRef();
5447   _nodal_connec=newConn.retn();
5448   _nodal_connec_index->decrRef();
5449   _nodal_connec_index=newConnI.retn();
5450   computeTypes();
5451   updateTime();
5452   return ret.retn();
5453 }
5454
5455 /*!
5456  * This private method is used to subdivide edges of a mesh with meshdim==2. If \a this has no a meshdim equal to 2 an exception will be thrown.
5457  * This method completly ignore coordinates.
5458  * \param nodeSubdived is the nodal connectivity of subdivision of edges
5459  * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5460  * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5461  * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5462  */
5463 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5464 {
5465   checkFullyDefined();
5466   if(getMeshDimension()!=2)
5467     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5468   int nbOfCells=getNumberOfCells();
5469   int *connI=_nodal_connec_index->getPointer();
5470   int newConnLgth=0;
5471   for(int i=0;i<nbOfCells;i++,connI++)
5472     {
5473       int offset=descIndex[i];
5474       int nbOfEdges=descIndex[i+1]-offset;
5475       //
5476       bool ddirect=desc[offset+nbOfEdges-1]>0;
5477       int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5478       int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5479       for(int j=0;j<nbOfEdges;j++)
5480         {
5481           bool direct=desc[offset+j]>0;
5482           int edgeId=std::abs(desc[offset+j])-1;
5483           if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5484             {
5485               int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5486               int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5487               int ref2=direct?id1:id2;
5488               if(ref==ref2)
5489                 {
5490                   int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5491                   newConnLgth+=nbOfSubNodes-1;
5492                   ref=direct?id2:id1;
5493                 }
5494               else
5495                 {
5496                   std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5497                   throw INTERP_KERNEL::Exception(oss.str().c_str());
5498                 }
5499             }
5500           else
5501             {
5502               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5503             }
5504         }
5505       newConnLgth++;//+1 is for cell type
5506       connI[1]=newConnLgth;
5507     }
5508   //
5509   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5510   newConn->alloc(newConnLgth,1);
5511   int *work=newConn->getPointer();
5512   for(int i=0;i<nbOfCells;i++)
5513     {
5514       *work++=INTERP_KERNEL::NORM_POLYGON;
5515       int offset=descIndex[i];
5516       int nbOfEdges=descIndex[i+1]-offset;
5517       for(int j=0;j<nbOfEdges;j++)
5518         {
5519           bool direct=desc[offset+j]>0;
5520           int edgeId=std::abs(desc[offset+j])-1;
5521           if(direct)
5522             work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5523           else
5524             {
5525               int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5526               std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5527               work=std::copy(it,it+nbOfSubNodes-1,work);
5528             }
5529         }
5530     }
5531   DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5532   _types.clear();
5533   if(nbOfCells>0)
5534     _types.insert(INTERP_KERNEL::NORM_POLYGON);
5535 }
5536
5537 /*!
5538  * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5539  * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5540  * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5541  * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5542  * so it can be useful to call mergeNodes() before calling this method.
5543  *  \throw If \a this->getMeshDimension() <= 1.
5544  *  \throw If the coordinates array is not set.
5545  *  \throw If the nodal connectivity of cells is not defined.
5546  */
5547 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5548 {
5549   checkFullyDefined();
5550   if(getMeshDimension()<=1)
5551     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5552   int nbOfCells=getNumberOfCells();
5553   if(nbOfCells<1)
5554     return ;
5555   int initMeshLgth=getMeshLength();
5556   int *conn=_nodal_connec->getPointer();
5557   int *index=_nodal_connec_index->getPointer();
5558   int posOfCurCell=0;
5559   int newPos=0;
5560   int lgthOfCurCell;
5561   for(int i=0;i<nbOfCells;i++)
5562     {
5563       lgthOfCurCell=index[i+1]-posOfCurCell;
5564       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5565       int newLgth;
5566       INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5567                                                                                                      conn+newPos+1,newLgth);
5568       conn[newPos]=newType;
5569       newPos+=newLgth+1;
5570       posOfCurCell=index[i+1];
5571       index[i+1]=newPos;
5572     }
5573   if(newPos!=initMeshLgth)
5574     _nodal_connec->reAlloc(newPos);
5575   computeTypes();
5576 }
5577
5578 /*!
5579  * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5580  * A cell is considered to be oriented correctly if an angle between its
5581  * normal vector and a given vector is less than \c PI / \c 2.
5582  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5583  *         cells. 
5584  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5585  *         checked.
5586  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5587  *         is not cleared before filling in.
5588  *  \throw If \a this->getMeshDimension() != 2.
5589  *  \throw If \a this->getSpaceDimension() != 3.
5590  *
5591  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5592  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5593  */
5594 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5595 {
5596   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5597     throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5598   int nbOfCells=getNumberOfCells();
5599   const int *conn=_nodal_connec->getConstPointer();
5600   const int *connI=_nodal_connec_index->getConstPointer();
5601   const double *coordsPtr=_coords->getConstPointer();
5602   for(int i=0;i<nbOfCells;i++)
5603     {
5604       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5605       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5606         {
5607           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5608           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5609             cells.push_back(i);
5610         }
5611     }
5612 }
5613
5614 /*!
5615  * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5616  * considered to be oriented correctly if an angle between its normal vector and a
5617  * given vector is less than \c PI / \c 2. 
5618  *  \param [in] vec - 3 components of the vector specifying the correct orientation of
5619  *         cells. 
5620  *  \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5621  *         checked.
5622  *  \throw If \a this->getMeshDimension() != 2.
5623  *  \throw If \a this->getSpaceDimension() != 3.
5624  *
5625  *  \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5626  *  \ref  py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5627  */
5628 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5629 {
5630   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5631     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5632   int nbOfCells=getNumberOfCells();
5633   int *conn=_nodal_connec->getPointer();
5634   const int *connI=_nodal_connec_index->getConstPointer();
5635   const double *coordsPtr=_coords->getConstPointer();
5636   bool isModified=false;
5637   for(int i=0;i<nbOfCells;i++)
5638     {
5639       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5640       if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5641         {
5642           bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5643           if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5644             {
5645               isModified=true;
5646               std::vector<int> tmp(connI[i+1]-connI[i]-2);
5647               std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5648               std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5649             }
5650         }
5651     }
5652   if(isModified)
5653     _nodal_connec->declareAsNew();
5654   updateTime();
5655 }
5656
5657 /*!
5658  * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5659  * oriented facets. The normal vector of the facet should point out of the cell.
5660  *  \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5661  *         is not cleared before filling in.
5662  *  \throw If \a this->getMeshDimension() != 3.
5663  *  \throw If \a this->getSpaceDimension() != 3.
5664  *  \throw If the coordinates array is not set.
5665  *  \throw If the nodal connectivity of cells is not defined.
5666  *
5667  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5668  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5669  */
5670 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5671 {
5672   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5673     throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5674   int nbOfCells=getNumberOfCells();
5675   const int *conn=_nodal_connec->getConstPointer();
5676   const int *connI=_nodal_connec_index->getConstPointer();
5677   const double *coordsPtr=_coords->getConstPointer();
5678   for(int i=0;i<nbOfCells;i++)
5679     {
5680       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5681       if(type==INTERP_KERNEL::NORM_POLYHED)
5682         {
5683           if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5684             cells.push_back(i);
5685         }
5686     }
5687 }
5688
5689 /*!
5690  * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5691  * out of the cell. 
5692  *  \throw If \a this->getMeshDimension() != 3.
5693  *  \throw If \a this->getSpaceDimension() != 3.
5694  *  \throw If the coordinates array is not set.
5695  *  \throw If the nodal connectivity of cells is not defined.
5696  *  \throw If the reparation fails.
5697  *
5698  *  \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5699  *  \ref  py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5700  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5701  */
5702 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5703 {
5704   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5705     throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5706   int nbOfCells=getNumberOfCells();
5707   int *conn=_nodal_connec->getPointer();
5708   const int *connI=_nodal_connec_index->getConstPointer();
5709   const double *coordsPtr=_coords->getConstPointer();
5710   for(int i=0;i<nbOfCells;i++)
5711     {
5712       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5713       if(type==INTERP_KERNEL::NORM_POLYHED)
5714         {
5715           try
5716             {
5717               if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5718                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5719             }
5720           catch(INTERP_KERNEL::Exception& e)
5721             {
5722               std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5723               throw INTERP_KERNEL::Exception(oss.str().c_str());
5724             }
5725         }
5726     }
5727   updateTime();
5728 }
5729
5730 /*!
5731  * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5732  * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5733  * according to which the first facet of the cell should be oriented to have the normal vector
5734  * pointing out of cell.
5735  *  \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5736  *         cells. The caller is to delete this array using decrRef() as it is no more
5737  *         needed. 
5738  *  \throw If \a this->getMeshDimension() != 3.
5739  *  \throw If \a this->getSpaceDimension() != 3.
5740  *  \throw If the coordinates array is not set.
5741  *  \throw If the nodal connectivity of cells is not defined.
5742  *
5743  *  \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5744  *  \ref  py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5745  * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5746  */
5747 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5748 {
5749   const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5750   if(getMeshDimension()!=3)
5751     throw INTERP_KERNEL::Exception(msg);
5752   int spaceDim=getSpaceDimension();
5753   if(spaceDim!=3)
5754     throw INTERP_KERNEL::Exception(msg);
5755   //
5756   int nbOfCells=getNumberOfCells();
5757   int *conn=_nodal_connec->getPointer();
5758   const int *connI=_nodal_connec_index->getConstPointer();
5759   const double *coo=getCoords()->getConstPointer();
5760   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5761   for(int i=0;i<nbOfCells;i++)
5762     {
5763       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5764       if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5765         {
5766           if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5767             {
5768               CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5769               cells->pushBackSilent(i);
5770             }
5771         }
5772     }
5773   return cells.retn();
5774 }
5775
5776 /*!
5777  * This method is a faster method to correct orientation of all 3D cells in \a this.
5778  * This method works only if \a this is a 3D mesh, that is to say a mesh with mesh dimension 3 and a space dimension 3.
5779  * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5780  * 
5781  * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5782  * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons, 
5783  */
5784 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5785 {
5786   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5787     throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5788   int nbOfCells=getNumberOfCells();
5789   int *conn=_nodal_connec->getPointer();
5790   const int *connI=_nodal_connec_index->getConstPointer();
5791   const double *coordsPtr=_coords->getConstPointer();
5792   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5793   for(int i=0;i<nbOfCells;i++)
5794     {
5795       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5796       switch(type)
5797         {
5798         case INTERP_KERNEL::NORM_TETRA4:
5799           {
5800             if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5801               {
5802                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5803                 ret->pushBackSilent(i);
5804               }
5805             break;
5806           }
5807         case INTERP_KERNEL::NORM_PYRA5:
5808           {
5809             if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5810               {
5811                 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5812                 ret->pushBackSilent(i);
5813               }
5814             break;
5815           }
5816         case INTERP_KERNEL::NORM_PENTA6:
5817         case INTERP_KERNEL::NORM_HEXA8:
5818         case INTERP_KERNEL::NORM_HEXGP12:
5819           {
5820             if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5821               {
5822                 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5823                 ret->pushBackSilent(i);
5824               }
5825             break;
5826           }
5827         case INTERP_KERNEL::NORM_POLYHED:
5828           {
5829             if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5830               {
5831                 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5832                 ret->pushBackSilent(i);
5833               }
5834             break;
5835           }
5836         default:
5837           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::orientCorrectly3DCells : Your mesh contains type of cell not supported yet ! send mail to anthony.geay@cea.fr to add it !");
5838         }
5839     }
5840   updateTime();
5841   return ret.retn();
5842 }
5843
5844 /*!
5845  * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5846  * If it is not the case an exception will be thrown.
5847  * This method is fast because the first cell of \a this is used to compute the plane.
5848  * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5849  * \param pos output of size at least 3 used to store a point owned of searched plane.
5850  */
5851 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5852 {
5853   if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5854     throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5855   const int *conn=_nodal_connec->getConstPointer();
5856   const int *connI=_nodal_connec_index->getConstPointer();
5857   const double *coordsPtr=_coords->getConstPointer();
5858   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5859   std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5860 }
5861
5862 /*!
5863  * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5864  * cells. Currently cells of the following types are treated:
5865  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5866  * For a cell of other type an exception is thrown.
5867  * Space dimension of a 2D mesh can be either 2 or 3.
5868  * The Edge Ratio of a cell \f$t\f$ is: 
5869  *  \f$\frac{|t|_\infty}{|t|_0}\f$,
5870  *  where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5871  *  the smallest edge lengths of \f$t\f$.
5872  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5873  *          cells and one time, lying on \a this mesh. The caller is to delete this
5874  *          field using decrRef() as it is no more needed. 
5875  *  \throw If the coordinates array is not set.
5876  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5877  *  \throw If the connectivity data array has more than one component.
5878  *  \throw If the connectivity data array has a named component.
5879  *  \throw If the connectivity index data array has more than one component.
5880  *  \throw If the connectivity index data array has a named component.
5881  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5882  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5883  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5884  */
5885 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5886 {
5887   checkCoherency();
5888   int spaceDim=getSpaceDimension();
5889   int meshDim=getMeshDimension();
5890   if(spaceDim!=2 && spaceDim!=3)
5891     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5892   if(meshDim!=2 && meshDim!=3)
5893     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5894   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5895   ret->setMesh(this);
5896   int nbOfCells=getNumberOfCells();
5897   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5898   arr->alloc(nbOfCells,1);
5899   double *pt=arr->getPointer();
5900   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5901   const int *conn=_nodal_connec->getConstPointer();
5902   const int *connI=_nodal_connec_index->getConstPointer();
5903   const double *coo=_coords->getConstPointer();
5904   double tmp[12];
5905   for(int i=0;i<nbOfCells;i++,pt++)
5906     {
5907       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5908       switch(t)
5909         {
5910           case INTERP_KERNEL::NORM_TRI3:
5911             {
5912               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5913               *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5914               break;
5915             }
5916           case INTERP_KERNEL::NORM_QUAD4:
5917             {
5918               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5919               *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5920               break;
5921             }
5922           case INTERP_KERNEL::NORM_TETRA4:
5923             {
5924               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5925               *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5926               break;
5927             }
5928         default:
5929           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5930         }
5931       conn+=connI[i+1]-connI[i];
5932     }
5933   ret->setName("EdgeRatio");
5934   ret->synchronizeTimeWithSupport();
5935   return ret.retn();
5936 }
5937
5938 /*!
5939  * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5940  * cells. Currently cells of the following types are treated:
5941  * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5942  * For a cell of other type an exception is thrown.
5943  * Space dimension of a 2D mesh can be either 2 or 3.
5944  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5945  *          cells and one time, lying on \a this mesh. The caller is to delete this
5946  *          field using decrRef() as it is no more needed. 
5947  *  \throw If the coordinates array is not set.
5948  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5949  *  \throw If the connectivity data array has more than one component.
5950  *  \throw If the connectivity data array has a named component.
5951  *  \throw If the connectivity index data array has more than one component.
5952  *  \throw If the connectivity index data array has a named component.
5953  *  \throw If \a this->getMeshDimension() is neither 2 nor 3.
5954  *  \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5955  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
5956  */
5957 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
5958 {
5959   checkCoherency();
5960   int spaceDim=getSpaceDimension();
5961   int meshDim=getMeshDimension();
5962   if(spaceDim!=2 && spaceDim!=3)
5963     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
5964   if(meshDim!=2 && meshDim!=3)
5965     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
5966   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5967   ret->setMesh(this);
5968   int nbOfCells=getNumberOfCells();
5969   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5970   arr->alloc(nbOfCells,1);
5971   double *pt=arr->getPointer();
5972   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5973   const int *conn=_nodal_connec->getConstPointer();
5974   const int *connI=_nodal_connec_index->getConstPointer();
5975   const double *coo=_coords->getConstPointer();
5976   double tmp[12];
5977   for(int i=0;i<nbOfCells;i++,pt++)
5978     {
5979       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5980       switch(t)
5981         {
5982           case INTERP_KERNEL::NORM_TRI3:
5983             {
5984               FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5985               *pt=INTERP_KERNEL::triAspectRatio(tmp);
5986               break;
5987             }
5988           case INTERP_KERNEL::NORM_QUAD4:
5989             {
5990               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5991               *pt=INTERP_KERNEL::quadAspectRatio(tmp);
5992               break;
5993             }
5994           case INTERP_KERNEL::NORM_TETRA4:
5995             {
5996               FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5997               *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
5998               break;
5999             }
6000         default:
6001           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6002         }
6003       conn+=connI[i+1]-connI[i];
6004     }
6005   ret->setName("AspectRatio");
6006   ret->synchronizeTimeWithSupport();
6007   return ret.retn();
6008 }
6009
6010 /*!
6011  * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6012  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6013  * treated: INTERP_KERNEL::NORM_QUAD4.
6014  * For a cell of other type an exception is thrown.
6015  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6016  *          cells and one time, lying on \a this mesh. The caller is to delete this
6017  *          field using decrRef() as it is no more needed. 
6018  *  \throw If the coordinates array is not set.
6019  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6020  *  \throw If the connectivity data array has more than one component.
6021  *  \throw If the connectivity data array has a named component.
6022  *  \throw If the connectivity index data array has more than one component.
6023  *  \throw If the connectivity index data array has a named component.
6024  *  \throw If \a this->getMeshDimension() != 2.
6025  *  \throw If \a this->getSpaceDimension() != 3.
6026  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6027  */
6028 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6029 {
6030   checkCoherency();
6031   int spaceDim=getSpaceDimension();
6032   int meshDim=getMeshDimension();
6033   if(spaceDim!=3)
6034     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6035   if(meshDim!=2)
6036     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6037   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6038   ret->setMesh(this);
6039   int nbOfCells=getNumberOfCells();
6040   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6041   arr->alloc(nbOfCells,1);
6042   double *pt=arr->getPointer();
6043   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6044   const int *conn=_nodal_connec->getConstPointer();
6045   const int *connI=_nodal_connec_index->getConstPointer();
6046   const double *coo=_coords->getConstPointer();
6047   double tmp[12];
6048   for(int i=0;i<nbOfCells;i++,pt++)
6049     {
6050       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6051       switch(t)
6052         {
6053           case INTERP_KERNEL::NORM_QUAD4:
6054             {
6055               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6056               *pt=INTERP_KERNEL::quadWarp(tmp);
6057               break;
6058             }
6059         default:
6060           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6061         }
6062       conn+=connI[i+1]-connI[i];
6063     }
6064   ret->setName("Warp");
6065   ret->synchronizeTimeWithSupport();
6066   return ret.retn();
6067 }
6068
6069
6070 /*!
6071  * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6072  * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6073  * treated: INTERP_KERNEL::NORM_QUAD4.
6074  * For a cell of other type an exception is thrown.
6075  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6076  *          cells and one time, lying on \a this mesh. The caller is to delete this
6077  *          field using decrRef() as it is no more needed. 
6078  *  \throw If the coordinates array is not set.
6079  *  \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6080  *  \throw If the connectivity data array has more than one component.
6081  *  \throw If the connectivity data array has a named component.
6082  *  \throw If the connectivity index data array has more than one component.
6083  *  \throw If the connectivity index data array has a named component.
6084  *  \throw If \a this->getMeshDimension() != 2.
6085  *  \throw If \a this->getSpaceDimension() != 3.
6086  *  \throw If \a this mesh includes cells of type different from the ones enumerated above.
6087  */
6088 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6089 {
6090   checkCoherency();
6091   int spaceDim=getSpaceDimension();
6092   int meshDim=getMeshDimension();
6093   if(spaceDim!=3)
6094     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6095   if(meshDim!=2)
6096     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6097   MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6098   ret->setMesh(this);
6099   int nbOfCells=getNumberOfCells();
6100   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6101   arr->alloc(nbOfCells,1);
6102   double *pt=arr->getPointer();
6103   ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6104   const int *conn=_nodal_connec->getConstPointer();
6105   const int *connI=_nodal_connec_index->getConstPointer();
6106   const double *coo=_coords->getConstPointer();
6107   double tmp[12];
6108   for(int i=0;i<nbOfCells;i++,pt++)
6109     {
6110       INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6111       switch(t)
6112         {
6113           case INTERP_KERNEL::NORM_QUAD4:
6114             {
6115               FillInCompact3DMode(3,4,conn+1,coo,tmp);
6116               *pt=INTERP_KERNEL::quadSkew(tmp);
6117               break;
6118             }
6119         default:
6120           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6121         }
6122       conn+=connI[i+1]-connI[i];
6123     }
6124   ret->setName("Skew");
6125   ret->synchronizeTimeWithSupport();
6126   return ret.retn();
6127 }
6128
6129 /*!
6130  * This method aggregate the bbox of each cell and put it into bbox parameter.
6131  * \param bbox out parameter of size 2*spacedim*nbOfcells.
6132  */
6133 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6134 {
6135   int spaceDim=getSpaceDimension();
6136   int nbOfCells=getNumberOfCells();
6137   bbox.resize(2*nbOfCells*spaceDim);
6138   for(int i=0;i<nbOfCells*spaceDim;i++)
6139     {
6140       bbox[2*i]=std::numeric_limits<double>::max();
6141       bbox[2*i+1]=-std::numeric_limits<double>::max();
6142     }
6143   const double *coordsPtr=_coords->getConstPointer();
6144   const int *conn=_nodal_connec->getConstPointer();
6145   const int *connI=_nodal_connec_index->getConstPointer();
6146   for(int i=0;i<nbOfCells;i++)
6147     {
6148       int offset=connI[i]+1;
6149       int nbOfNodesForCell=connI[i+1]-offset;
6150       for(int j=0;j<nbOfNodesForCell;j++)
6151         {
6152           int nodeId=conn[offset+j];
6153           if(nodeId>=0)
6154             for(int k=0;k<spaceDim;k++)
6155               {
6156                 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6157                 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6158               }
6159         }
6160     }
6161 }
6162
6163 /// @cond INTERNAL
6164
6165 namespace ParaMEDMEMImpl
6166 {
6167   class ConnReader
6168   {
6169   public:
6170     ConnReader(const int *c, int val):_conn(c),_val(val) { }
6171     bool operator() (const int& pos) { return _conn[pos]!=_val; }
6172   private:
6173     const int *_conn;
6174     int _val;
6175   };
6176
6177   class ConnReader2
6178   {
6179   public:
6180     ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6181     bool operator() (const int& pos) { return _conn[pos]==_val; }
6182   private:
6183     const int *_conn;
6184     int _val;
6185   };
6186 }
6187
6188 /// @endcond
6189
6190 /*!
6191  * This method expects that \a this is sorted by types. If not an exception will be thrown.
6192  * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6193  * \a this is composed in cell types.
6194  * The returned array is of size 3*n where n is the number of different types present in \a this. 
6195  * For every k in [0,n] ret[3*k+2]==0 because it has no sense here. 
6196  * This parameter is kept only for compatibility with other methode listed above.
6197  */
6198 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6199 {
6200   checkConnectivityFullyDefined();
6201   const int *conn=_nodal_connec->getConstPointer();
6202   const int *connI=_nodal_connec_index->getConstPointer();
6203   const int *work=connI;
6204   int nbOfCells=getNumberOfCells();
6205   std::size_t n=getAllTypes().size();
6206   std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
6207   std::set<INTERP_KERNEL::NormalizedCellType> types;
6208   for(std::size_t i=0;work!=connI+nbOfCells;i++)
6209     {
6210       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6211       if(types.find(typ)!=types.end())
6212         {
6213           std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6214           oss << " is not contiguous !";
6215           throw INTERP_KERNEL::Exception(oss.str().c_str());
6216         }
6217       types.insert(typ);
6218       ret[3*i]=typ;
6219       const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6220       ret[3*i+1]=(int)std::distance(work,work2);
6221       work=work2;
6222     }
6223   return ret;
6224 }
6225
6226 /*!
6227  * This method is used to check that this has contiguous cell type in same order than described in \a code.
6228  * only for types cell, type node is not managed.
6229  * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6230  * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6231  * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6232  * If 2 or more same geometric type is in \a code and exception is thrown too.
6233  *
6234  * This method firstly checks
6235  * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6236  * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6237  * an exception is thrown too.
6238  * 
6239  * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6240  * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown 
6241  * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6242  */
6243 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6244 {
6245   if(code.empty())
6246     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6247   std::size_t sz=code.size();
6248   std::size_t n=sz/3;
6249   if(sz%3!=0)
6250     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6251   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6252   int nb=0;
6253   bool isNoPflUsed=true;
6254   for(std::size_t i=0;i<n;i++)
6255     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6256       {
6257         types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6258         nb+=code[3*i+1];
6259         if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6260           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6261         isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6262       }
6263   if(types.size()!=n)
6264     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6265   if(isNoPflUsed)
6266     {
6267       if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6268         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6269       if(types.size()==_types.size())
6270         return 0;
6271     }
6272   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6273   ret->alloc(nb,1);
6274   int *retPtr=ret->getPointer();
6275   const int *connI=_nodal_connec_index->getConstPointer();
6276   const int *conn=_nodal_connec->getConstPointer();
6277   int nbOfCells=getNumberOfCells();
6278   const int *i=connI;
6279   int kk=0;
6280   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6281     {
6282       i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6283       int offset=(int)std::distance(connI,i);
6284       const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6285       int nbOfCellsOfCurType=(int)std::distance(i,j);
6286       if(code[3*kk+2]==-1)
6287         for(int k=0;k<nbOfCellsOfCurType;k++)
6288           *retPtr++=k+offset;
6289       else
6290         {
6291           int idInIdsPerType=code[3*kk+2];
6292           if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6293             {
6294               const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6295               if(zePfl)
6296                 {
6297                   zePfl->checkAllocated();
6298                   if(zePfl->getNumberOfComponents()==1)
6299                     {
6300                       for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6301                         {
6302                           if(*k>=0 && *k<nbOfCellsOfCurType)
6303                             *retPtr=(*k)+offset;
6304                           else
6305                             {
6306                               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6307                               oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6308                               throw INTERP_KERNEL::Exception(oss.str().c_str());
6309                             }
6310                         }
6311                     }
6312                   else
6313                     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6314                 }
6315               else
6316                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6317             }
6318           else
6319             {
6320               std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6321               oss << " should be in [0," << idsPerType.size() << ") !";
6322               throw INTERP_KERNEL::Exception(oss.str().c_str());
6323             }
6324         }
6325       i=j;
6326     }
6327   return ret.retn();
6328 }
6329
6330 /*!
6331  * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6332  * This method is the opposite of MEDCouplingUMesh::checkTypeConsistencyAndContig method. Given a list of cells in \a profile it returns a list of sub-profiles sorted by geo type.
6333  * The result is put in the array \a idsPerType. In the returned parameter \a code, foreach i \a code[3*i+2] refers (if different from -1) to a location into the \a idsPerType.
6334  * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6335  * 
6336  * \param [out] code is a vector of size 3*n where n is the number of different geometric type in \a this \b reduced to the profile \a profile. \a code has exactly the same semantic than in MEDCouplingUMesh::checkTypeConsistencyAndContig method.
6337  * \param [out] idsInPflPerType is a vector of size of different geometric type in the subpart defined by \a profile of \a this ( equal to \a code.size()/3). For each i,
6338  *              \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6339  * \param [out] idsPerType is a vector of size of different sub profiles needed to be defined to represent the profile \a profile for a given geometric type.
6340  *              This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6341  * \throw if \a profile has not exactly one component. It throws too, if \a profile contains some values not in [0,getNumberOfCells()) or if \a this is not fully defined
6342  */
6343 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6344 {
6345   if(!profile)
6346     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6347   if(profile->getNumberOfComponents()!=1)
6348     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6349   checkConnectivityFullyDefined();
6350   const int *conn=_nodal_connec->getConstPointer();
6351   const int *connI=_nodal_connec_index->getConstPointer();
6352   int nbOfCells=getNumberOfCells();
6353   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6354   std::vector<int> typeRangeVals(1);
6355   for(const int *i=connI;i!=connI+nbOfCells;)
6356     {
6357       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6358       if(std::find(types.begin(),types.end(),curType)!=types.end())
6359         {
6360           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6361         }
6362       types.push_back(curType);
6363       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6364       typeRangeVals.push_back((int)std::distance(connI,i));
6365     }
6366   //
6367   DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6368   profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6369   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6370   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6371   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6372   //
6373   int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6374   code.resize(3*nbOfCastsFinal);
6375   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6376   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6377   for(int i=0;i<nbOfCastsFinal;i++)
6378     {
6379       int castId=castsPresent->getIJ(i,0);
6380       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6381       idsInPflPerType2.push_back(tmp3);
6382       code[3*i]=(int)types[castId];
6383       code[3*i+1]=tmp3->getNumberOfTuples();
6384       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6385       if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6386         {
6387           tmp4->copyStringInfoFrom(*profile);
6388           idsPerType2.push_back(tmp4);
6389           code[3*i+2]=(int)idsPerType2.size()-1;
6390         }
6391       else
6392         {
6393           code[3*i+2]=-1;
6394         }
6395     }
6396   std::size_t sz2=idsInPflPerType2.size();
6397   idsInPflPerType.resize(sz2);
6398   for(std::size_t i=0;i<sz2;i++)
6399     {
6400       DataArrayInt *locDa=idsInPflPerType2[i];
6401       locDa->incrRef();
6402       idsInPflPerType[i]=locDa;
6403     }
6404   std::size_t sz=idsPerType2.size();
6405   idsPerType.resize(sz);
6406   for(std::size_t i=0;i<sz;i++)
6407     {
6408       DataArrayInt *locDa=idsPerType2[i];
6409       locDa->incrRef();
6410       idsPerType[i]=locDa;
6411     }
6412 }
6413
6414 /*!
6415  * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6416  * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6417  * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6418  * This method returns 5+2 elements. 'desc', 'descIndx', 'revDesc', 'revDescIndx' and 'meshnM1' behaves exactly as ParaMEDMEM::MEDCouplingUMesh::buildDescendingConnectivity except the content as described after. The returned array specifies the n-1 mesh reordered by type as MEDMEM does. 'nM1LevMeshIds' contains the ids in returned 'meshnM1'. Finally 'meshnM1Old2New' contains numbering old2new that is to say the cell #k in coarse 'nM1LevMesh' will have the number ret[k] in returned mesh 'nM1LevMesh' MEDMEM reordered.
6419  */
6420 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6421 {
6422   checkFullyDefined();
6423   nM1LevMesh->checkFullyDefined();
6424   if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6425     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6426   if(_coords!=nM1LevMesh->getCoords())
6427     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6428   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6429   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6430   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6431   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6432   desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6433   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6434   tmp->setConnectivity(tmp0,tmp1);
6435   tmp->renumberCells(ret0->getConstPointer(),false);
6436   revDesc=tmp->getNodalConnectivity();
6437   revDescIndx=tmp->getNodalConnectivityIndex();
6438   DataArrayInt *ret=0;
6439   if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6440     {
6441       int tmp2;
6442       ret->getMaxValue(tmp2);
6443       ret->decrRef();
6444       std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6445       throw INTERP_KERNEL::Exception(oss.str().c_str());
6446     }
6447   nM1LevMeshIds=ret;
6448   //
6449   revDesc->incrRef();
6450   revDescIndx->incrRef();
6451   ret1->incrRef();
6452   ret0->incrRef();
6453   meshnM1Old2New=ret0;
6454   return ret1;
6455 }
6456
6457 /*!
6458  * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6459  * necessary for writing the mesh to MED file. Additionally returns a permutation array
6460  * in "Old to New" mode.
6461  *  \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6462  *          this array using decrRef() as it is no more needed.
6463  *  \throw If the nodal connectivity of cells is not defined.
6464  */
6465 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6466 {
6467   checkConnectivityFullyDefined();
6468   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6469   renumberCells(ret->getConstPointer(),false);
6470   return ret.retn();
6471 }
6472
6473 /*!
6474  * This methods checks that cells are sorted by their types.
6475  * This method makes asumption (no check) that connectivity is correctly set before calling.
6476  */
6477 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6478 {
6479   checkFullyDefined();
6480   const int *conn=_nodal_connec->getConstPointer();
6481   const int *connI=_nodal_connec_index->getConstPointer();
6482   int nbOfCells=getNumberOfCells();
6483   std::set<INTERP_KERNEL::NormalizedCellType> types;
6484   for(const int *i=connI;i!=connI+nbOfCells;)
6485     {
6486       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6487       if(types.find(curType)!=types.end())
6488         return false;
6489       types.insert(curType);
6490       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6491     }
6492   return true;
6493 }
6494
6495 /*!
6496  * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6497  * The geometric type order is specified by MED file.
6498  * 
6499  * \sa  MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6500  */
6501 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6502 {
6503   return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6504 }
6505
6506 /*!
6507  * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6508  * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6509  * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6510  * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6511  */
6512 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6513 {
6514   checkFullyDefined();
6515   const int *conn=_nodal_connec->getConstPointer();
6516   const int *connI=_nodal_connec_index->getConstPointer();
6517   int nbOfCells=getNumberOfCells();
6518   if(nbOfCells==0)
6519     return true;
6520   int lastPos=-1;
6521   std::set<INTERP_KERNEL::NormalizedCellType> sg;
6522   for(const int *i=connI;i!=connI+nbOfCells;)
6523     {
6524       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6525       const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6526       if(isTypeExists!=orderEnd)
6527         {
6528           int pos=(int)std::distance(orderBg,isTypeExists);
6529           if(pos<=lastPos)
6530             return false;
6531           lastPos=pos;
6532           i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6533         }
6534       else
6535         {
6536           if(sg.find(curType)==sg.end())
6537             {
6538               i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6539               sg.insert(curType);
6540             }
6541           else
6542             return false;
6543         }
6544     }
6545   return true;
6546 }
6547
6548 /*!
6549  * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6550  * that tells for each cell the pos of its type in the array on type given in input parameter. The 2nd output parameter is an array with the same
6551  * number of tuples than input type array and with one component. This 2nd output array gives type by type the number of occurence of type in 'this'.
6552  */
6553 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6554 {
6555   checkConnectivityFullyDefined();
6556   int nbOfCells=getNumberOfCells();
6557   const int *conn=_nodal_connec->getConstPointer();
6558   const int *connI=_nodal_connec_index->getConstPointer();
6559   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6560   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6561   tmpa->alloc(nbOfCells,1);
6562   tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6563   tmpb->fillWithZero();
6564   int *tmp=tmpa->getPointer();
6565   int *tmp2=tmpb->getPointer();
6566   for(const int *i=connI;i!=connI+nbOfCells;i++)
6567     {
6568       const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6569       if(where!=orderEnd)
6570         {
6571           int pos=(int)std::distance(orderBg,where);
6572           tmp2[pos]++;
6573           tmp[std::distance(connI,i)]=pos;
6574         }
6575       else
6576         {
6577           const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6578           std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6579           oss << " has a type " << cm.getRepr() << " not in input array of type !";
6580           throw INTERP_KERNEL::Exception(oss.str().c_str());
6581         }
6582     }
6583   nbPerType=tmpb.retn();
6584   return tmpa.retn();
6585 }
6586
6587 /*!
6588  * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6589  *
6590  * \return a new object containing the old to new correspondance.
6591  *
6592  * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6593  */
6594 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6595 {
6596   return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6597 }
6598
6599 /*!
6600  * This method is similar to method MEDCouplingUMesh::rearrange2ConsecutiveCellTypes except that the type order is specfied by [ \a orderBg , \a orderEnd ) (as MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method) and that this method is \b const and performs \b NO permutation in \a this.
6601  * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6602  * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6603  * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6604  */
6605 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6606 {
6607   DataArrayInt *nbPerType=0;
6608   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6609   nbPerType->decrRef();
6610   return tmpa->buildPermArrPerLevel();
6611 }
6612
6613 /*!
6614  * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6615  * The number of cells remains unchanged after the call of this method.
6616  * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6617  * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6618  *
6619  * \return the array giving the correspondance old to new.
6620  */
6621 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6622 {
6623   checkFullyDefined();
6624   computeTypes();
6625   const int *conn=_nodal_connec->getConstPointer();
6626   const int *connI=_nodal_connec_index->getConstPointer();
6627   int nbOfCells=getNumberOfCells();
6628   std::vector<INTERP_KERNEL::NormalizedCellType> types;
6629   for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6630     if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6631       {
6632         INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6633         types.push_back(curType);
6634         for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6635       }
6636   DataArrayInt *ret=DataArrayInt::New();
6637   ret->alloc(nbOfCells,1);
6638   int *retPtr=ret->getPointer();
6639   std::fill(retPtr,retPtr+nbOfCells,-1);
6640   int newCellId=0;
6641   for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6642     {
6643       for(const int *i=connI;i!=connI+nbOfCells;i++)
6644         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6645           retPtr[std::distance(connI,i)]=newCellId++;
6646     }
6647   renumberCells(retPtr,false);
6648   return ret;
6649 }
6650
6651 /*!
6652  * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6653  * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6654  * This method makes asumption that connectivity is correctly set before calling.
6655  */
6656 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6657 {
6658   checkFullyDefined();
6659   const int *conn=_nodal_connec->getConstPointer();
6660   const int *connI=_nodal_connec_index->getConstPointer();
6661   int nbOfCells=getNumberOfCells();
6662   std::vector<MEDCouplingUMesh *> ret;
6663   for(const int *i=connI;i!=connI+nbOfCells;)
6664     {
6665       INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6666       int beginCellId=(int)std::distance(connI,i);
6667       i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6668       int endCellId=(int)std::distance(connI,i);
6669       int sz=endCellId-beginCellId;
6670       int *cells=new int[sz];
6671       for(int j=0;j<sz;j++)
6672         cells[j]=beginCellId+j;
6673       MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6674       delete [] cells;
6675       ret.push_back(m);
6676     }
6677   return ret;
6678 }
6679
6680 /*!
6681  * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6682  * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6683  * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6684  *
6685  * \return a newly allocated instance, that the caller must manage.
6686  * \throw If \a this contains more than one geometric type.
6687  * \throw If the nodal connectivity of \a this is not fully defined.
6688  * \throw If the internal data is not coherent.
6689  */
6690 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6691 {
6692   checkConnectivityFullyDefined();
6693     if(_types.size()!=1)
6694     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6695   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6696   MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6697   ret->setCoords(getCoords());
6698   MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6699   if(retC)
6700     {
6701       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6702       retC->setNodalConnectivity(c);
6703     }
6704   else
6705     {
6706       MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6707       if(!retD)
6708         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6709       DataArrayInt *c=0,*ci=0;
6710       convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6711       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6712       retD->setNodalConnectivity(cs,cis);
6713     }
6714   return ret.retn();
6715 }
6716
6717 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6718 {
6719   checkConnectivityFullyDefined();
6720     if(_types.size()!=1)
6721     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6722   INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6723   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6724   if(cm.isDynamic())
6725     {
6726       std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6727       oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6728       throw INTERP_KERNEL::Exception(oss.str().c_str());
6729     }
6730   int nbCells=getNumberOfCells();
6731   int typi=(int)typ;
6732   int nbNodesPerCell=(int)cm.getNumberOfNodes();
6733   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6734   int *outPtr=connOut->getPointer();
6735   const int *conn=_nodal_connec->begin();
6736   const int *connI=_nodal_connec_index->begin();
6737   nbNodesPerCell++;
6738   for(int i=0;i<nbCells;i++,connI++)
6739     {
6740       if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6741         outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6742       else
6743         {
6744           std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : there something wrong in cell #" << i << " ! The type of cell is not those expected, or the length of nodal connectivity is not those expected (" << nbNodesPerCell-1 << ") !";
6745           throw INTERP_KERNEL::Exception(oss.str().c_str());
6746         }
6747     }
6748   return connOut.retn();
6749 }
6750
6751 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const throw(INTERP_KERNEL::Exception)
6752 {
6753   static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
6754   checkConnectivityFullyDefined();
6755   if(_types.size()!=1)
6756     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6757   int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6758   if(lgth<nbCells)
6759     throw INTERP_KERNEL::Exception(msg0);
6760   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6761   c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6762   int *cp(c->getPointer()),*cip(ci->getPointer());
6763   const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6764   cip[0]=0;
6765   for(int i=0;i<nbCells;i++,cip++,incip++)
6766     {
6767       int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6768       int delta(stop-strt);
6769       if(delta>=1)
6770         {
6771           if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6772             cp=std::copy(incp+strt,incp+stop,cp);
6773           else
6774             throw INTERP_KERNEL::Exception(msg0);
6775         }
6776       else
6777         throw INTERP_KERNEL::Exception(msg0);
6778       cip[1]=cip[0]+delta;
6779     }
6780   nodalConn=c.retn(); nodalConnIndex=ci.retn();
6781 }
6782
6783 /*!
6784  * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6785  * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6786  * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6787  * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6788  * are not used here to avoid the build of big permutation array.
6789  *
6790  * \param [in] ms meshes with same mesh dimension lying on the same coords and sorted by type following de the same geometric type order than
6791  *                those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6792  * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6793  *              in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6794  * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6795  *              output array gives for each chunck of same type the corresponding mesh id in \b ms.
6796  * \return A newly allocated unstructured mesh that is the result of the aggregation on same coords of all meshes in \b ms. This returned mesh
6797  *         is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6798  */
6799 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6800                                                                             DataArrayInt *&szOfCellGrpOfSameType,
6801                                                                             DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6802 {
6803   std::vector<const MEDCouplingUMesh *> ms2;
6804   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6805     if(*it)
6806       {
6807         (*it)->checkConnectivityFullyDefined();
6808         ms2.push_back(*it);
6809       }
6810   if(ms2.empty())
6811     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6812   const DataArrayDouble *refCoo=ms2[0]->getCoords();
6813   int meshDim=ms2[0]->getMeshDimension();
6814   std::vector<const MEDCouplingUMesh *> m1ssm;
6815   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6816   //
6817   std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6818   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6819   int fake=0,rk=0;
6820   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6821   ret1->alloc(0,1); ret2->alloc(0,1);
6822   for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6823     {
6824       if(meshDim!=(*it)->getMeshDimension())
6825         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6826       if(refCoo!=(*it)->getCoords())
6827         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6828       std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6829       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6830       std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6831       for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6832         {
6833           MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6834           m1ssmSingleAuto.push_back(singleCell);
6835           m1ssmSingle.push_back(singleCell);
6836           ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6837         }
6838     }
6839   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6840   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6841   std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6842   for(std::size_t i=0;i<m1ssm.size();i++)
6843     m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6844   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6845   szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6846   idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6847   return ret0.retn();
6848 }
6849
6850 /*!
6851  * This method returns a newly created DataArrayInt instance.
6852  * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6853  */
6854 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6855 {
6856   checkFullyDefined();
6857   const int *conn=_nodal_connec->getConstPointer();
6858   const int *connIndex=_nodal_connec_index->getConstPointer();
6859   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6860   for(const int *w=begin;w!=end;w++)
6861     if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6862       ret->pushBackSilent(*w);
6863   return ret.retn();
6864 }
6865
6866 /*!
6867  * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6868  * are in [0:getNumberOfCells())
6869  */
6870 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6871 {
6872   checkFullyDefined();
6873   const int *conn=_nodal_connec->getConstPointer();
6874   const int *connI=_nodal_connec_index->getConstPointer();
6875   int nbOfCells=getNumberOfCells();
6876   std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6877   int *tmp=new int[nbOfCells];
6878   for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6879     {
6880       int j=0;
6881       for(const int *i=connI;i!=connI+nbOfCells;i++)
6882         if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6883           tmp[std::distance(connI,i)]=j++;
6884     }
6885   DataArrayInt *ret=DataArrayInt::New();
6886   ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6887   ret->copyStringInfoFrom(*da);
6888   int *retPtr=ret->getPointer();
6889   const int *daPtr=da->getConstPointer();
6890   int nbOfElems=da->getNbOfElems();
6891   for(int k=0;k<nbOfElems;k++)
6892     retPtr[k]=tmp[daPtr[k]];
6893   delete [] tmp;
6894   return ret;
6895 }
6896
6897 /*!
6898  * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6899  * This method \b works \b for mesh sorted by type.
6900  * cells whose ids is in 'idsPerGeoType' array.
6901  * This method conserves coords and name of mesh.
6902  */
6903 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6904 {
6905   std::vector<int> code=getDistributionOfTypes();
6906   std::size_t nOfTypesInThis=code.size()/3;
6907   int sz=0,szOfType=0;
6908   for(std::size_t i=0;i<nOfTypesInThis;i++)
6909     {
6910       if(code[3*i]!=type)
6911         sz+=code[3*i+1];
6912       else
6913         szOfType=code[3*i+1];
6914     }
6915   for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6916     if(*work<0 || *work>=szOfType)
6917       {
6918         std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6919         oss << ". It should be in [0," << szOfType << ") !";
6920         throw INTERP_KERNEL::Exception(oss.str().c_str());
6921       }
6922   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6923   int *idsPtr=idsTokeep->getPointer();
6924   int offset=0;
6925   for(std::size_t i=0;i<nOfTypesInThis;i++)
6926     {
6927       if(code[3*i]!=type)
6928         for(int j=0;j<code[3*i+1];j++)
6929           *idsPtr++=offset+j;
6930       else
6931         idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6932       offset+=code[3*i+1];
6933     }
6934   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6935   ret->copyTinyInfoFrom(this);
6936   return ret.retn();
6937 }
6938
6939 /*!
6940  * This method returns a vector of size 'this->getNumberOfCells()'.
6941  * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6942  */
6943 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
6944 {
6945   int ncell=getNumberOfCells();
6946   std::vector<bool> ret(ncell);
6947   const int *cI=getNodalConnectivityIndex()->getConstPointer();
6948   const int *c=getNodalConnectivity()->getConstPointer();
6949   for(int i=0;i<ncell;i++)
6950     {
6951       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6952       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6953       ret[i]=cm.isQuadratic();
6954     }
6955   return ret;
6956 }
6957
6958 /*!
6959  * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6960  */
6961 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6962 {
6963   if(other->getType()!=UNSTRUCTURED)
6964     throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6965   const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6966   return MergeUMeshes(this,otherC);
6967 }
6968
6969 /*!
6970  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6971  * computed by averaging coordinates of cell nodes, so this method is not a right
6972  * choice for degnerated meshes (not well oriented, cells with measure close to zero).
6973  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6974  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6975  *          components. The caller is to delete this array using decrRef() as it is
6976  *          no more needed.
6977  *  \throw If the coordinates array is not set.
6978  *  \throw If the nodal connectivity of cells is not defined.
6979  *  \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6980  */
6981 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
6982 {
6983   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6984   int spaceDim=getSpaceDimension();
6985   int nbOfCells=getNumberOfCells();
6986   ret->alloc(nbOfCells,spaceDim);
6987   ret->copyStringInfoFrom(*getCoords());
6988   double *ptToFill=ret->getPointer();
6989   const int *nodal=_nodal_connec->getConstPointer();
6990   const int *nodalI=_nodal_connec_index->getConstPointer();
6991   const double *coor=_coords->getConstPointer();
6992   for(int i=0;i<nbOfCells;i++)
6993     {
6994       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6995       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6996       ptToFill+=spaceDim;
6997     }
6998   return ret.retn();
6999 }
7000
7001 /*!
7002  * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7003  * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the 
7004  * 
7005  * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned 
7006  *          DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7007  * 
7008  * \sa MEDCouplingUMesh::getBarycenterAndOwner
7009  * \throw If \a this is not fully defined (coordinates and connectivity)
7010  * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7011  */
7012 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7013 {
7014   checkFullyDefined();
7015   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7016   int spaceDim=getSpaceDimension();
7017   int nbOfCells=getNumberOfCells();
7018   int nbOfNodes=getNumberOfNodes();
7019   ret->alloc(nbOfCells,spaceDim);
7020   double *ptToFill=ret->getPointer();
7021   const int *nodal=_nodal_connec->getConstPointer();
7022   const int *nodalI=_nodal_connec_index->getConstPointer();
7023   const double *coor=_coords->getConstPointer();
7024   for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7025     {
7026       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7027       std::fill(ptToFill,ptToFill+spaceDim,0.);
7028       if(type!=INTERP_KERNEL::NORM_POLYHED)
7029         {
7030           for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7031             {
7032               if(*conn>=0 && *conn<nbOfNodes)
7033                 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7034               else
7035                 {
7036                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," <<   nbOfNodes << ") !";
7037                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7038                 }
7039             }
7040           int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7041           if(nbOfNodesInCell>0)
7042             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7043           else
7044             {
7045               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7046               throw INTERP_KERNEL::Exception(oss.str().c_str());
7047             }
7048         }
7049       else
7050         {
7051           std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7052           s.erase(-1);
7053           for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7054             {
7055               if(*it>=0 && *it<nbOfNodes)
7056                 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7057               else
7058                 {
7059                   std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," <<   nbOfNodes << ") !";
7060                   throw INTERP_KERNEL::Exception(oss.str().c_str());
7061                 }
7062             }
7063           if(!s.empty())
7064             std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7065           else
7066             {
7067               std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7068               throw INTERP_KERNEL::Exception(oss.str().c_str());
7069             }
7070         }
7071     }
7072   return ret.retn();
7073 }
7074
7075 /*!
7076  * Returns a new DataArrayDouble holding barycenters of specified cells. The
7077  * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7078  * are specified via an array of cell ids. 
7079  *  \warning Validity of the specified cell ids is not checked! 
7080  *           Valid range is [ 0, \a this->getNumberOfCells() ).
7081  *  \param [in] begin - an array of cell ids of interest.
7082  *  \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7083  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7084  *          end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7085  *          caller is to delete this array using decrRef() as it is no more needed. 
7086  *  \throw If the coordinates array is not set.
7087  *  \throw If the nodal connectivity of cells is not defined.
7088  *
7089  *  \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7090  *  \ref  py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7091  */
7092 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7093 {
7094   DataArrayDouble *ret=DataArrayDouble::New();
7095   int spaceDim=getSpaceDimension();
7096   int nbOfTuple=(int)std::distance(begin,end);
7097   ret->alloc(nbOfTuple,spaceDim);
7098   double *ptToFill=ret->getPointer();
7099   double *tmp=new double[spaceDim];
7100   const int *nodal=_nodal_connec->getConstPointer();
7101   const int *nodalI=_nodal_connec_index->getConstPointer();
7102   const double *coor=_coords->getConstPointer();
7103   for(const int *w=begin;w!=end;w++)
7104     {
7105       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7106       INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7107       ptToFill+=spaceDim;
7108     }
7109   delete [] tmp;
7110   return ret;
7111 }
7112
7113 /*!
7114  * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7115  * 
7116  */
7117 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7118 {
7119   if(!da)
7120     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7121   da->checkAllocated();
7122   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7123   ret->setCoords(da);
7124   int nbOfTuples=da->getNumberOfTuples();
7125   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7126   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7127   c->alloc(2*nbOfTuples,1);
7128   cI->alloc(nbOfTuples+1,1);
7129   int *cp=c->getPointer();
7130   int *cip=cI->getPointer();
7131   *cip++=0;
7132   for(int i=0;i<nbOfTuples;i++)
7133     {
7134       *cp++=INTERP_KERNEL::NORM_POINT1;
7135       *cp++=i;
7136       *cip++=2*(i+1);
7137     }
7138   ret->setConnectivity(c,cI,true);
7139   return ret.retn();
7140 }
7141 /*!
7142  * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7143  * Cells and nodes of
7144  * the first mesh precede cells and nodes of the second mesh within the result mesh.
7145  *  \param [in] mesh1 - the first mesh.
7146  *  \param [in] mesh2 - the second mesh.
7147  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7148  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7149  *          is no more needed.
7150  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7151  *  \throw If the coordinates array is not set in none of the meshes.
7152  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7153  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7154  */
7155 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7156 {
7157   std::vector<const MEDCouplingUMesh *> tmp(2);
7158   tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7159   return MergeUMeshes(tmp);
7160 }
7161
7162 /*!
7163  * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7164  * Cells and nodes of
7165  * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7166  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7167  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7168  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7169  *          is no more needed.
7170  *  \throw If \a a.size() == 0.
7171  *  \throw If \a a[ *i* ] == NULL.
7172  *  \throw If the coordinates array is not set in none of the meshes.
7173  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7174  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7175 */
7176 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7177 {
7178   std::size_t sz=a.size();
7179   if(sz==0)
7180     return MergeUMeshesLL(a);
7181   for(std::size_t ii=0;ii<sz;ii++)
7182     if(!a[ii])
7183       {
7184         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7185         throw INTERP_KERNEL::Exception(oss.str().c_str());
7186       }
7187   std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7188   std::vector< const MEDCouplingUMesh * > aa(sz);
7189   int spaceDim=-3;
7190   for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7191     {
7192       const MEDCouplingUMesh *cur=a[i];
7193       const DataArrayDouble *coo=cur->getCoords();
7194       if(coo)
7195         spaceDim=coo->getNumberOfComponents();
7196     }
7197   if(spaceDim==-3)
7198     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7199   for(std::size_t i=0;i<sz;i++)
7200     {
7201       bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7202       aa[i]=bb[i];
7203     }
7204   return MergeUMeshesLL(aa);
7205 }
7206
7207 /// @cond INTERNAL
7208
7209 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7210 {
7211   if(a.empty())
7212     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7213   std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7214   int meshDim=(*it)->getMeshDimension();
7215   int nbOfCells=(*it)->getNumberOfCells();
7216   int meshLgth=(*it++)->getMeshLength();
7217   for(;it!=a.end();it++)
7218     {
7219       if(meshDim!=(*it)->getMeshDimension())
7220         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7221       nbOfCells+=(*it)->getNumberOfCells();
7222       meshLgth+=(*it)->getMeshLength();
7223     }
7224   std::vector<const MEDCouplingPointSet *> aps(a.size());
7225   std::copy(a.begin(),a.end(),aps.begin());
7226   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7227   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7228   ret->setCoords(pts);
7229   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7230   c->alloc(meshLgth,1);
7231   int *cPtr=c->getPointer();
7232   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7233   cI->alloc(nbOfCells+1,1);
7234   int *cIPtr=cI->getPointer();
7235   *cIPtr++=0;
7236   int offset=0;
7237   int offset2=0;
7238   for(it=a.begin();it!=a.end();it++)
7239     {
7240       int curNbOfCell=(*it)->getNumberOfCells();
7241       const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7242       const int *curC=(*it)->_nodal_connec->getConstPointer();
7243       cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7244       for(int j=0;j<curNbOfCell;j++)
7245         {
7246           const int *src=curC+curCI[j];
7247           *cPtr++=*src++;
7248           for(;src!=curC+curCI[j+1];src++,cPtr++)
7249             {
7250               if(*src!=-1)
7251                 *cPtr=*src+offset2;
7252               else
7253                 *cPtr=-1;
7254             }
7255         }
7256       offset+=curCI[curNbOfCell];
7257       offset2+=(*it)->getNumberOfNodes();
7258     }
7259   //
7260   ret->setConnectivity(c,cI,true);
7261   return ret.retn();
7262 }
7263
7264 /// @endcond
7265
7266 /*!
7267  * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7268  * dimension and sharing the node coordinates array.
7269  * All cells of the first mesh precede all cells of the second mesh
7270  * within the result mesh. 
7271  *  \param [in] mesh1 - the first mesh.
7272  *  \param [in] mesh2 - the second mesh.
7273  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7274  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7275  *          is no more needed.
7276  *  \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7277  *  \throw If the meshes do not share the node coordinates array.
7278  *  \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7279  *  \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7280  */
7281 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7282 {
7283   std::vector<const MEDCouplingUMesh *> tmp(2);
7284   tmp[0]=mesh1; tmp[1]=mesh2;
7285   return MergeUMeshesOnSameCoords(tmp);
7286 }
7287
7288 /*!
7289  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7290  * dimension and sharing the node coordinates array.
7291  * All cells of the *i*-th mesh precede all cells of the
7292  * (*i*+1)-th mesh within the result mesh.
7293  *  \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7294  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7295  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7296  *          is no more needed.
7297  *  \throw If \a a.size() == 0.
7298  *  \throw If \a a[ *i* ] == NULL.
7299  *  \throw If the meshes do not share the node coordinates array.
7300  *  \throw If \a a[ *i* ]->getMeshDimension() < 0.
7301  *  \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7302  */
7303 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7304 {
7305   if(meshes.empty())
7306     throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7307   for(std::size_t ii=0;ii<meshes.size();ii++)
7308     if(!meshes[ii])
7309       {
7310         std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7311         throw INTERP_KERNEL::Exception(oss.str().c_str());
7312       }
7313   const DataArrayDouble *coords=meshes.front()->getCoords();
7314   int meshDim=meshes.front()->getMeshDimension();
7315   std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7316   int meshLgth=0;
7317   int meshIndexLgth=0;
7318   for(;iter!=meshes.end();iter++)
7319     {
7320       if(coords!=(*iter)->getCoords())
7321         throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7322       if(meshDim!=(*iter)->getMeshDimension())
7323         throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7324       meshLgth+=(*iter)->getMeshLength();
7325       meshIndexLgth+=(*iter)->getNumberOfCells();
7326     }
7327   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7328   nodal->alloc(meshLgth,1);
7329   int *nodalPtr=nodal->getPointer();
7330   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7331   nodalIndex->alloc(meshIndexLgth+1,1);
7332   int *nodalIndexPtr=nodalIndex->getPointer();
7333   int offset=0;
7334   for(iter=meshes.begin();iter!=meshes.end();iter++)
7335     {
7336       const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7337       const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7338       int nbOfCells=(*iter)->getNumberOfCells();
7339       int meshLgth2=(*iter)->getMeshLength();
7340       nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7341       if(iter!=meshes.begin())
7342         nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7343       else
7344         nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7345       offset+=meshLgth2;
7346     }
7347   MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7348   ret->setName("merge");
7349   ret->setMeshDimension(meshDim);
7350   ret->setConnectivity(nodal,nodalIndex,true);
7351   ret->setCoords(coords);
7352   return ret;
7353 }
7354
7355 /*!
7356  * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7357  * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7358  * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7359  * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7360  * New" mode are returned for each input mesh.
7361  *  \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7362  *  \param [in] compType - specifies a cell comparison technique. For meaning of its
7363  *          valid values [0,1,2], see zipConnectivityTraducer().
7364  *  \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7365  *          meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7366  *          mesh. The caller is to delete each of the arrays using decrRef() as it is
7367  *          no more needed.
7368  *  \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7369  *          MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7370  *          is no more needed.
7371  *  \throw If \a meshes.size() == 0.
7372  *  \throw If \a meshes[ *i* ] == NULL.
7373  *  \throw If the meshes do not share the node coordinates array.
7374  *  \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7375  *  \throw If the \a meshes are of different dimension (getMeshDimension()).
7376  *  \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7377  *  \throw If the nodal connectivity any of \a meshes includes an invalid id.
7378  */
7379 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7380 {
7381   //All checks are delegated to MergeUMeshesOnSameCoords
7382   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7383   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7384   corr.resize(meshes.size());
7385   std::size_t nbOfMeshes=meshes.size();
7386   int offset=0;
7387   const int *o2nPtr=o2n->getConstPointer();
7388   for(std::size_t i=0;i<nbOfMeshes;i++)
7389     {
7390       DataArrayInt *tmp=DataArrayInt::New();
7391       int curNbOfCells=meshes[i]->getNumberOfCells();
7392       tmp->alloc(curNbOfCells,1);
7393       std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7394       offset+=curNbOfCells;
7395       tmp->setName(meshes[i]->getName());
7396       corr[i]=tmp;
7397     }
7398   return ret.retn();
7399 }
7400
7401 /*!
7402  * Makes all given meshes share the nodal connectivity array. The common connectivity
7403  * array is created by concatenating the connectivity arrays of all given meshes. All
7404  * the given meshes must be of the same space dimension but dimension of cells **can
7405  * differ**. This method is particulary useful in MEDLoader context to build a \ref
7406  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7407  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7408  *  \param [in,out] meshes - a vector of meshes to update.
7409  *  \throw If any of \a meshes is NULL.
7410  *  \throw If the coordinates array is not set in any of \a meshes.
7411  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7412  *  \throw If \a meshes are of different space dimension.
7413  */
7414 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7415 {
7416   std::size_t sz=meshes.size();
7417   if(sz==0 || sz==1)
7418     return;
7419   std::vector< const DataArrayDouble * > coords(meshes.size());
7420   std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7421   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7422     {
7423       if((*it))
7424         {
7425           (*it)->checkConnectivityFullyDefined();
7426           const DataArrayDouble *coo=(*it)->getCoords();
7427           if(coo)
7428             *it2=coo;
7429           else
7430             {
7431               std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7432               oss << " has no coordinate array defined !";
7433               throw INTERP_KERNEL::Exception(oss.str().c_str());
7434             }
7435         }
7436       else
7437         {
7438           std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7439           oss << " is null !";
7440           throw INTERP_KERNEL::Exception(oss.str().c_str());
7441         }
7442     }
7443   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7444   std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7445   int offset=(*it)->getNumberOfNodes();
7446   (*it++)->setCoords(res);
7447   for(;it!=meshes.end();it++)
7448     {
7449       int oldNumberOfNodes=(*it)->getNumberOfNodes();
7450       (*it)->setCoords(res);
7451       (*it)->shiftNodeNumbersInConn(offset);
7452       offset+=oldNumberOfNodes;
7453     }
7454 }
7455
7456 /*!
7457  * Merges nodes coincident with a given precision within all given meshes that share
7458  * the nodal connectivity array. The given meshes **can be of different** mesh
7459  * dimension. This method is particulary useful in MEDLoader context to build a \ref
7460  * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7461  * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array. 
7462  *  \param [in,out] meshes - a vector of meshes to update.
7463  *  \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7464  *  \throw If any of \a meshes is NULL.
7465  *  \throw If the \a meshes do not share the same node coordinates array.
7466  *  \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7467  */
7468 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7469 {
7470   if(meshes.empty())
7471     return ;
7472   std::set<const DataArrayDouble *> s;
7473   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7474     {
7475       if(*it)
7476         s.insert((*it)->getCoords());
7477       else
7478         {
7479           std::ostringstream oss; oss << "MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords : In input vector of unstructured meshes of size " << meshes.size() << " the element #" << std::distance(meshes.begin(),it) << " is null !";
7480           throw INTERP_KERNEL::Exception(oss.str().c_str());
7481         }
7482     }
7483   if(s.size()!=1)
7484     {
7485       std::ostringstream oss; oss << "MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords : In input vector of unstructured meshes of size " << meshes.size() << ", it appears that they do not share the same instance of DataArrayDouble for coordiantes ! tryToShareSameCoordsPermute method can help to reach that !";
7486       throw INTERP_KERNEL::Exception(oss.str().c_str());
7487     }
7488   const DataArrayDouble *coo=*(s.begin());
7489   if(!coo)
7490     return;
7491   //
7492   DataArrayInt *comm,*commI;
7493   coo->findCommonTuples(eps,-1,comm,commI);
7494   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7495   int oldNbOfNodes=coo->getNumberOfTuples();
7496   int newNbOfNodes;
7497   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7498   if(oldNbOfNodes==newNbOfNodes)
7499     return ;
7500   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7501   for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7502     {
7503       (*it)->renumberNodesInConn(o2n->getConstPointer());
7504       (*it)->setCoords(newCoords);
7505     } 
7506 }
7507
7508 /*!
7509  * This method takes in input a cell defined by its MEDcouplingUMesh connectivity [ \a connBg , \a connEnd ) and returns its extruded cell by inserting the result at the end of ret.
7510  * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7511  * \param isQuad specifies the policy of connectivity.
7512  * @ret in/out parameter in which the result will be append
7513  */
7514 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7515 {
7516   INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7517   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7518   ret.push_back(cm.getExtrudedType());
7519   int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7520   switch(flatType)
7521     {
7522     case INTERP_KERNEL::NORM_POINT1:
7523       {
7524         ret.push_back(connBg[1]);
7525         ret.push_back(connBg[1]+nbOfNodesPerLev);
7526         break;
7527       }
7528     case INTERP_KERNEL::NORM_SEG2:
7529       {
7530         int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7531         ret.insert(ret.end(),conn,conn+4);
7532         break;
7533       }
7534     case INTERP_KERNEL::NORM_SEG3:
7535       {
7536         int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7537         ret.insert(ret.end(),conn,conn+8);
7538         break;
7539       }
7540     case INTERP_KERNEL::NORM_QUAD4:
7541       {
7542         int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7543         ret.insert(ret.end(),conn,conn+8);
7544         break;
7545       }
7546     case INTERP_KERNEL::NORM_TRI3:
7547       {
7548         int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7549         ret.insert(ret.end(),conn,conn+6);
7550         break;
7551       }
7552     case INTERP_KERNEL::NORM_TRI6:
7553       {
7554         int conn[15]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4],connBg[5],connBg[6],connBg[4]+deltaz,connBg[5]+deltaz,connBg[6]+deltaz,
7555                       connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7556         ret.insert(ret.end(),conn,conn+15);
7557         break;
7558       }
7559     case INTERP_KERNEL::NORM_QUAD8:
7560       {
7561         int conn[20]={
7562           connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7563           connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7564           connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7565         };
7566         ret.insert(ret.end(),conn,conn+20);
7567         break;
7568       }
7569     case INTERP_KERNEL::NORM_POLYGON:
7570       {
7571         std::back_insert_iterator< std::vector<int> > ii(ret);
7572         std::copy(connBg+1,connEnd,ii);
7573         *ii++=-1;
7574         std::reverse_iterator<const int *> rConnBg(connEnd);
7575         std::reverse_iterator<const int *> rConnEnd(connBg+1);
7576         std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7577         std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7578         for(std::size_t i=0;i<nbOfRadFaces;i++)
7579           {
7580             *ii++=-1;
7581             int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7582             std::copy(conn,conn+4,ii);
7583           }
7584         break;
7585       }
7586     default:
7587       throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7588     }
7589 }
7590
7591 /*!
7592  * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7593  */
7594 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7595 {
7596   double v[3]={0.,0.,0.};
7597   std::size_t sz=std::distance(begin,end);
7598   if(isQuadratic)
7599     sz/=2;
7600   for(std::size_t i=0;i<sz;i++)
7601     {
7602       v[0]+=coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]+2]-coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]+1];
7603       v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7604       v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7605     }
7606   return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7607 }
7608
7609 /*!
7610  * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7611  */
7612 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7613 {
7614   std::vector<std::pair<int,int> > edges;
7615   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7616   const int *bgFace=begin;
7617   for(std::size_t i=0;i<nbOfFaces;i++)
7618     {
7619       const int *endFace=std::find(bgFace+1,end,-1);
7620       std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7621       for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7622         {
7623           std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7624           if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7625             return false;
7626           edges.push_back(p1);
7627         }
7628       bgFace=endFace+1;
7629     }
7630   return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7631 }
7632
7633 /*!
7634  * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7635  */
7636 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7637 {
7638   double vec0[3],vec1[3];
7639   std::size_t sz=std::distance(begin,end);
7640   if(sz%2!=0)
7641     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7642   int nbOfNodes=(int)sz/2;
7643   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7644   const double *pt0=coords+3*begin[0];
7645   const double *pt1=coords+3*begin[nbOfNodes];
7646   vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7647   return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7648 }
7649
7650 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7651 {
7652   std::size_t sz=std::distance(begin,end);
7653   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7654   std::size_t nbOfNodes(sz/2);
7655   std::copy(begin,end,(int *)tmp);
7656   for(std::size_t j=1;j<nbOfNodes;j++)
7657     {
7658       begin[j]=tmp[nbOfNodes-j];
7659       begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7660     }
7661 }
7662
7663 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7664 {
7665   std::size_t sz=std::distance(begin,end);
7666   if(sz!=4)
7667     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7668   double vec0[3],vec1[3];
7669   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7670   vec0[0]=pt1[0]-pt0[0]; vec0[1]=pt1[1]-pt0[1]; vec0[2]=pt1[2]-pt0[2]; vec1[0]=pt2[0]-pt0[0]; vec1[1]=pt2[1]-pt0[1]; vec1[2]=pt2[2]-pt0[2]; 
7671   return ((vec0[1]*vec1[2]-vec0[2]*vec1[1])*(pt3[0]-pt0[0])+(vec0[2]*vec1[0]-vec0[0]*vec1[2])*(pt3[1]-pt0[1])+(vec0[0]*vec1[1]-vec0[1]*vec1[0])*(pt3[2]-pt0[2]))<0;
7672 }
7673
7674 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7675 {
7676   std::size_t sz=std::distance(begin,end);
7677   if(sz!=5)
7678     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7679   double vec0[3];
7680   INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7681   const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7682   return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7683 }
7684
7685 /*!
7686  * This method performs a simplyfication of a single polyedron cell. To do that each face of cell whose connectivity is defined by [ \b begin , \b end ) 
7687  * is compared with the others in order to find faces in the same plane (with approx of eps). If any, the cells are grouped together and projected to
7688  * a 2D space.
7689  *
7690  * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7691  * \param [in] coords the coordinates with nb of components exactly equal to 3
7692  * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7693  * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7694  * \param [out] res the result is put at the end of the vector without any alteration of the data.
7695  */
7696 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7697 {
7698   int nbFaces=std::count(begin+1,end,-1)+1;
7699   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7700   double *vPtr=v->getPointer();
7701   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7702   double *pPtr=p->getPointer();
7703   const int *stFaceConn=begin+1;
7704   for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7705     {
7706       const int *endFaceConn=std::find(stFaceConn,end,-1);
7707       ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7708       stFaceConn=endFaceConn+1;
7709     }
7710   pPtr=p->getPointer(); vPtr=v->getPointer();
7711   DataArrayInt *comm1=0,*commI1=0;
7712   v->findCommonTuples(eps,-1,comm1,commI1);
7713   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7714   const int *comm1Ptr=comm1->getConstPointer();
7715   const int *commI1Ptr=commI1->getConstPointer();
7716   int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7717   res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7718   //
7719   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7720   mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7721   mm->finishInsertingCells();
7722   //
7723   for(int i=0;i<nbOfGrps1;i++)
7724     {
7725       int vecId=comm1Ptr[commI1Ptr[i]];
7726       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7727       DataArrayInt *comm2=0,*commI2=0;
7728       tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7729       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7730       const int *comm2Ptr=comm2->getConstPointer();
7731       const int *commI2Ptr=commI2->getConstPointer();
7732       int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7733       for(int j=0;j<nbOfGrps2;j++)
7734         {
7735           if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7736             {
7737               res->insertAtTheEnd(begin,end);
7738               res->pushBackSilent(-1);
7739             }
7740           else
7741             {
7742               int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7743               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7744               ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7745               DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7746               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7747               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7748               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7749               MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7750               const int *idsNodePtr=idsNode->getConstPointer();
7751               double center[3]; center[0]=pPtr[pointId]*vPtr[3*vecId]; center[1]=pPtr[pointId]*vPtr[3*vecId+1]; center[2]=pPtr[pointId]*vPtr[3*vecId+2];
7752               double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7753               double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7754               if(std::abs(norm)>eps)
7755                 {
7756                   double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7757                   mm3->rotate(center,vec,angle);
7758                 }
7759               mm3->changeSpaceDimension(2);
7760               MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7761               const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7762               const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7763               int nbOfCells=mm4->getNumberOfCells();
7764               for(int k=0;k<nbOfCells;k++)
7765                 {
7766                   int l=0;
7767                   for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7768                     res->pushBackSilent(idsNodePtr[*work]);
7769                   res->pushBackSilent(-1);
7770                 }
7771             }
7772         }
7773     }
7774   res->popBackSilent();
7775 }
7776
7777 /*!
7778  * This method computes the normalized vector of the plane and the pos of the point belonging to the plane and the line defined by the vector going
7779  * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7780  * 
7781  * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7782  * \param [in] coords coordinates expected to have 3 components.
7783  * \param [in] begin start of the nodal connectivity of the face.
7784  * \param [in] end end of the nodal connectivity (excluded) of the face.
7785  * \param [out] v the normalized vector of size 3
7786  * \param [out] p the pos of plane
7787  */
7788 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7789 {
7790   std::size_t nbPoints=std::distance(begin,end);
7791   if(nbPoints<3)
7792     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7793   double vec[3]={0.,0.,0.};
7794   std::size_t j=0;
7795   bool refFound=false;
7796   for(;j<nbPoints-1 && !refFound;j++)
7797     {
7798       vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7799       vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7800       vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7801       double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7802       if(norm>eps)
7803         {
7804           refFound=true;
7805           vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7806         }
7807     }
7808   for(std::size_t i=j;i<nbPoints-1;i++)
7809     {
7810       double curVec[3];
7811       curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7812       curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7813       curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7814       double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7815       if(norm<eps)
7816         continue;
7817       curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7818       v[0]=vec[1]*curVec[2]-vec[2]*curVec[1]; v[1]=vec[2]*curVec[0]-vec[0]*curVec[2]; v[2]=vec[0]*curVec[1]-vec[1]*curVec[0];
7819       norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7820       if(norm>eps)
7821         {
7822           v[0]/=norm; v[1]/=norm; v[2]/=norm;
7823           *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7824           return ;
7825         }
7826     }
7827   throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7828 }
7829
7830 /*!
7831  * This method tries to obtain a well oriented polyhedron.
7832  * If the algorithm fails, an exception will be thrown.
7833  */
7834 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7835 {
7836   std::list< std::pair<int,int> > edgesOK,edgesFinished;
7837   std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7838   std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7839   isPerm[0]=true;
7840   int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7841   std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7842   for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7843   //
7844   while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7845     {
7846       bgFace=begin;
7847       std::size_t smthChanged=0;
7848       for(std::size_t i=0;i<nbOfFaces;i++)
7849         {
7850           endFace=std::find(bgFace+1,end,-1);
7851           nbOfEdgesInFace=std::distance(bgFace,endFace);
7852           if(!isPerm[i])
7853             {
7854               bool b;
7855               for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7856                 {
7857                   std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7858                   std::pair<int,int> p2(p1.second,p1.first);
7859                   bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7860                   bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7861                   if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7862                 }
7863               if(isPerm[i])
7864                 { 
7865                   if(!b)
7866                     std::reverse(bgFace+1,endFace);
7867                   for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7868                     {
7869                       std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7870                       std::pair<int,int> p2(p1.second,p1.first);
7871                       if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7872                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7873                       if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7874                         { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7875                       std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7876                       if(it!=edgesOK.end())
7877                         {
7878                           edgesOK.erase(it);
7879                           edgesFinished.push_back(p1);
7880                         }
7881                       else
7882                         edgesOK.push_back(p1);
7883                     }
7884                 }
7885             }
7886           bgFace=endFace+1;
7887         }
7888       if(smthChanged==0)
7889         { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7890     }
7891   if(!edgesOK.empty())
7892     { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7893   if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7894     {//not lucky ! The first face was not correctly oriented : reorient all faces...
7895       bgFace=begin;
7896       for(std::size_t i=0;i<nbOfFaces;i++)
7897         {
7898           endFace=std::find(bgFace+1,end,-1);
7899           std::reverse(bgFace+1,endFace);
7900           bgFace=endFace+1;
7901         }
7902     }
7903 }
7904
7905 /*!
7906  * This method makes the assumption spacedimension == meshdimension == 2.
7907  * This method works only for linear cells.
7908  * 
7909  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7910  */
7911 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7912 {
7913   if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7914     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7915   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7916   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7917   int nbOfNodesExpected=m->getNumberOfNodes();
7918   if(m->getNumberOfCells()!=nbOfNodesExpected)
7919     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7920   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7921   const int *n2oPtr=n2o->getConstPointer();
7922   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7923   m->getReverseNodalConnectivity(revNodal,revNodalI);
7924   const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7925   const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7926   const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7927   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7928   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYGON;
7929   if(nbOfNodesExpected<1)
7930     return ret.retn();
7931   int prevCell=0;
7932   int prevNode=nodalPtr[nodalIPtr[0]+1];
7933   *work++=n2oPtr[prevNode];
7934   for(int i=1;i<nbOfNodesExpected;i++)
7935     {
7936       if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7937         {
7938           std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
7939           conn.erase(prevNode);
7940           if(conn.size()==1)
7941             {
7942               int curNode=*(conn.begin());
7943               *work++=n2oPtr[curNode];
7944               std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
7945               shar.erase(prevCell);
7946               if(shar.size()==1)
7947                 {
7948                   prevCell=*(shar.begin());
7949                   prevNode=curNode;
7950                 }
7951               else
7952                 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
7953             }
7954           else
7955             throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
7956         }
7957       else
7958         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
7959     }
7960   return ret.retn();
7961 }
7962
7963 /*!
7964  * This method makes the assumption spacedimension == meshdimension == 3.
7965  * This method works only for linear cells.
7966  * 
7967  * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7968  */
7969 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
7970 {
7971   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7972     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7973   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7974   const int *conn=m->getNodalConnectivity()->getConstPointer();
7975   const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
7976   int nbOfCells=m->getNumberOfCells();
7977   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7978   int *work=ret->getPointer();  *work++=INTERP_KERNEL::NORM_POLYHED;
7979   if(nbOfCells<1)
7980     return ret.retn();
7981   work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7982   for(int i=1;i<nbOfCells;i++)
7983     {
7984       *work++=-1;
7985       work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7986     }
7987   return ret.retn();
7988 }
7989
7990 /*!
7991  * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
7992  * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
7993  */
7994 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
7995 {
7996   double *w=zipFrmt;
7997   if(spaceDim==3)
7998     for(int i=0;i<nbOfNodesInCell;i++)
7999       w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8000   else if(spaceDim==2)
8001     {
8002       for(int i=0;i<nbOfNodesInCell;i++)
8003         {
8004           w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8005           *w++=0.;
8006         }
8007     }
8008   else
8009     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8010 }
8011
8012 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8013 {
8014   int nbOfCells=getNumberOfCells();
8015   if(nbOfCells<=0)
8016     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8017   static const int PARAMEDMEM2VTKTYPETRADUCER[INTERP_KERNEL::NORM_MAXTYPE+1]={1,3,21,5,9,7,22,34,23,28,-1,-1,-1,-1,10,14,13,-1,12,-1,24,-1,16,27,-1,26,-1,29,-1,-1,25,42,-1,4};
8018   ofs << "  <" << getVTKDataSetType() << ">\n";
8019   ofs << "    <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8020   ofs << "      <PointData>\n" << pointData << std::endl;
8021   ofs << "      </PointData>\n";
8022   ofs << "      <CellData>\n" << cellData << std::endl;
8023   ofs << "      </CellData>\n";
8024   ofs << "      <Points>\n";
8025   if(getSpaceDimension()==3)
8026     _coords->writeVTK(ofs,8,"Points");
8027   else
8028     {
8029       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8030       coo->writeVTK(ofs,8,"Points");
8031     }
8032   ofs << "      </Points>\n";
8033   ofs << "      <Cells>\n";
8034   const int *cPtr=_nodal_connec->getConstPointer();
8035   const int *cIPtr=_nodal_connec_index->getConstPointer();
8036   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8037   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8038   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8039   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8040   int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8041   int szFaceOffsets=0,szConn=0;
8042   for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8043     {
8044       *w2=cPtr[cIPtr[i]];
8045       if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8046         {
8047           *w1=-1;
8048           *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8049           w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8050         }
8051       else
8052         {
8053           int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8054           *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8055           std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8056           *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8057           w4=std::copy(c.begin(),c.end(),w4);
8058         }
8059     }
8060   types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8061   types->writeVTK(ofs,8,"UInt8","types");
8062   offsets->writeVTK(ofs,8,"Int32","offsets");
8063   if(szFaceOffsets!=0)
8064     {//presence of Polyhedra
8065       connectivity->reAlloc(szConn);
8066       faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8067       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8068       w1=faces->getPointer();
8069       for(int i=0;i<nbOfCells;i++)
8070         if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8071           {
8072             int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8073             *w1++=nbFaces;
8074             const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8075             for(int j=0;j<nbFaces;j++)
8076               {
8077                 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8078                 *w1++=(int)std::distance(w6,w5);
8079                 w1=std::copy(w6,w5,w1);
8080                 w6=w5+1;
8081               }
8082           }
8083       faces->writeVTK(ofs,8,"Int32","faces");
8084     }
8085   connectivity->writeVTK(ofs,8,"Int32","connectivity");
8086   ofs << "      </Cells>\n";
8087   ofs << "    </Piece>\n";
8088   ofs << "  </" << getVTKDataSetType() << ">\n";
8089 }
8090
8091 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8092 {
8093   stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8094   if(_mesh_dim==-2)
8095     { stream << " Not set !"; return ; }
8096   stream << " Mesh dimension : " << _mesh_dim << ".";
8097   if(_mesh_dim==-1)
8098     return ;
8099   if(!_coords)
8100     { stream << " No coordinates set !"; return ; }
8101   if(!_coords->isAllocated())
8102     { stream << " Coordinates set but not allocated !"; return ; }
8103   stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8104   stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8105   if(!_nodal_connec_index)
8106     { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8107   if(!_nodal_connec_index->isAllocated())
8108     { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8109   int lgth=_nodal_connec_index->getNumberOfTuples();
8110   int cpt=_nodal_connec_index->getNumberOfComponents();
8111   if(cpt!=1 || lgth<1)
8112     return ;
8113   stream << std::endl << "Number of cells : " << lgth-1 << ".";
8114 }
8115
8116 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8117 {
8118   return std::string("UnstructuredGrid");
8119 }
8120
8121 /*!
8122  * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8123  * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8124  * addition, returns two arrays mapping cells of the result mesh to cells of the input
8125  * meshes.
8126  *  \param [in] m1 - the first input mesh which is a partitioned object.
8127  *  \param [in] m2 - the second input mesh which is a partition tool.
8128  *  \param [in] eps - precision used to detect coincident mesh entities.
8129  *  \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8130  *         cell an id of the cell of \a m1 it comes from. The caller is to delete
8131  *         this array using decrRef() as it is no more needed.
8132  *  \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8133  *         cell an id of the cell of \a m2 it comes from. -1 value means that a
8134  *         result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8135  *         any cell of \a m2. The caller is to delete this array using decrRef() as
8136  *         it is no more needed.  
8137  *  \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8138  *         MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8139  *         is no more needed.  
8140  *  \throw If the coordinates array is not set in any of the meshes.
8141  *  \throw If the nodal connectivity of cells is not defined in any of the meshes.
8142  *  \throw If any of the meshes is not a 2D mesh in 2D space.
8143  */
8144 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8145 {
8146   m1->checkFullyDefined();
8147   m2->checkFullyDefined();
8148   if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8149     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2  with meshdim equal to 2 and spaceDim equal to 2 too!");
8150   std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8151   MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8152   DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8153   std::vector<double> addCoo,addCoordsQuadratic;
8154   INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8155   INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8156   IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8157                               m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8158   revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8159   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8160   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8161   std::vector< std::vector<int> > intersectEdge2;
8162   BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8163   subDiv2.clear(); dd5=0; dd6=0;
8164   std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8165   std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8166   BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8167                                     /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8168   //
8169   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8170   addCooDa->alloc((int)(addCoo.size())/2,2);
8171   std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8172   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8173   addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8174   std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8175   std::vector<const DataArrayDouble *> coordss(4);
8176   coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8177   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8178   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8179   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8180   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8181   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8182   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8183   ret->setConnectivity(conn,connI,true);
8184   ret->setCoords(coo);
8185   cellNb1=c1.retn(); cellNb2=c2.retn();
8186   return ret.retn();
8187 }
8188
8189 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8190                                                          const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8191                                                          const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8192                                                          const std::vector<double>& addCoords,
8193                                                          std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8194 {
8195   static const int SPACEDIM=2;
8196   std::vector<double> bbox1,bbox2;
8197   const double *coo1=m1->getCoords()->getConstPointer();
8198   const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8199   const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8200   int offset1=m1->getNumberOfNodes();
8201   const double *coo2=m2->getCoords()->getConstPointer();
8202   const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8203   const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8204   int offset2=offset1+m2->getNumberOfNodes();
8205   int offset3=offset2+((int)addCoords.size())/2;
8206   m1->getBoundingBoxForBBTree(bbox1);
8207   m2->getBoundingBoxForBBTree(bbox2);
8208   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8209   int ncell1=m1->getNumberOfCells();
8210   crI.push_back(0);
8211   for(int i=0;i<ncell1;i++)
8212     {
8213       std::vector<int> candidates2;
8214       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8215       std::map<INTERP_KERNEL::Node *,int> mapp;
8216       std::map<int,INTERP_KERNEL::Node *> mappRev;
8217       INTERP_KERNEL::QuadraticPolygon pol1;
8218       INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8219       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8220       MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8221       pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8222                                    desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8223       //
8224       std::set<INTERP_KERNEL::Edge *> edges1;// store all edges of pol1 that are NOT consumed by intersect cells. If any after iteration over candidates2 -> a part of pol1 should appear in result
8225       std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8226       INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8227       for(it1.first();!it1.finished();it1.next())
8228         edges1.insert(it1.current()->getPtr());
8229       //
8230       std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8231       std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8232       int ii=0;
8233       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8234         {
8235           INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8236           const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8237           MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8238           pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8239                                              pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8240         }
8241       ii=0;
8242       for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8243         {
8244           pol1.initLocationsWithOther(pol2s[ii]);
8245           pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8246           //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8247           pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8248         }
8249       if(!edges1.empty())
8250         {
8251           try
8252             {
8253               INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8254             }
8255           catch(INTERP_KERNEL::Exception& e)
8256             {
8257               std::ostringstream oss; oss << "Error when computing residual of cell #" << i << " in source/m1 mesh ! Maybe the neighbours of this cell in mesh are not well connected !\n" << "The deep reason is the following : " << e.what();
8258               throw INTERP_KERNEL::Exception(oss.str().c_str());
8259             }
8260         }
8261       for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8262         (*it).second->decrRef();
8263     }
8264 }
8265
8266 /*!
8267  * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8268  * 
8269  */
8270 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8271                                                    std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8272                                                    MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8273                                                    MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8274                                                    std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8275 {
8276   static const int SPACEDIM=2;
8277   desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8278   desc2=DataArrayInt::New();
8279   descIndx2=DataArrayInt::New();
8280   revDesc2=DataArrayInt::New();
8281   revDescIndx2=DataArrayInt::New();
8282   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8283   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8284   m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8285   m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8286   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8287   const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8288   const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8289   std::vector<double> bbox1,bbox2;
8290   m1Desc->getBoundingBoxForBBTree(bbox1);
8291   m2Desc->getBoundingBoxForBBTree(bbox2);
8292   int ncell1=m1Desc->getNumberOfCells();
8293   int ncell2=m2Desc->getNumberOfCells();
8294   intersectEdge1.resize(ncell1);
8295   colinear2.resize(ncell2);
8296   subDiv2.resize(ncell2);
8297   BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8298   std::vector<int> candidates1(1);
8299   int offset1=m1->getNumberOfNodes();
8300   int offset2=offset1+m2->getNumberOfNodes();
8301   for(int i=0;i<ncell1;i++)
8302     {
8303       std::vector<int> candidates2;
8304       myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8305       if(!candidates2.empty())
8306         {
8307           std::map<INTERP_KERNEL::Node *,int> map1,map2;
8308           INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8309           candidates1[0]=i;
8310           INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8311           pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8312           delete pol2;
8313           delete pol1;
8314         }
8315       else
8316         intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8317     }
8318   m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8319   m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8320 }
8321
8322 /*!
8323  * This method performs the 2nd step of Partition of 2D mesh.
8324  * This method has 4 inputs :
8325  *  - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8326  *  - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8327  *  - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8328  * The aim of this method is to sort the splitting nodes, if any, and to put in 'intersectEdge' output paramter based on edges of mesh 'm2'
8329  * \param m1 is expected to be a mesh of meshDimension equal to 1 and spaceDim equal to 2. No check of that is performed by this method. Only present for its coords in case of 'subDiv' shares some nodes of 'm1'
8330  * \param m2 is expected to be a mesh of meshDimension equal to 1 and spaceDim equal to 2. No check of that is performed by this method.
8331  * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8332  */
8333 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, const std::vector<double>& addCoo, const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge) throw(INTERP_KERNEL::Exception)
8334 {
8335   int offset1=m1->getNumberOfNodes();
8336   int ncell=m2->getNumberOfCells();
8337   const int *c=m2->getNodalConnectivity()->getConstPointer();
8338   const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8339   const double *coo=m2->getCoords()->getConstPointer();
8340   const double *cooBis=m1->getCoords()->getConstPointer();
8341   int offset2=offset1+m2->getNumberOfNodes();
8342   intersectEdge.resize(ncell);
8343   for(int i=0;i<ncell;i++,cI++)
8344     {
8345       const std::vector<int>& divs=subDiv[i];
8346       int nnode=cI[1]-cI[0]-1;
8347       std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8348       std::map<INTERP_KERNEL::Node *, int> mapp22;
8349       for(int j=0;j<nnode;j++)
8350         {
8351           INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8352           int nnid=c[(*cI)+j+1];
8353           mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8354           mapp22[nn]=nnid+offset1;
8355         }
8356       INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8357       for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8358         ((*it).second.first)->decrRef();
8359       std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8360       std::map<INTERP_KERNEL::Node *,int> mapp3;
8361       for(std::size_t j=0;j<divs.size();j++)
8362         {
8363           int id=divs[j];
8364           INTERP_KERNEL::Node *tmp=0;
8365           if(id<offset1)
8366             tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8367           else if(id<offset2)
8368             tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8369           else
8370             tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8371           addNodes[j]=tmp;
8372           mapp3[tmp]=id;
8373         }
8374       e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8375       for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8376         (*it)->decrRef();
8377       e->decrRef();
8378     }
8379 }
8380
8381 /*!
8382  * This method is part of the Slice3D algorithm. It is the first step of assembly process, ones coordinates have been computed (by MEDCouplingUMesh::split3DCurveWithPlane method).
8383  * This method allows to compute given the status of 3D curve cells and the descending connectivity 3DSurf->3DCurve to deduce the intersection of each 3D surf cells
8384  * with a plane. The result will be put in 'cut3DSuf' out parameter.
8385  * \param [in] cut3DCurve  input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8386  * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8387  * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8388  * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8389  * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8390  * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8391  * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8392  * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8393  * \param [out] cut3DSuf input/output param.
8394  */
8395 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8396                                                    const int *nodal3DCurve, const int *nodalIndx3DCurve,
8397                                                    const int *desc, const int *descIndx, 
8398                                                    std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8399 {
8400   std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8401   int nbOf3DSurfCell=(int)cut3DSurf.size();
8402   for(int i=0;i<nbOf3DSurfCell;i++)
8403     {
8404       std::vector<int> res;
8405       int offset=descIndx[i];
8406       int nbOfSeg=descIndx[i+1]-offset;
8407       for(int j=0;j<nbOfSeg;j++)
8408         {
8409           int edgeId=desc[offset+j];
8410           int status=cut3DCurve[edgeId];
8411           if(status!=-2)
8412             {
8413               if(status>-1)
8414                 res.push_back(status);
8415               else
8416                 {
8417                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8418                   res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8419                 }
8420             }
8421         }
8422       switch(res.size())
8423         {
8424         case 2:
8425           {
8426             cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8427             break;
8428           }
8429         case 1:
8430         case 0:
8431           {
8432             std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8433             std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8434             if(res.size()==2)
8435               {
8436                 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8437               }
8438             else
8439               {
8440                 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8441               }
8442             break;
8443           }
8444         default:
8445           {// case when plane is on a multi colinear edge of a polyhedron
8446             if((int)res.size()==2*nbOfSeg)
8447               {
8448                 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8449               }
8450             else
8451               throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8452           }
8453         }
8454     }
8455 }
8456
8457 /*!
8458  * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8459  * This method is part of the Slice3D algorithm. It is the second step of assembly process, ones coordinates have been computed (by MEDCouplingUMesh::split3DCurveWithPlane method).
8460  * This method allows to compute given the result of 3D surf cells with plane and the descending connectivity 3D->3DSurf to deduce the intersection of each 3D cells
8461  * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8462  * \param cut3DSurf  input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8463  * \param desc is the descending connectivity 3D->3DSurf
8464  * \param descIndx is the descending connectivity index 3D->3DSurf
8465  */
8466 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8467                                                   const int *desc, const int *descIndx,
8468                                                   DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8469 {
8470   checkFullyDefined();
8471   if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8472     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8473   const int *nodal3D=_nodal_connec->getConstPointer();
8474   const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8475   int nbOfCells=getNumberOfCells();
8476   for(int i=0;i<nbOfCells;i++)
8477     {
8478       std::map<int, std::set<int> > m;
8479       int offset=descIndx[i];
8480       int nbOfFaces=descIndx[i+1]-offset;
8481       int start=-1;
8482       int end=-1;
8483       for(int j=0;j<nbOfFaces;j++)
8484         {
8485           const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8486           if(p.first!=-1 && p.second!=-1)
8487             {
8488               if(p.first!=-2)
8489                 {
8490                   start=p.first; end=p.second;
8491                   m[p.first].insert(p.second);
8492                   m[p.second].insert(p.first);
8493                 }
8494               else
8495                 {
8496                   const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8497                   int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8498                   INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8499                   INTERP_KERNEL::NormalizedCellType cmsId;
8500                   unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8501                   start=tmp[0]; end=tmp[nbOfNodesSon-1];
8502                   for(unsigned k=0;k<nbOfNodesSon;k++)
8503                     {
8504                       m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8505                       m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8506                     }
8507                 }
8508             }
8509         }
8510       if(m.empty())
8511         continue;
8512       std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8513       int prev=end;
8514       while(end!=start)
8515         {
8516           std::map<int, std::set<int> >::const_iterator it=m.find(start);
8517           const std::set<int>& s=(*it).second;
8518           std::set<int> s2; s2.insert(prev);
8519           std::set<int> s3;
8520           std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8521           if(s3.size()==1)
8522             {
8523               int val=*s3.begin();
8524               conn.push_back(start);
8525               prev=start;
8526               start=val;
8527             }
8528           else
8529             start=end;
8530         }
8531       conn.push_back(end);
8532       if(conn.size()>3)
8533         {
8534           nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8535           nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8536           cellIds->pushBackSilent(i);
8537         }
8538     }
8539 }
8540
8541 /*!
8542  * This method compute the convex hull of a single 2D cell. This method tries to conserve at maximum the given input connectivity. In particular, if the orientation of cell is not clockwise
8543  * as in MED format norm. If definitely the result of Jarvis algorithm is not matchable with the input connectivity, the result will be copied into \b nodalConnecOut parameter and
8544  * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8545  * This method excepts that \b coords parameter is expected to be in dimension 2. [ \b nodalConnBg , \b nodalConnEnd ) is the nodal connectivity of the input
8546  * cell (geometric cell type included at the position 0). If the meshdimension of the input cell is not equal to 2 an INTERP_KERNEL::Exception will be thrown.
8547  * 
8548  * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8549  */
8550 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8551 {
8552   std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8553   if(sz>=4)
8554     {
8555       const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8556       if(cm.getDimension()==2)
8557         {
8558           const int *node=nodalConnBg+1;
8559           int startNode=*node++;
8560           double refX=coords[2*startNode];
8561           for(;node!=nodalConnEnd;node++)
8562             {
8563               if(coords[2*(*node)]<refX)
8564                 {
8565                   startNode=*node;
8566                   refX=coords[2*startNode];
8567                 }
8568             }
8569           std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8570           refX=1e300;
8571           double tmp1;
8572           double tmp2[2];
8573           double angle0=-M_PI/2;
8574           //
8575           int nextNode=-1;
8576           int prevNode=-1;
8577           double resRef;
8578           double angleNext=0.;
8579           while(nextNode!=startNode)
8580             {
8581               nextNode=-1;
8582               resRef=1e300;
8583               for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8584                 {
8585                   if(*node!=tmpOut.back() && *node!=prevNode)
8586                     {
8587                       tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8588                       double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8589                       double res;
8590                       if(angleM<=angle0)
8591                         res=angle0-angleM;
8592                       else
8593                         res=angle0-angleM+2.*M_PI;
8594                       if(res<resRef)
8595                         {
8596                           nextNode=*node;
8597                           resRef=res;
8598                           angleNext=angleM;
8599                         }
8600                     }
8601                 }
8602               if(nextNode!=startNode)
8603                 {
8604                   angle0=angleNext-M_PI;
8605                   if(angle0<-M_PI)
8606                     angle0+=2*M_PI;
8607                   prevNode=tmpOut.back();
8608                   tmpOut.push_back(nextNode);
8609                 }
8610             }
8611           std::vector<int> tmp3(2*(sz-1));
8612           std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8613           std::copy(nodalConnBg+1,nodalConnEnd,it);
8614           if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8615             {
8616               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8617               return false;
8618             }
8619           if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8620             {
8621               nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8622               return false;
8623             }
8624           else
8625             {
8626               nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8627               nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8628               return true;
8629             }
8630         }
8631       else
8632         throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8633     }
8634   else
8635     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8636 }
8637
8638 /*!
8639  * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8640  * This method will not impact the size of inout parameter \b arrIndx but the size of \b arr will be modified in case of suppression.
8641  * 
8642  * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8643  * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8644  * \param [in,out] arr array in which the remove operation will be done.
8645  * \param [in,out] arrIndx array in the remove operation will modify
8646  * \param [in] offsetForRemoval (by default 0) offset so that for each i in [0,arrIndx->getNumberOfTuples()-1) removal process will be performed in the following range [arr+arrIndx[i]+offsetForRemoval,arr+arr[i+1])
8647  * \return true if \b arr and \b arrIndx have been modified, false if not.
8648  */
8649 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8650 {
8651   if(!arrIndx || !arr)
8652     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8653   if(offsetForRemoval<0)
8654     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8655   std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8656   int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8657   int *arrIPtr=arrIndx->getPointer();
8658   *arrIPtr++=0;
8659   int previousArrI=0;
8660   const int *arrPtr=arr->getConstPointer();
8661   std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8662   for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8663     {
8664       if(*arrIPtr-previousArrI>offsetForRemoval)
8665         {
8666           for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8667             {
8668               if(s.find(*work)==s.end())
8669                 arrOut.push_back(*work);
8670             }
8671         }
8672       previousArrI=*arrIPtr;
8673       *arrIPtr=(int)arrOut.size();
8674     }
8675   if(arr->getNumberOfTuples()==(int)arrOut.size())
8676     return false;
8677   arr->alloc((int)arrOut.size(),1);
8678   std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8679   return true;
8680 }
8681
8682 /*!
8683  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8684  * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8685  * The selection of extraction is done standardly in new2old format.
8686  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8687  *
8688  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8689  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8690  * \param [in] arrIn arr origin array from which the extraction will be done.
8691  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8692  * \param [out] arrOut the resulting array
8693  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8694  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
8695  */
8696 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8697                                                 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8698 {
8699   if(!arrIn || !arrIndxIn)
8700     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8701   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8702   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8703     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
8704   std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8705   const int *arrInPtr=arrIn->getConstPointer();
8706   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8707   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8708   if(nbOfGrps<0)
8709     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8710   int maxSizeOfArr=arrIn->getNumberOfTuples();
8711   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8712   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8713   arrIo->alloc((int)(sz+1),1);
8714   const int *idsIt=idsOfSelectBg;
8715   int *work=arrIo->getPointer();
8716   *work++=0;
8717   int lgth=0;
8718   for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8719     {
8720       if(*idsIt>=0 && *idsIt<nbOfGrps)
8721         lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8722       else
8723         {
8724           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8725           throw INTERP_KERNEL::Exception(oss.str().c_str());
8726         }
8727       if(lgth>=work[-1])
8728         *work=lgth;
8729       else
8730         {
8731           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8732           oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8733           throw INTERP_KERNEL::Exception(oss.str().c_str());
8734         }
8735     }
8736   arro->alloc(lgth,1);
8737   work=arro->getPointer();
8738   idsIt=idsOfSelectBg;
8739   for(std::size_t i=0;i<sz;i++,idsIt++)
8740     {
8741       if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8742         work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8743       else
8744         {
8745           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8746           oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8747           throw INTERP_KERNEL::Exception(oss.str().c_str());
8748         }
8749     }
8750   arrOut=arro.retn();
8751   arrIndexOut=arrIo.retn();
8752 }
8753
8754 /*!
8755  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8756  * This method returns the result of the extraction ( specified by a set of ids with a slice given by \a idsOfSelectStart, \a idsOfSelectStop and \a idsOfSelectStep ).
8757  * The selection of extraction is done standardly in new2old format.
8758  * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8759  *
8760  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8761  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8762  * \param [in] arrIn arr origin array from which the extraction will be done.
8763  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8764  * \param [out] arrOut the resulting array
8765  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8766  * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
8767  */
8768 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8769                                                  DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8770 {
8771   if(!arrIn || !arrIndxIn)
8772     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
8773   arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8774   if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8775     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
8776   int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
8777   const int *arrInPtr=arrIn->getConstPointer();
8778   const int *arrIndxPtr=arrIndxIn->getConstPointer();
8779   int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8780   if(nbOfGrps<0)
8781     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8782   int maxSizeOfArr=arrIn->getNumberOfTuples();
8783   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8784   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8785   arrIo->alloc((int)(sz+1),1);
8786   int idsIt=idsOfSelectStart;
8787   int *work=arrIo->getPointer();
8788   *work++=0;
8789   int lgth=0;
8790   for(std::size_t i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
8791     {
8792       if(idsIt>=0 && idsIt<nbOfGrps)
8793         lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
8794       else
8795         {
8796           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8797           throw INTERP_KERNEL::Exception(oss.str().c_str());
8798         }
8799       if(lgth>=work[-1])
8800         *work=lgth;
8801       else
8802         {
8803           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
8804           oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
8805           throw INTERP_KERNEL::Exception(oss.str().c_str());
8806         }
8807     }
8808   arro->alloc(lgth,1);
8809   work=arro->getPointer();
8810   idsIt=idsOfSelectStart;
8811   for(std::size_t i=0;i<sz;i++,idsIt+=idsOfSelectStep)
8812     {
8813       if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
8814         work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
8815       else
8816         {
8817           std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
8818           oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8819           throw INTERP_KERNEL::Exception(oss.str().c_str());
8820         }
8821     }
8822   arrOut=arro.retn();
8823   arrIndexOut=arrIo.retn();
8824 }
8825
8826 /*!
8827  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8828  * This method builds an output pair (\b arrOut,\b arrIndexOut) that is a copy from \b arrIn for all cell ids \b not \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) and for
8829  * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8830  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8831  *
8832  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8833  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8834  * \param [in] arrIn arr origin array from which the extraction will be done.
8835  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8836  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8837  * \param [in] srcArrIndex index array of \b srcArr
8838  * \param [out] arrOut the resulting array
8839  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8840  * 
8841  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8842  */
8843 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8844                                               const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8845                                               DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8846 {
8847   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8848     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8849   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8850   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8851   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8852   std::vector<bool> v(nbOfTuples,true);
8853   int offset=0;
8854   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8855   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8856   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8857     {
8858       if(*it>=0 && *it<nbOfTuples)
8859         {
8860           v[*it]=false;
8861           offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8862         }
8863       else
8864         {
8865           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8866           throw INTERP_KERNEL::Exception(oss.str().c_str());
8867         }
8868     }
8869   srcArrIndexPtr=srcArrIndex->getConstPointer();
8870   arrIo->alloc(nbOfTuples+1,1);
8871   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8872   const int *arrInPtr=arrIn->getConstPointer();
8873   const int *srcArrPtr=srcArr->getConstPointer();
8874   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8875   int *arroPtr=arro->getPointer();
8876   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8877     {
8878       if(v[ii])
8879         {
8880           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8881           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8882         }
8883       else
8884         {
8885           std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8886           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8887           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8888         }
8889     }
8890   arrOut=arro.retn();
8891   arrIndexOut=arrIo.retn();
8892 }
8893
8894 /*!
8895  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8896  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8897  *
8898  * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8899  * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8900  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8901  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8902  * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8903  * \param [in] srcArrIndex index array of \b srcArr
8904  * 
8905  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8906  */
8907 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8908                                                      const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8909 {
8910   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8911     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8912   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8913   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8914   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8915   int *arrInOutPtr=arrInOut->getPointer();
8916   const int *srcArrPtr=srcArr->getConstPointer();
8917   for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8918     {
8919       if(*it>=0 && *it<nbOfTuples)
8920         {
8921           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8922             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8923           else
8924             {
8925               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " id (idsOfSelectBg[" << std::distance(idsOfSelectBg,it)<< "]) is " << *it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
8926               throw INTERP_KERNEL::Exception(oss.str().c_str());
8927             }
8928         }
8929       else
8930         {
8931           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8932           throw INTERP_KERNEL::Exception(oss.str().c_str());
8933         }
8934     }
8935 }
8936
8937 /*!
8938  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8939  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8940  * This method start from id 0 that will be contained in output DataArrayInt. It searches then all neighbors of id0 regarding arrIn[arrIndxIn[0]:arrIndxIn[0+1]].
8941  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8942  * A negative value in \b arrIn means that it is ignored.
8943  * This method is useful to see if a mesh is contiguous regarding its connectivity. If it is not the case the size of returned array is different from arrIndxIn->getNumberOfTuples()-1.
8944  * 
8945  * \param [in] arrIn arr origin array from which the extraction will be done.
8946  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8947  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8948  * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8949  */
8950 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
8951 {
8952   int seed=0,nbOfDepthPeelingPerformed=0;
8953   return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
8954 }
8955
8956 /*!
8957  * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8958  * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8959  * This method start from id 0 that will be contained in output DataArrayInt. It searches then all neighbors of id0 regarding arrIn[arrIndxIn[0]:arrIndxIn[0+1]].
8960  * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8961  * A negative value in \b arrIn means that it is ignored.
8962  * This method is useful to see if a mesh is contiguous regarding its connectivity. If it is not the case the size of returned array is different from arrIndxIn->getNumberOfTuples()-1.
8963  * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
8964  * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
8965  * \param [in] arrIn arr origin array from which the extraction will be done.
8966  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8967  * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8968  * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8969  * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8970  * \sa MEDCouplingUMesh::partitionBySpreadZone
8971  */
8972 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8973 {
8974   nbOfDepthPeelingPerformed=0;
8975   if(!arrIndxIn)
8976     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8977   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8978   if(nbOfTuples<=0)
8979     {
8980       DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
8981       return ret;
8982     }
8983   //
8984   std::vector<bool> fetched(nbOfTuples,false);
8985   return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
8986 }
8987
8988 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8989 {
8990   nbOfDepthPeelingPerformed=0;
8991   if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
8992     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
8993   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8994   std::vector<bool> fetched2(nbOfTuples,false);
8995   int i=0;
8996   for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
8997     {
8998       if(*seedElt>=0 && *seedElt<nbOfTuples)
8999         { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9000       else
9001         { std::ostringstream oss; oss << "MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : At pos #" << i << " of seeds value is " << *seedElt << "! Should be in [0," << nbOfTuples << ") !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
9002     }
9003   const int *arrInPtr=arrIn->getConstPointer();
9004   const int *arrIndxPtr=arrIndxIn->getConstPointer();
9005   int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9006   std::vector<int> idsToFetch1(seedBg,seedEnd);
9007   std::vector<int> idsToFetch2;
9008   std::vector<int> *idsToFetch=&idsToFetch1;
9009   std::vector<int> *idsToFetchOther=&idsToFetch2;
9010   while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9011     {
9012       for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9013         for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9014           if(!fetched[*it2])
9015             { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9016       std::swap(idsToFetch,idsToFetchOther);
9017       idsToFetchOther->clear();
9018       nbOfDepthPeelingPerformed++;
9019     }
9020   int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9021   i=0;
9022   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9023   int *retPtr=ret->getPointer();
9024   for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9025     if(*it)
9026       *retPtr++=i;
9027   return ret.retn();
9028 }
9029
9030 /*!
9031  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9032  * This method builds an output pair (\b arrOut,\b arrIndexOut) that is a copy from \b arrIn for all cell ids \b not \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) and for
9033  * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9034  * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9035  *
9036  * \param [in] start begin of set of ids of the input extraction (included)
9037  * \param [in] end end of set of ids of the input extraction (excluded)
9038  * \param [in] step step of the set of ids in range mode.
9039  * \param [in] arrIn arr origin array from which the extraction will be done.
9040  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9041  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9042  * \param [in] srcArrIndex index array of \b srcArr
9043  * \param [out] arrOut the resulting array
9044  * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9045  * 
9046  * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9047  */
9048 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9049                                                const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9050                                                DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9051 {
9052   if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9053     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9054   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9055   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9056   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9057   int offset=0;
9058   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9059   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9060   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9061   int it=start;
9062   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9063     {
9064       if(it>=0 && it<nbOfTuples)
9065         offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9066       else
9067         {
9068           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9069           throw INTERP_KERNEL::Exception(oss.str().c_str());
9070         }
9071     }
9072   srcArrIndexPtr=srcArrIndex->getConstPointer();
9073   arrIo->alloc(nbOfTuples+1,1);
9074   arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9075   const int *arrInPtr=arrIn->getConstPointer();
9076   const int *srcArrPtr=srcArr->getConstPointer();
9077   int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9078   int *arroPtr=arro->getPointer();
9079   for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9080     {
9081       int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9082       if(pos<0)
9083         {
9084           arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9085           *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9086         }
9087       else
9088         {
9089           arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9090           *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9091         }
9092     }
9093   arrOut=arro.retn();
9094   arrIndexOut=arrIo.retn();
9095 }
9096
9097 /*!
9098  * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9099  * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9100  *
9101  * \param [in] start begin of set of ids of the input extraction (included)
9102  * \param [in] end end of set of ids of the input extraction (excluded)
9103  * \param [in] step step of the set of ids in range mode.
9104  * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9105  * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9106  * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9107  * \param [in] srcArrIndex index array of \b srcArr
9108  * 
9109  * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9110  */
9111 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9112                                                       const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9113 {
9114   if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9115     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9116   int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9117   const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9118   const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9119   int *arrInOutPtr=arrInOut->getPointer();
9120   const int *srcArrPtr=srcArr->getConstPointer();
9121   int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9122   int it=start;
9123   for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9124     {
9125       if(it>=0 && it<nbOfTuples)
9126         {
9127           if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9128             std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9129           else
9130             {
9131               std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9132               throw INTERP_KERNEL::Exception(oss.str().c_str());
9133             }
9134         }
9135       else
9136         {
9137           std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9138           throw INTERP_KERNEL::Exception(oss.str().c_str());
9139         }
9140     }
9141 }
9142
9143 /*!
9144  * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9145  * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9146  * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9147  * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9148  * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9149  * 
9150  * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9151  */
9152 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9153 {
9154   checkFullyDefined();
9155   int mdim=getMeshDimension();
9156   int spaceDim=getSpaceDimension();
9157   if(mdim!=spaceDim)
9158     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9159   std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9160   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9161   std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9162   MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9163   ret->setCoords(getCoords());
9164   ret->allocateCells((int)partition.size());
9165   //
9166   for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9167     {
9168       MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9169       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9170       switch(mdim)
9171         {
9172         case 2:
9173           cell=tmp->buildUnionOf2DMesh();
9174           break;
9175         case 3:
9176           cell=tmp->buildUnionOf3DMesh();
9177           break;
9178         default:
9179           throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9180         }
9181       
9182       ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9183     }
9184   //
9185   ret->finishInsertingCells();
9186   return ret.retn();
9187 }
9188
9189 /*!
9190  * This method partitions \b this into contiguous zone.
9191  * This method only needs a well defined connectivity. Coordinates are not considered here.
9192  * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9193  */
9194 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9195 {
9196   //#if 0
9197   int nbOfCellsCur=getNumberOfCells();
9198   std::vector<DataArrayInt *> ret;
9199   if(nbOfCellsCur<=0)
9200     return ret;
9201   DataArrayInt *neigh=0,*neighI=0;
9202   computeNeighborsOfCells(neigh,neighI);
9203   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9204   std::vector<bool> fetchedCells(nbOfCellsCur,false);
9205   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9206   int seed=0;
9207   while(seed<nbOfCellsCur)
9208     {
9209       int nbOfPeelPerformed=0;
9210       ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9211       seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9212     }
9213   for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9214     ret.push_back((*it).retn());
9215   return ret;
9216   //#endif
9217 #if 0
9218   int nbOfCellsCur=getNumberOfCells();
9219   DataArrayInt *neigh=0,*neighI=0;
9220   computeNeighborsOfCells(neigh,neighI);
9221   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9222   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9223   std::vector<DataArrayInt *> ret;
9224   std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9225   while(nbOfCellsCur>0)
9226     {
9227       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9228       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9229       MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9230       ret2.push_back(tmp2);  ret.push_back(tmp2);
9231       nbOfCellsCur=tmp3->getNumberOfTuples();
9232       if(nbOfCellsCur>0)
9233         {
9234           ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9235           MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9236           neighAuto=neigh;
9237           neighIAuto=neighI;
9238           MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9239           neighAuto->transformWithIndArr(renum->begin(),renum->end());
9240         }
9241     }
9242   for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9243     (*it)->incrRef();
9244   return ret;
9245 #endif
9246 }
9247
9248 /*!
9249  * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9250  * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9251  *
9252  * \param [in] code a code with the same format than those returned by MEDCouplingUMesh::getDistributionOfTypes except for the code[3*k+2] that should contain start id of chunck.
9253  * \return a newly allocated DataArrayInt to be managed by the caller.
9254  * \throw In case of \a code has not the right format (typically of size 3*n)
9255  */
9256 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9257 {
9258   MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9259   std::size_t nb=code.size()/3;
9260   if(code.size()%3!=0)
9261     throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9262   ret->alloc((int)nb,2);
9263   int *retPtr=ret->getPointer();
9264   for(std::size_t i=0;i<nb;i++,retPtr+=2)
9265     {
9266       retPtr[0]=code[3*i+2];
9267       retPtr[1]=code[3*i+2]+code[3*i+1];
9268     }
9269   return ret.retn();
9270 }
9271
9272 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9273                                                                                    _own_cell(true),_cell_id(-1),_nb_cell(0)
9274 {
9275   if(mesh)
9276     {
9277       mesh->incrRef();
9278       _nb_cell=mesh->getNumberOfCells();
9279     }
9280 }
9281
9282 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9283 {
9284   if(_mesh)
9285     _mesh->decrRef();
9286   if(_own_cell)
9287     delete _cell;
9288 }
9289
9290 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9291                                                                                                                                _own_cell(false),_cell_id(bg-1),
9292                                                                                                                                _nb_cell(end)
9293 {
9294   if(mesh)
9295     mesh->incrRef();
9296 }
9297
9298 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9299 {
9300   _cell_id++;
9301   if(_cell_id<_nb_cell)
9302     {
9303       _cell->next();
9304       return _cell;
9305     }
9306   else
9307     return 0;
9308 }
9309
9310 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9311 {
9312   if(_mesh)
9313     _mesh->incrRef();
9314 }
9315
9316 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9317 {
9318   return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9319 }
9320
9321 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9322 {
9323   if(_mesh)
9324     _mesh->decrRef();
9325 }
9326
9327 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh,  INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9328                                                                                                                                                                   _itc(itc),
9329                                                                                                                                                                   _bg(bg),_end(end)
9330 {
9331   if(_mesh)
9332     _mesh->incrRef();
9333 }
9334
9335 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9336 {
9337   if(_mesh)
9338     _mesh->decrRef();
9339 }
9340
9341 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9342 {
9343   return _type;
9344 }
9345
9346 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9347 {
9348   return _end-_bg;
9349 }
9350
9351 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9352 {
9353   return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9354 }
9355
9356 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9357 {
9358   if(mesh)
9359     {
9360       mesh->incrRef();
9361       _nb_cell=mesh->getNumberOfCells();
9362     }
9363 }
9364
9365 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9366 {
9367   if(_mesh)
9368     _mesh->decrRef();
9369   delete _cell;
9370 }
9371
9372 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9373 {
9374   const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9375   const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9376   if(_cell_id<_nb_cell)
9377     {
9378       INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9379       int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9380       int startId=_cell_id;
9381       _cell_id+=nbOfElems;
9382       return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9383     }
9384   else
9385     return 0;
9386 }
9387
9388 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9389 {
9390   if(mesh)
9391     {
9392       _conn=mesh->getNodalConnectivity()->getPointer();
9393       _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9394     }
9395 }
9396
9397 void MEDCouplingUMeshCell::next()
9398 {
9399   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9400     {
9401       _conn+=_conn_lgth;
9402       _conn_indx++;
9403     }
9404   _conn_lgth=_conn_indx[1]-_conn_indx[0];
9405 }
9406
9407 std::string MEDCouplingUMeshCell::repr() const
9408 {
9409   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9410     {
9411       std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9412       oss << " : ";
9413       std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9414       return oss.str();
9415     }
9416   else
9417     return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9418 }
9419
9420 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9421 {
9422   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9423     return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9424   else
9425     return INTERP_KERNEL::NORM_ERROR;
9426 }
9427
9428 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9429 {
9430   lgth=_conn_lgth;
9431   if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9432     return _conn;
9433   else
9434     return 0;
9435 }