Salome HOME
writeVTK for image grid
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingIMesh.cxx
1 // Copyright (C) 2007-2014  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, or (at your option) any later version.
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 "MEDCouplingIMesh.hxx"
22 #include "MEDCouplingCMesh.hxx"
23 #include "MEDCouplingMemArray.hxx"
24 #include "MEDCouplingFieldDouble.hxx"
25
26 #include <functional>
27 #include <algorithm>
28 #include <sstream>
29 #include <numeric>
30
31 using namespace ParaMEDMEM;
32
33 MEDCouplingIMesh::MEDCouplingIMesh():_space_dim(-1)
34 {
35   _origin[0]=0.; _origin[1]=0.; _origin[2]=0.;
36   _dxyz[0]=0.; _dxyz[1]=0.; _dxyz[2]=0.;
37   _structure[0]=0; _structure[1]=0; _structure[2]=0;
38 }
39
40 MEDCouplingIMesh::MEDCouplingIMesh(const MEDCouplingIMesh& other, bool deepCopy):MEDCouplingStructuredMesh(other,deepCopy),_space_dim(other._space_dim),_axis_unit(other._axis_unit)
41 {
42   _origin[0]=other._origin[0]; _origin[1]=other._origin[1]; _origin[2]=other._origin[2];
43   _dxyz[0]=other._dxyz[0]; _dxyz[1]=other._dxyz[1]; _dxyz[2]=other._dxyz[2];
44   _structure[0]=other._structure[0]; _structure[1]=other._structure[1]; _structure[2]=other._structure[2];
45 }
46
47 MEDCouplingIMesh::~MEDCouplingIMesh()
48 {
49 }
50
51 MEDCouplingIMesh *MEDCouplingIMesh::New()
52 {
53   return new MEDCouplingIMesh;
54 }
55
56 MEDCouplingIMesh *MEDCouplingIMesh::New(const std::string& meshName, int spaceDim, const int *nodeStrctStart, const int *nodeStrctStop,
57                                         const double *originStart, const double *originStop, const double *dxyzStart, const double *dxyzStop)
58 {
59   MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> ret(new MEDCouplingIMesh);
60   ret->setName(meshName);
61   ret->setSpaceDimension(spaceDim);
62   ret->setNodeStruct(nodeStrctStart,nodeStrctStop);
63   ret->setOrigin(originStart,originStop);
64   ret->setDXYZ(dxyzStart,dxyzStop);
65   return ret.retn();
66 }
67
68 MEDCouplingMesh *MEDCouplingIMesh::deepCpy() const
69 {
70   return clone(true);
71 }
72
73 MEDCouplingIMesh *MEDCouplingIMesh::clone(bool recDeepCpy) const
74 {
75   return new MEDCouplingIMesh(*this,recDeepCpy);
76 }
77
78 void MEDCouplingIMesh::setNodeStruct(const int *nodeStrctStart, const int *nodeStrctStop)
79 {
80   checkSpaceDimension();
81   int sz((int)std::distance(nodeStrctStart,nodeStrctStop));
82   if(sz!=_space_dim)
83     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::setNodeStruct : input vector of node structure has not the right size ! Or change space dimension before calling it !");
84   std::copy(nodeStrctStart,nodeStrctStop,_structure);
85   declareAsNew();
86 }
87
88 std::vector<int> MEDCouplingIMesh::getNodeStruct() const
89 {
90   checkSpaceDimension();
91   return std::vector<int>(_structure,_structure+_space_dim);
92 }
93
94 void MEDCouplingIMesh::setOrigin(const double *originStart, const double *originStop)
95 {
96   checkSpaceDimension();
97   int sz((int)std::distance(originStart,originStop));
98   if(sz!=_space_dim)
99     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::setOrigin : input vector of origin vector has not the right size ! Or change space dimension before calling it !");
100   std::copy(originStart,originStop,_origin);
101   declareAsNew();
102 }
103
104 std::vector<double> MEDCouplingIMesh::getOrigin() const
105 {
106   checkSpaceDimension();
107   return std::vector<double>(_origin,_origin+_space_dim);
108 }
109
110 void MEDCouplingIMesh::setDXYZ(const double *dxyzStart, const double *dxyzStop)
111 {
112   checkSpaceDimension();
113   int sz((int)std::distance(dxyzStart,dxyzStop));
114   if(sz!=_space_dim)
115     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::setDXYZ : input vector of dxyz vector has not the right size ! Or change space dimension before calling it !");
116   std::copy(dxyzStart,dxyzStop,_dxyz);
117   declareAsNew();
118 }
119
120 std::vector<double> MEDCouplingIMesh::getDXYZ() const
121 {
122   checkSpaceDimension();
123   return std::vector<double>(_dxyz,_dxyz+_space_dim);
124 }
125
126 void MEDCouplingIMesh::setAxisUnit(const std::string& unitName)
127 {
128   _axis_unit=unitName;
129   declareAsNew();
130 }
131
132 std::string MEDCouplingIMesh::getAxisUnit() const
133 {
134   return _axis_unit;
135 }
136
137 /*!
138  * This method returns the measure of any cell in \a this.
139  * This specific method of image grid mesh utilizes the fact that any cell in \a this have the same measure.
140  * The value returned by this method is those used to feed the returned field in the MEDCouplingIMesh::getMeasureField.
141  *
142  * \sa getMeasureField
143  */
144 double MEDCouplingIMesh::getMeasureOfAnyCell() const
145 {
146   checkCoherency();
147   int dim(getSpaceDimension());
148   double ret(1.);
149   for(int i=0;i<dim;i++)
150     ret*=fabs(_dxyz[i]);
151   return ret;
152 }
153
154 /*!
155  * This method is allows to convert \a this into MEDCouplingCMesh instance.
156  * This method is the middle level between MEDCouplingIMesh and the most general MEDCouplingUMesh.
157  * This method is useful for MED writers that do not have still the image grid support.
158  *
159  * \sa MEDCouplingMesh::buildUnstructured
160  */
161 MEDCouplingCMesh *MEDCouplingIMesh::convertToCartesian() const
162 {
163   checkCoherency();
164   MEDCouplingAutoRefCountObjectPtr<MEDCouplingCMesh> ret(MEDCouplingCMesh::New());
165   try
166   { ret->copyTinyInfoFrom(this); }
167   catch(INTERP_KERNEL::Exception& e) { }
168   int spaceDim(getSpaceDimension());
169   std::vector<std::string> infos(buildInfoOnComponents());
170   for(int i=0;i<spaceDim;i++)
171     {
172       MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr(DataArrayDouble::New()); arr->alloc(_structure[i],1); arr->setInfoOnComponent(0,infos[i]);
173       arr->iota(); arr->applyLin(_dxyz[i],_origin[i]);
174       ret->setCoordsAt(i,arr);
175     }
176   return ret.retn();
177 }
178
179 void MEDCouplingIMesh::setSpaceDimension(int spaceDim)
180 {
181   if(spaceDim==_space_dim)
182     return ;
183   CheckSpaceDimension(spaceDim);
184   _space_dim=spaceDim;
185   declareAsNew();
186 }
187
188 void MEDCouplingIMesh::updateTime() const
189 {
190 }
191
192 std::size_t MEDCouplingIMesh::getHeapMemorySizeWithoutChildren() const
193 {
194   return MEDCouplingStructuredMesh::getHeapMemorySizeWithoutChildren();
195 }
196
197 std::vector<const BigMemoryObject *> MEDCouplingIMesh::getDirectChildren() const
198 {
199   return std::vector<const BigMemoryObject *>();
200 }
201
202 /*!
203  * This method copyies all tiny strings from other (name and components name).
204  * @throw if other and this have not same mesh type.
205  */
206 void MEDCouplingIMesh::copyTinyStringsFrom(const MEDCouplingMesh *other)
207
208   const MEDCouplingIMesh *otherC=dynamic_cast<const MEDCouplingIMesh *>(other);
209   if(!otherC)
210     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::copyTinyStringsFrom : meshes have not same type !");
211   MEDCouplingStructuredMesh::copyTinyStringsFrom(other);
212   declareAsNew();
213 }
214
215 bool MEDCouplingIMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
216 {
217   if(!other)
218     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::isEqualIfNotWhy : input other pointer is null !");
219   const MEDCouplingIMesh *otherC(dynamic_cast<const MEDCouplingIMesh *>(other));
220   if(!otherC)
221     {
222       reason="mesh given in input is not castable in MEDCouplingIMesh !";
223       return false;
224     }
225   if(!MEDCouplingStructuredMesh::isEqualIfNotWhy(other,prec,reason))
226     return false;
227   if(!isEqualWithoutConsideringStrInternal(otherC,prec,reason))
228     return false;
229   if(_axis_unit!=otherC->_axis_unit)
230     {
231       reason="The units of axis are not the same !";
232       return false;
233     }
234   return true;
235 }
236
237 bool MEDCouplingIMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
238 {
239   const MEDCouplingIMesh *otherC=dynamic_cast<const MEDCouplingIMesh *>(other);
240   if(!otherC)
241     return false;
242   std::string tmp;
243   return isEqualWithoutConsideringStrInternal(other,prec,tmp);
244 }
245
246 bool MEDCouplingIMesh::isEqualWithoutConsideringStrInternal(const MEDCouplingMesh *other, double prec, std::string& reason) const
247 {
248   const MEDCouplingIMesh *otherC=dynamic_cast<const MEDCouplingIMesh *>(other);
249   if(!otherC)
250     return false;
251   if(_space_dim!=otherC->_space_dim)
252     {
253       std::ostringstream oss;
254       oss << "The spaceDimension of this (" << _space_dim << ") is not equal to those of other (" << otherC->_space_dim << ") !";
255       return false;
256     }
257   checkSpaceDimension();
258   for(int i=0;i<_space_dim;i++)
259     {
260       if(fabs(_origin[i]-otherC->_origin[i])>prec)
261         {
262           std::ostringstream oss;
263           oss << "The origin of this and other differs at " << i << " !";
264           reason=oss.str();
265           return false;
266         }
267     }
268   for(int i=0;i<_space_dim;i++)
269     {
270       if(fabs(_dxyz[i]-otherC->_dxyz[i])>prec)
271         {
272           std::ostringstream oss;
273           oss << "The delta of this and other differs at " << i << " !";
274           reason=oss.str();
275           return false;
276         }
277     }
278   for(int i=0;i<_space_dim;i++)
279     {
280       if(_structure[i]!=otherC->_structure[i])
281         {
282           std::ostringstream oss;
283           oss << "The structure of this and other differs at " << i << " !";
284           reason=oss.str();
285           return false;
286         }
287     }
288   return true;
289 }
290
291 void MEDCouplingIMesh::checkDeepEquivalWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
292                                             DataArrayInt *&cellCor, DataArrayInt *&nodeCor) const
293 {
294   if(!isEqualWithoutConsideringStr(other,prec))
295     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::checkDeepEquivalWith : Meshes are not the same !");
296 }
297
298 /*!
299  * Nothing is done here (except to check that the other is a ParaMEDMEM::MEDCouplingIMesh instance too).
300  * The user intend that the nodes are the same, so by construction of ParaMEDMEM::MEDCouplingIMesh, \a this and \a other are the same !
301  */
302 void MEDCouplingIMesh::checkDeepEquivalOnSameNodesWith(const MEDCouplingMesh *other, int cellCompPol, double prec,
303                                                        DataArrayInt *&cellCor) const
304 {
305   if(!isEqualWithoutConsideringStr(other,prec))
306     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::checkDeepEquivalOnSameNodesWith : Meshes are not the same !");
307 }
308
309 void MEDCouplingIMesh::checkCoherency() const
310 {
311   checkSpaceDimension();
312   for(int i=0;i<_space_dim;i++)
313     if(_structure[i]<1)
314       {
315         std::ostringstream oss; oss << "MEDCouplingIMesh::checkCoherency : On axis " << i << "/" << _space_dim << ", number of nodes is equal to " << _structure[i] << " ! must be >=1 !";
316         throw INTERP_KERNEL::Exception(oss.str().c_str());
317       }
318 }
319
320 void MEDCouplingIMesh::checkCoherency1(double eps) const
321 {
322   checkCoherency();
323 }
324
325 void MEDCouplingIMesh::checkCoherency2(double eps) const
326 {
327   checkCoherency1(eps);
328 }
329
330 void MEDCouplingIMesh::getSplitCellValues(int *res) const
331 {
332   int meshDim(getMeshDimension());
333   for(int l=0;l<meshDim;l++)
334     {
335       int val=1;
336       for(int p=0;p<meshDim-l-1;p++)
337         val*=_structure[p]-1;
338       res[meshDim-l-1]=val;
339     }
340 }
341
342 void MEDCouplingIMesh::getSplitNodeValues(int *res) const
343 {
344   int spaceDim(getSpaceDimension());
345   for(int l=0;l<spaceDim;l++)
346     {
347       int val=1;
348       for(int p=0;p<spaceDim-l-1;p++)
349         val*=_structure[p];
350       res[spaceDim-l-1]=val;
351     }
352 }
353
354 void MEDCouplingIMesh::getNodeGridStructure(int *res) const
355 {
356   checkSpaceDimension();
357   std::copy(_structure,_structure+_space_dim,res);
358 }
359
360 std::vector<int> MEDCouplingIMesh::getNodeGridStructure() const
361 {
362   checkSpaceDimension();
363   std::vector<int> ret(_structure,_structure+_space_dim);
364   return ret;
365 }
366
367 MEDCouplingStructuredMesh *MEDCouplingIMesh::buildStructuredSubPart(const std::vector< std::pair<int,int> >& cellPart) const
368 {
369   checkCoherency();
370   int dim(getSpaceDimension());
371   if(dim!=(int)cellPart.size())
372     {
373       std::ostringstream oss; oss << "MEDCouplingIMesh::buildStructuredSubPart : the space dimension is " << dim << " and cell part size is " << cellPart.size() << " !";
374       throw INTERP_KERNEL::Exception(oss.str().c_str());
375     }
376   double retOrigin[3]={0.,0.,0.};
377   int retStruct[3]={0,0,0};
378   MEDCouplingAutoRefCountObjectPtr<MEDCouplingIMesh> ret(dynamic_cast<MEDCouplingIMesh *>(deepCpy()));
379   for(int i=0;i<dim;i++)
380     {
381       int startNode(cellPart[i].first),endNode(cellPart[i].second+1);
382       int myDelta(endNode-startNode);
383       if(startNode<0 || startNode>=_structure[i])
384         {
385           std::ostringstream oss; oss << "MEDCouplingIMesh::buildStructuredSubPart : At dimension #" << i << " the start node id is " << startNode << " it should be in [0," << _structure[i] << ") !";
386           throw INTERP_KERNEL::Exception(oss.str().c_str());
387         }
388       if(myDelta<0 || myDelta>_structure[i])
389         {
390           std::ostringstream oss; oss << "MEDCouplingIMesh::buildStructuredSubPart : Along dimension #" << i << " the number of nodes is " << _structure[i] << ", and you are requesting for " << myDelta << " nodes wide range !" << std::endl;
391           throw INTERP_KERNEL::Exception(oss.str().c_str());
392         }
393       retOrigin[i]=_origin[i]+startNode*_dxyz[i];
394       retStruct[i]=myDelta;
395     }
396   ret->setNodeStruct(retStruct,retStruct+dim);
397   ret->setOrigin(retOrigin,retOrigin+dim);
398   ret->checkCoherency();
399   return ret.retn();
400 }
401
402 /*!
403  * Return the space dimension of \a this.
404  */
405 int MEDCouplingIMesh::getSpaceDimension() const
406 {
407   return _space_dim;
408 }
409
410 void MEDCouplingIMesh::getCoordinatesOfNode(int nodeId, std::vector<double>& coo) const
411 {
412   int tmp[3];
413   int spaceDim(getSpaceDimension());
414   getSplitNodeValues(tmp);
415   int tmp2[3];
416   GetPosFromId(nodeId,spaceDim,tmp,tmp2);
417   for(int j=0;j<spaceDim;j++)
418     coo.push_back(_origin[j]+_dxyz[j]*tmp2[j]);
419 }
420
421 std::string MEDCouplingIMesh::simpleRepr() const
422 {
423   std::ostringstream ret;
424   ret << "Image grid with name : \"" << getName() << "\"\n";
425   ret << "Description of mesh : \"" << getDescription() << "\"\n";
426   int tmpp1,tmpp2;
427   double tt(getTime(tmpp1,tmpp2));
428   int spaceDim(_space_dim);
429   ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
430   ret << "Iteration : " << tmpp1  << " Order : " << tmpp2 << "\n";
431   ret << "Space dimension : " << spaceDim << "\n";
432   if(spaceDim<0 || spaceDim>3)
433     return ret.str();
434   ret << "The nodal structure is : "; std::copy(_structure,_structure+spaceDim,std::ostream_iterator<int>(ret," ")); ret << "\n";
435   ret << "The origin position is [" << _axis_unit << "]: ";
436   std::copy(_origin,_origin+spaceDim,std::ostream_iterator<double>(ret," ")); ret << "\n";
437   ret << "The intervals along axis are : ";
438   std::copy(_dxyz,_dxyz+spaceDim,std::ostream_iterator<double>(ret," ")); ret << "\n";
439   return ret.str();
440 }
441
442 std::string MEDCouplingIMesh::advancedRepr() const
443 {
444   return simpleRepr();
445 }
446
447 void MEDCouplingIMesh::getBoundingBox(double *bbox) const
448 {
449   checkCoherency();
450   int dim(getSpaceDimension());
451   for(int idim=0; idim<dim; idim++)
452     {
453       bbox[2*idim]=_origin[idim];
454       bbox[2*idim+1]=_origin[idim]+_dxyz[idim]*_structure[idim];
455     }
456 }
457
458 /*!
459  * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
460  * mesh.<br>
461  * For 1D cells, the returned field contains lengths.<br>
462  * For 2D cells, the returned field contains areas.<br>
463  * For 3D cells, the returned field contains volumes.
464  *  \param [in] isAbs - a not used parameter.
465  *  \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
466  *         and one time . The caller is to delete this field using decrRef() as it is no
467  *         more needed.
468  */
469 MEDCouplingFieldDouble *MEDCouplingIMesh::getMeasureField(bool isAbs) const
470 {
471   checkCoherency();
472   std::string name="MeasureOfMesh_";
473   name+=getName();
474   int nbelem(getNumberOfCells());
475   MEDCouplingFieldDouble *field(MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME));
476   field->setName(name);
477   DataArrayDouble* array(DataArrayDouble::New());
478   array->alloc(nbelem,1);
479   array->fillWithValue(getMeasureOfAnyCell());
480   field->setArray(array) ;
481   array->decrRef();
482   field->setMesh(const_cast<MEDCouplingIMesh *>(this));
483   field->synchronizeTimeWithMesh();
484   return field;
485 }
486
487 /*!
488  * not implemented yet !
489  */
490 MEDCouplingFieldDouble *MEDCouplingIMesh::getMeasureFieldOnNode(bool isAbs) const
491 {
492   throw INTERP_KERNEL::Exception("MEDCouplingIMesh::getMeasureFieldOnNode : not implemented yet !");
493   //return 0;
494 }
495
496 int MEDCouplingIMesh::getCellContainingPoint(const double *pos, double eps) const
497 {
498   int dim(getSpaceDimension()),ret(0),coeff(1);
499   for(int i=0;i<dim;i++)
500     {
501       int nbOfCells(_structure[i]-1);
502       double ref(pos[i]);
503       int tmp((ref-_origin[i])/_dxyz[i]);
504       if(tmp>=0 && tmp<nbOfCells)
505         {
506           ret+=coeff*tmp;
507           coeff*=nbOfCells;
508         }
509       else
510         return -1;
511     }
512   return ret;
513 }
514
515 void MEDCouplingIMesh::rotate(const double *center, const double *vector, double angle)
516 {
517   throw INTERP_KERNEL::Exception("No rotation available on IMesh : Traduce it to unstructured mesh to apply it !");
518 }
519
520 /*!
521  * Translates all nodes of \a this mesh by a given vector. Actually, it adds each
522  * component of the \a vector to all node coordinates of a corresponding axis.
523  *  \param [in] vector - the translation vector whose size must be not less than \a
524  *         this->getSpaceDimension().
525  */
526 void MEDCouplingIMesh::translate(const double *vector)
527 {
528   checkSpaceDimension();
529   int dim(getSpaceDimension());
530   std::transform(_origin,_origin+dim,vector,_origin,std::plus<double>());
531   declareAsNew();
532 }
533
534 /*!
535  * Applies scaling transformation to all nodes of \a this mesh.
536  *  \param [in] point - coordinates of a scaling center. This array is to be of
537  *         size \a this->getSpaceDimension() at least.
538  *  \param [in] factor - a scale factor.
539  */
540 void MEDCouplingIMesh::scale(const double *point, double factor)
541 {
542   checkSpaceDimension();
543   int dim(getSpaceDimension());
544   std::transform(_origin,_origin+dim,point,_origin,std::minus<double>());
545   std::transform(_origin,_origin+dim,_origin,std::bind2nd(std::multiplies<double>(),factor));
546   std::transform(_dxyz,_dxyz+dim,_dxyz,std::bind2nd(std::multiplies<double>(),factor));
547   std::transform(_origin,_origin+dim,point,_origin,std::plus<double>());
548   declareAsNew();
549 }
550
551 MEDCouplingMesh *MEDCouplingIMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
552 {
553   //not implemented yet !
554   return 0;
555 }
556
557 /*!
558  * Returns a new DataArrayDouble holding coordinates of all nodes of \a this mesh.
559  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
560  *          this->getNumberOfNodes() tuples per \a this->getSpaceDimension()
561  *          components. The caller is to delete this array using decrRef() as it is
562  *          no more needed.
563  */
564 DataArrayDouble *MEDCouplingIMesh::getCoordinatesAndOwner() const
565 {
566   checkCoherency();
567   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
568   int spaceDim(getSpaceDimension()),nbNodes(getNumberOfNodes());
569   ret->alloc(nbNodes,spaceDim);
570   double *pt(ret->getPointer());
571   ret->setInfoOnComponents(buildInfoOnComponents());
572   int tmp2[3],tmp[3];
573   getSplitNodeValues(tmp);
574   for(int i=0;i<nbNodes;i++)
575     {
576       GetPosFromId(i,spaceDim,tmp,tmp2);
577       for(int j=0;j<spaceDim;j++)
578         pt[i*spaceDim+j]=_dxyz[j]*tmp2[j]+_origin[j];
579     }
580   return ret.retn();
581 }
582
583 /*!
584  * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
585  * computed by averaging coordinates of cell nodes.
586  *  \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
587  *          this->getNumberOfCells() tuples per \a this->getSpaceDimension()
588  *          components. The caller is to delete this array using decrRef() as it is
589  *          no more needed.
590  */
591 DataArrayDouble *MEDCouplingIMesh::getBarycenterAndOwner() const
592 {
593   checkCoherency();
594   MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
595   int spaceDim(getSpaceDimension()),nbCells(getNumberOfCells()),tmp[3],tmp2[3];
596   ret->alloc(nbCells,spaceDim);
597   double *pt(ret->getPointer()),shiftOrigin[3];
598   std::transform(_dxyz,_dxyz+spaceDim,shiftOrigin,std::bind2nd(std::multiplies<double>(),0.5));
599   std::transform(_origin,_origin+spaceDim,shiftOrigin,shiftOrigin,std::plus<double>());
600   getSplitCellValues(tmp);
601   ret->setInfoOnComponents(buildInfoOnComponents());
602   for(int i=0;i<nbCells;i++)
603     {
604       GetPosFromId(i,spaceDim,tmp,tmp2);
605       for(int j=0;j<spaceDim;j++)
606         pt[i*spaceDim+j]=_dxyz[j]*tmp2[j]+shiftOrigin[j];
607     }
608   return ret.retn();
609 }
610
611 DataArrayDouble *MEDCouplingIMesh::computeIsoBarycenterOfNodesPerCell() const
612 {
613   return MEDCouplingIMesh::getBarycenterAndOwner();
614 }
615
616 void MEDCouplingIMesh::renumberCells(const int *old2NewBg, bool check)
617 {
618   throw INTERP_KERNEL::Exception("Functionnality of renumbering cell not available for IMesh !");
619 }
620
621 void MEDCouplingIMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
622 {
623   int it,order;
624   double time(getTime(it,order));
625   tinyInfo.clear();
626   tinyInfoD.clear();
627   littleStrings.clear();
628   littleStrings.push_back(getName());
629   littleStrings.push_back(getDescription());
630   littleStrings.push_back(getTimeUnit());
631   littleStrings.push_back(getAxisUnit());
632   tinyInfo.push_back(it);
633   tinyInfo.push_back(order);
634   tinyInfo.push_back(_space_dim);
635   tinyInfo.insert(tinyInfo.end(),_structure,_structure+3);
636   tinyInfoD.push_back(time);
637   tinyInfoD.insert(tinyInfoD.end(),_dxyz,_dxyz+3);
638   tinyInfoD.insert(tinyInfoD.end(),_origin,_origin+3);
639 }
640
641 void MEDCouplingIMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
642 {
643   a1->alloc(0,1);
644   a2->alloc(0,1);
645 }
646
647 void MEDCouplingIMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
648 {
649   a1=DataArrayInt::New();
650   a1->alloc(0,1);
651   a2=DataArrayDouble::New();
652   a2->alloc(0,1);
653 }
654
655 void MEDCouplingIMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2,
656                                        const std::vector<std::string>& littleStrings)
657 {
658   setName(littleStrings[0]);
659   setDescription(littleStrings[1]);
660   setTimeUnit(littleStrings[2]);
661   setAxisUnit(littleStrings[3]);
662   setTime(tinyInfoD[0],tinyInfo[0],tinyInfo[1]);
663   _space_dim=tinyInfo[2];
664   _structure[0]=tinyInfo[3]; _structure[1]=tinyInfo[4]; _structure[2]=tinyInfo[5];
665   _dxyz[0]=tinyInfoD[1]; _dxyz[1]=tinyInfoD[2]; _dxyz[2]=tinyInfoD[3];
666   _origin[0]=tinyInfoD[4]; _origin[1]=tinyInfoD[5]; _origin[2]=tinyInfoD[6];
667   declareAsNew();
668 }
669
670 void MEDCouplingIMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
671 {
672   checkCoherency();
673   std::ostringstream extent,origin,spacing;
674   for(int i=0;i<3;i++)
675     {
676       if(i<_space_dim)
677         { extent << "0 " <<  _structure[i]-1 << " "; origin << _origin[i] << " "; spacing << _dxyz[i] << " "; }
678       else
679         { extent << "0 0 "; origin << "0 "; spacing << "0 "; }
680     }
681   ofs << "  <" << getVTKDataSetType() << " WholeExtent=\"" << extent.str() << "\" Origin=\"" << origin.str() << "\" Spacing=\"" << spacing.str() << "\">\n";
682   ofs << "    <Piece Extent=\"" << extent.str() << "\">\n";
683   ofs << "      <PointData>\n" << pointData << std::endl;
684   ofs << "      </PointData>\n";
685   ofs << "      <CellData>\n" << cellData << std::endl;
686   ofs << "      </CellData>\n";
687   ofs << "      <Coordinates>\n";
688   ofs << "      </Coordinates>\n";
689   ofs << "    </Piece>\n";
690   ofs << "  </" << getVTKDataSetType() << ">\n";
691 }
692
693 void MEDCouplingIMesh::reprQuickOverview(std::ostream& stream) const
694 {
695   stream << "MEDCouplingIMesh C++ instance at " << this << ". Name : \"" << getName() << "\". Space dimension : " << _space_dim << ".";
696   if(_space_dim<0 || _space_dim>3)
697     return ;
698   stream << "\n";
699   std::ostringstream stream0,stream1;
700   int nbNodes(1),nbCells(0);
701   bool isPb(false);
702   for(int i=0;i<_space_dim;i++)
703     {
704       char tmp('X'+i);
705       int tmpNodes(_structure[i]);
706       stream1 << "- Axis " << tmp << " : " << tmpNodes << " nodes (orig=" << _origin[i] << ", inter=" << _dxyz[i] << ").";
707       if(i!=_space_dim-1)
708         stream1 << std::endl;
709       if(tmpNodes>=1)
710         nbNodes*=tmpNodes;
711       else
712         isPb=true;
713       if(tmpNodes>=2)
714         nbCells=nbCells==0?tmpNodes-1:nbCells*(tmpNodes-1);
715     }
716   if(!isPb)
717     {
718       stream0 << "Number of cells : " << nbCells << ", Number of nodes : " << nbNodes;
719       stream << stream0.str();
720       if(_space_dim>0)
721         stream << std::endl;
722     }
723   stream << stream1.str();
724 }
725
726 std::string MEDCouplingIMesh::getVTKDataSetType() const
727 {
728   return std::string("ImageData");
729 }
730
731 std::vector<std::string> MEDCouplingIMesh::buildInfoOnComponents() const
732 {
733   checkSpaceDimension();
734   int dim(getSpaceDimension());
735   std::vector<std::string> ret(dim);
736   for(int i=0;i<dim;i++)
737     {
738       std::ostringstream oss;
739       char tmp('X'+i); oss << tmp;
740       ret[i]=DataArray::BuildInfoFromVarAndUnit(oss.str(),_axis_unit);
741     }
742   return ret;
743 }
744
745 void MEDCouplingIMesh::checkSpaceDimension() const
746 {
747   CheckSpaceDimension(_space_dim);
748 }
749
750 void MEDCouplingIMesh::CheckSpaceDimension(int spaceDim)
751 {
752   if(spaceDim<0 || spaceDim>3)
753     throw INTERP_KERNEL::Exception("MEDCouplingIMesh::CheckSpaceDimension : input spaceDim must be in [0,1,2,3] !");
754 }
755