Salome HOME
[EDF21149] : Improvements for // spliter
[tools/medcoupling.git] / src / MEDCoupling / MEDCouplingSkyLineArray.cxx
1 // Copyright (C) 2007-2020  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
20 #include "MEDCouplingSkyLineArray.hxx"
21
22 #include <sstream>
23 #include <deque>
24 #include <set>
25
26 using namespace MEDCoupling;
27
28 MEDCouplingSkyLineArray::MEDCouplingSkyLineArray():
29   _super_index( DataArrayIdType::New() ), _index( DataArrayIdType::New() ), _values( DataArrayIdType::New() )
30 {
31 }
32
33 MEDCouplingSkyLineArray::~MEDCouplingSkyLineArray()
34 {
35 }
36
37 MEDCouplingSkyLineArray* MEDCouplingSkyLineArray::New()
38 {
39   return new MEDCouplingSkyLineArray();
40 }
41
42 MEDCouplingSkyLineArray* MEDCouplingSkyLineArray::New( const std::vector<mcIdType>& index,
43                                                        const std::vector<mcIdType>& value )
44 {
45   MEDCouplingSkyLineArray * ret = new MEDCouplingSkyLineArray();
46   ret->_index->reserve( index.size() );
47   ret->_index->insertAtTheEnd( index.begin(), index.end() );
48   ret->_values->reserve( value.size() );
49   ret->_values->insertAtTheEnd( value.begin(), value.end() );
50   return ret;
51 }
52
53 MEDCouplingSkyLineArray* MEDCouplingSkyLineArray::New( DataArrayIdType* index, DataArrayIdType* value )
54 {
55   MEDCouplingSkyLineArray* ret = new MEDCouplingSkyLineArray();
56   ret->set(index, value);
57   return ret;
58 }
59
60 MEDCouplingSkyLineArray* MEDCouplingSkyLineArray::New( const MEDCouplingSkyLineArray & other )
61 {
62   MEDCouplingSkyLineArray* ret = new MEDCouplingSkyLineArray();
63   ret->_super_index = other._super_index;
64   ret->_index = other._index;
65   ret->_values = other._values;
66   return ret;
67 }
68
69 /**! Build a three level SkyLine array from the dynamic connectivity of a dynamic mesh (i.e. containing only
70  * polyhedrons or polygons).
71  * The input arrays are deep copied, contrary to the other ctors.
72  */
73 MEDCouplingSkyLineArray * MEDCouplingSkyLineArray::BuildFromPolyhedronConn( const DataArrayIdType* c, const DataArrayIdType* cI )
74 {
75   using namespace std;
76
77   MEDCouplingSkyLineArray* ret = new MEDCouplingSkyLineArray();
78
79   const mcIdType * cP(c->begin()), * cIP(cI->begin());
80   mcIdType prev = -1;
81   if (c->getNbOfElems() != *(cI->end()-1))
82     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::BuildFromDynamicConn: misformatted connectivity (wrong nb of tuples)!");
83   for (mcIdType i=0; i < cI->getNbOfElems(); i++)
84     {
85       mcIdType j = cIP[i];
86       if (cIP[i] < prev)
87         throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::BuildFromDynamicConn: misformatted connectivity (indices not monotonic ascending)!");
88       prev = cIP[i];
89       if (i!=cI->getNbOfElems()-1)
90         if (cP[j] != INTERP_KERNEL::NORM_POLYHED)
91           throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::BuildFromDynamicConn: connectivity containing other types than POLYHED!");
92     }
93
94   vector<mcIdType> superIdx, idx, vals;
95   mcIdType cnt = 0, cnt2 = 0;
96   superIdx.reserve(cI->getNbOfElems());
97   superIdx.push_back(0);
98   idx.push_back(0);
99   vals.resize(c->getNbOfElems()); // too much because of the type and the -1, but still better than push_back().
100   for (mcIdType i=0; i < cI->getNbOfElems()-1; i++)
101     {
102       mcIdType start = cIP[i]+1, end = cIP[i+1];
103       mcIdType * work = vals.data() + cnt;
104       const mcIdType * w = cP+start;
105       const mcIdType * w2 = find(w, cP+end, -1);
106       while (w2 != cP+end)
107         {
108           copy(w, w2, work);
109           mcIdType d = ToIdType(distance(w, w2));
110           cnt += d; work +=d;
111           idx.push_back(cnt); cnt2++;
112           w = w2+1;  // skip the -1
113           w2 = find(w, cP+end, -1);
114         }
115       copy(w, cP+end, work);
116       cnt += ToIdType(distance(w, cP+end));
117       idx.push_back(cnt); cnt2++;
118       superIdx.push_back(cnt2);
119     }
120   ret->_super_index->alloc(superIdx.size(),1);
121   copy(superIdx.begin(), superIdx.end(), ret->_super_index->getPointer());
122   ret->_index->alloc(idx.size(),1);
123   copy(idx.begin(), idx.end(), ret->_index->getPointer());
124   ret->_values->alloc(cnt,1);
125   copy(vals.begin(), vals.begin()+cnt, ret->_values->getPointer());
126
127   return ret;
128 }
129
130 /**
131  * Convert a three-level SkyLineArray into a polyhedral connectivity.
132  * The super-packs are interpreted as cell description, and the packs represent the face connectivity.
133  */
134 void MEDCouplingSkyLineArray::convertToPolyhedronConn( MCAuto<DataArrayIdType>& c,  MCAuto<DataArrayIdType>& cI) const
135 {
136   // TODO: in this case an iterator would be nice
137   using namespace std;
138
139   checkSuperIndex("convertToPolyhedronConn");
140
141   const mcIdType * siP(_super_index->begin()), * iP(_index->begin()), *vP(_values->begin());
142   mcIdType cnt = 0;
143   cI->alloc(_super_index->getNbOfElems(),1);  // same number of super packs as number of cells
144   mcIdType * cIVecP(cI->getPointer());
145   MCAuto <DataArrayIdType> dsi = _index->deltaShiftIndex();
146   mcIdType sz = dsi->accumulate((std::size_t)0) + ToIdType(dsi->getNbOfElems());  // think about it: one slot for the type, -1 at the end of each face of the cell
147   c->alloc(sz, 1);
148   mcIdType * cVecP(c->getPointer());
149
150   for ( mcIdType i=0; i < _super_index->getNbOfElems()-1; i++)
151      {
152        cIVecP[i]= cnt;
153        mcIdType endId = siP[i+1];
154        cVecP[cnt++] = INTERP_KERNEL::NORM_POLYHED;
155        for (mcIdType j=siP[i]; j < endId; j++)
156          {
157            mcIdType startId2 = iP[j], endId2 = iP[j+1];
158            copy(vP+startId2, vP+endId2, cVecP+cnt);
159            cnt += endId2-startId2;
160            if(j != endId-1)
161              cVecP[cnt++] = -1;
162          }
163      }
164   cIVecP[_super_index->getNbOfElems()-1] = cnt;
165 }
166
167 std::size_t MEDCouplingSkyLineArray::getHeapMemorySizeWithoutChildren() const
168 {
169   return _index->getHeapMemorySizeWithoutChildren()+_values->getHeapMemorySizeWithoutChildren()+_super_index->getHeapMemorySizeWithoutChildren();
170 }
171
172 std::vector<const BigMemoryObject *> MEDCouplingSkyLineArray::getDirectChildrenWithNull() const
173 {
174   std::vector<const BigMemoryObject *> ret;
175   ret.push_back(_super_index);
176   ret.push_back(_index);
177   ret.push_back(_values);
178   return ret;
179 }
180
181
182 void MEDCouplingSkyLineArray::set( DataArrayIdType* index, DataArrayIdType* value )
183 {
184   _index=index;
185   _values=value;
186   if ( (DataArrayIdType*)_index ) _index->incrRef();
187   else                            _index = DataArrayIdType::New();
188   if ( (DataArrayIdType*)_values ) _values->incrRef();
189   else                             _values = DataArrayIdType::New();
190 }
191
192 void MEDCouplingSkyLineArray::set3( DataArrayIdType* superIndex, DataArrayIdType* index, DataArrayIdType* value )
193 {
194   _super_index=superIndex;
195   if ( (DataArrayIdType*)_super_index ) _super_index->incrRef();
196   else                                  _super_index = DataArrayIdType::New();
197   set(index, value);
198 }
199
200 DataArrayIdType* MEDCouplingSkyLineArray::getSuperIndexArray() const
201 {
202   return const_cast<MEDCouplingSkyLineArray*>(this)->_super_index;
203 }
204
205
206 DataArrayIdType* MEDCouplingSkyLineArray::getIndexArray() const
207 {
208   return const_cast<MEDCouplingSkyLineArray*>(this)->_index;
209 }
210
211 DataArrayIdType* MEDCouplingSkyLineArray::getValuesArray() const
212 {
213   return const_cast<MEDCouplingSkyLineArray*>(this)->_values;
214 }
215
216 void MEDCouplingSkyLineArray::checkSuperIndex(const std::string& func) const
217 {
218   if (!_super_index->getNbOfElems())
219     {
220       std::ostringstream oss;
221       oss << "MEDCouplingSkyLineArray::"<< func << ": not a three level SkyLineArray! Method is not available for two-level SkyLineArray.";
222       throw INTERP_KERNEL::Exception(oss.str());
223     }
224 }
225
226 void MEDCouplingSkyLineArray::validSuperIndex(const std::string& func, mcIdType superIndex) const
227 {
228   if(superIndex < 0 || superIndex >= _super_index->getNbOfElems())
229     {
230       std::ostringstream oss;
231       oss << "MEDCouplingSkyLineArray::" << func <<  ": invalid super index!";
232       throw INTERP_KERNEL::Exception(oss.str());
233     }
234 }
235
236 void MEDCouplingSkyLineArray::validIndex(const std::string& func, mcIdType idx) const
237 {
238   if(idx < 0 || idx >= _index->getNbOfElems())
239     {
240       std::ostringstream oss;
241       oss << "MEDCouplingSkyLineArray::" << func <<  ": invalid index!";
242       throw INTERP_KERNEL::Exception(oss.str());
243     }
244 }
245
246 void MEDCouplingSkyLineArray::validSuperIndexAndIndex(const std::string& func, mcIdType superIndex, mcIdType index) const
247 {
248   validSuperIndex(func, superIndex);
249   mcIdType idx = _super_index->begin()[superIndex] + index;
250   if(idx < 0 || idx >= _index->getNbOfElems())
251     {
252       std::ostringstream oss;
253       oss << "MEDCouplingSkyLineArray::" << func <<  ": invalid index!";
254       throw INTERP_KERNEL::Exception(oss.str());
255     }
256 }
257
258 std::string MEDCouplingSkyLineArray::simpleRepr() const
259 {
260   std::ostringstream oss;
261   oss << "MEDCouplingSkyLineArray (" << this << ")" << std::endl;
262   MCAuto<DataArrayIdType> super_index = _super_index->deepCopy();
263   if (_super_index->getNbOfElems())
264     oss << "   Nb of super-packs: " << getSuperNumberOf() << std::endl;
265   else
266     {
267       super_index->alloc(2,1);
268       super_index->setIJSilent(0,0,0);
269       super_index->setIJSilent(1,0,_index->getNbOfElems()-1);
270     }
271   oss << "   Nb of packs: " << getNumberOf() << std::endl;
272   oss << "   Nb of values: " << getLength() << std::endl;
273
274   if (_super_index->getNbOfElems())
275     {
276       oss << "   Super-indices:" << std::endl;
277       oss << "   ";
278       const mcIdType * i = _super_index->begin();
279       for ( ; i != _super_index->end(); ++i )
280         oss << *i << " ";
281       oss << std::endl;
282     }
283
284   oss << "   Indices:" << std::endl;
285   oss << "   ";
286   const mcIdType * i = _index->begin();
287   for ( ; i != _index->end(); ++i )
288     oss << *i << " ";
289   oss << std::endl;
290   oss << "   Values:" << std::endl;
291   oss << "     ";
292   const mcIdType * v = _values->begin();
293   mcIdType cnt = 0, cntI = 0;
294   i = _index->begin();
295   for ( const mcIdType * si = super_index->begin()+1; v != _values->end(); ++v, ++cnt )
296     {
297       if ( cnt == *i )
298         {
299           if ( cntI == *si && cnt != 0)
300             {
301               oss << std::endl << "     ";
302               ++si;
303             }
304
305           oss << "| ";
306           ++i; ++cntI;
307         }
308       oss << *v << " ";
309     }
310   oss << std::endl;
311
312   return oss.str();
313 }
314
315 MEDCouplingSkyLineArray *MEDCouplingSkyLineArray::groupPacks(const DataArrayIdType *indexedPacks) const
316 {
317   indexedPacks->checkAllocated();
318   if( indexedPacks->getNumberOfComponents() != 1 )
319     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::groupPacks : number of components must be 1 !");
320   std::size_t nbTuples(indexedPacks->getNumberOfTuples());
321   if( nbTuples == 0 )
322     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::groupPacks : number of tuples must be > 0 !");
323   const DataArrayIdType *index(this->getIndexArray());
324   MCAuto<DataArrayIdType> partIndex(index->selectByTupleIdSafe(indexedPacks->begin(),indexedPacks->end()));
325   MCAuto<MEDCouplingSkyLineArray> ret(MEDCouplingSkyLineArray::New(partIndex,this->getValuesArray()));
326   return ret.retn();
327 }
328
329 MEDCouplingSkyLineArray *MEDCouplingSkyLineArray::uniqueNotSortedByPack() const
330 {
331   mcIdType nbPacks(this->getNumberOf());
332   MCAuto<DataArrayIdType> retIndex(DataArrayIdType::New()); retIndex->alloc(nbPacks+1,1);
333   const mcIdType *valuesPtr(this->_values->begin()),*indexPtr(this->_index->begin());
334   mcIdType *retIndexPtr(retIndex->getPointer()); *retIndexPtr = 0;
335   for(mcIdType i = 0 ; i < nbPacks ; ++i, ++retIndexPtr)
336   {
337     std::set<mcIdType> s(valuesPtr+indexPtr[i],valuesPtr+indexPtr[i+1]);
338     retIndexPtr[1] = retIndexPtr[0] + ToIdType(s.size());
339   }
340   MCAuto<DataArrayIdType> retValues(DataArrayIdType::New()); retValues->alloc(retIndex->back(),1);
341   mcIdType *retValuesPtr(retValues->getPointer());
342   for(mcIdType i = 0 ; i < nbPacks ; ++i)
343   {
344     std::set<mcIdType> s(valuesPtr+indexPtr[i],valuesPtr+indexPtr[i+1]);
345     retValuesPtr = std::copy(s.begin(),s.end(),retValuesPtr);
346   }
347   MCAuto<MEDCouplingSkyLineArray> ret(MEDCouplingSkyLineArray::New(retIndex,retValues));
348   return ret.retn();
349 }
350
351 /**
352  * For a 2- or 3-level SkyLine array, return a copy of the absolute pack with given identifier.
353  */
354 void MEDCouplingSkyLineArray::getSimplePackSafe(const mcIdType absolutePackId, std::vector<mcIdType> & pack) const
355 {
356   if(absolutePackId < 0 || absolutePackId >= _index->getNbOfElems())
357     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::getPackSafe: invalid index!");
358   const mcIdType * iP(_index->begin()), *vP(_values->begin());
359   mcIdType sz = iP[absolutePackId+1]-iP[absolutePackId];
360   pack.resize(sz);
361   std::copy(vP+iP[absolutePackId], vP+iP[absolutePackId+1],pack.begin());
362 }
363
364 /**
365  * Same as getPackSafe, but directly returns a pointer to the internal data with the size of the pack.
366  */
367 const mcIdType * MEDCouplingSkyLineArray::getSimplePackSafePtr(const mcIdType absolutePackId, mcIdType & packSize) const
368 {
369   if(absolutePackId < 0 || absolutePackId >= _index->getNbOfElems())
370     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::getPackSafe: invalid index!");
371   const mcIdType * iP(_index->begin()), *vP(_values->begin());
372   packSize = iP[absolutePackId+1]-iP[absolutePackId];
373   return vP+iP[absolutePackId];
374 }
375
376
377 /**!
378  * For each given super-pack ID, provide the sub-index of the first matching pack. If no matching pack is found for the
379  * given super-pack -1 is returned.
380  * \param[in] superPackIndices the list of super-packs that should be inspected
381  * \param[in] packBg the pack that the function is looking for in each of the provided super-pack
382  * \param[in] packEnd the pack that the function is looking for in each of the provided super-pack
383  * \param[out] a vector of mcIdType, having the same size as superPackIndices and containing for each inspected super-pack
384  * the index of the first matching pack, or -1 if none found.
385  */
386 void MEDCouplingSkyLineArray::findPackIds(const std::vector<mcIdType> & superPackIndices,
387                                           const mcIdType *packBg, const mcIdType *packEnd,
388                                           std::vector<mcIdType>& out) const
389 {
390   using namespace std;
391
392   checkSuperIndex("findPackIds");
393
394   mcIdType packSz = ToIdType(std::distance(packBg, packEnd));
395   if (!packSz)
396     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::findPackIds: void pack!");
397
398   out.resize(superPackIndices.size());
399   mcIdType i = 0;
400   const mcIdType * siP(_super_index->begin()), * iP(_index->begin()), *vP(_values->begin());
401   for(vector<mcIdType>::const_iterator it=superPackIndices.begin(); it!=superPackIndices.end(); ++it, i++)
402     {
403       out[i] = -1;
404       const mcIdType sPackIdx = *it;
405       // for each pack
406       for (mcIdType idx=siP[sPackIdx], j=0; idx < siP[sPackIdx+1]; idx++, j++)
407         {
408           if (packSz == (iP[idx+1] - iP[idx]))
409             if (equal(&vP[iP[idx]], &vP[iP[idx+1]], packBg))
410               {
411                 out[i] = j;
412                 break;
413               }
414         }
415     }
416 }
417
418 /**!
419  * Delete pack number 'idx' in super-pack number 'superIdx'.
420  * \param[in] superIdx is the super-pack number
421  * \param[in] idx is the pack index inside the super-pack 'superIdx'.
422  */
423 void MEDCouplingSkyLineArray::deletePack(const mcIdType superIdx, const mcIdType idx)
424 {
425   checkSuperIndex("deletePack");
426   validSuperIndexAndIndex("deletePack", superIdx, idx);
427
428   mcIdType * vP = _values->getPointer();
429   mcIdType * siP(_super_index->getPointer()), *iP(_index->getPointer());
430   const mcIdType start = iP[siP[superIdx]+idx], end = iP[siP[superIdx]+idx+1];
431   // _values
432   std::copy(vP+end, vP+_values->getNbOfElems(), vP+start);
433   _values->reAlloc(_values->getNbOfElems() - (end-start));
434
435   // _index
436   mcIdType nt = _index->getNbOfElems();
437   std::copy(iP+siP[superIdx]+idx+1, iP+nt, iP+siP[superIdx]+idx);
438   _index->reAlloc(nt-1); iP = _index->getPointer();  // better not forget this ...
439   for(mcIdType ii = siP[superIdx]+idx; ii < nt-1; ii++)
440     iP[ii] -= (end-start);
441
442   // _super_index
443   for(mcIdType ii = superIdx+1; ii < _super_index->getNbOfElems(); ii++)
444     (siP[ii])--;
445 }
446
447 void MEDCouplingSkyLineArray::deleteSimplePack(const mcIdType idx)
448 {
449   validIndex("deleteSimplePack", idx);
450   
451   mcIdType* iP(_index->getPointer());
452   const mcIdType start(iP[idx]), end(iP[idx+1]);
453
454   // _values
455   mcIdType initValSz=_values->getNbOfElems();
456   mcIdType deltaSz( start-end );  // should be negative
457   mcIdType *vP(_values->getPointer());
458   if (deltaSz < 0)
459     {
460       std::copy(vP+end, vP+initValSz, vP+start);
461       _values->reAlloc(initValSz+deltaSz);
462     }
463   else
464     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::deleteSimplePack");
465   // _index
466   mcIdType nt=_index->getNbOfElems();
467   std::copy(iP+idx+1, iP+nt, iP+idx);
468   for(mcIdType ii = idx; ii < nt-1; ii++)
469     iP[ii] += deltaSz;
470   _index->reAlloc(nt-1);
471 }
472
473 void MEDCouplingSkyLineArray::replaceSimplePacks(const DataArrayIdType* idx, const std::vector<const DataArrayIdType*>& packs)
474 {    
475   if (idx->empty())
476     return;
477     
478   for (const mcIdType * id = idx->begin(); id != idx->end(); id++)
479     validIndex("deleteSimplePacks", *id);
480     
481   if (idx->getNbOfElems() != ToIdType( packs.size()))
482     throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::deleteSimplePacks: size of list of pack is incorrect");
483     
484   // copy _index, _values into a deque<set<mcIdType>>
485   std::deque< std::set<mcIdType> > valuesByIdx;
486   mcIdType* vP(_values->getPointer());
487   mcIdType* iP(_index->getPointer());
488   mcIdType nt = _index->getNbOfElems();
489   for (mcIdType ii = 0; ii < nt-1; ii++)
490     valuesByIdx.push_back(std::set<mcIdType>(vP+iP[ii], vP+iP[ii+1]));
491     
492   // modify the deque<set<mcIdType>> according to idx and packs
493   mcIdType ii(0);
494   for (const mcIdType *id = idx->begin(); id != idx->end(); id++)
495     {
496       valuesByIdx[*id] = std::set<mcIdType>(packs[ii]->begin(), packs[ii]->end());
497       ii++;
498     }
499   // copy back the deque<set<mcIdType>> into _index, _values
500   mcIdType valSz(0);
501   *iP = 0;
502   for (std::deque< std::set<mcIdType> >::const_iterator values=valuesByIdx.begin();values!=valuesByIdx.end();values++)
503     {
504       valSz += ToIdType((*values).size());
505       *(++iP) = valSz;
506     }
507   _values->reAlloc(valSz);
508   iP = _index->getPointer();
509   vP = _values->getPointer();
510   for (auto values : valuesByIdx)
511     {
512       std::copy(values.begin(), values.end(), vP+(*iP));
513       iP++;
514     }
515 }
516
517 void MEDCouplingSkyLineArray::deleteSimplePacks(const DataArrayIdType* idx)
518 {    
519   for (auto id = idx->begin(); id != idx->end(); id++)
520     validIndex("deleteSimplePacks", *id);
521   
522   std::set<mcIdType> packsToDelete(idx->begin(), idx->end());
523     
524   // _values
525   mcIdType* iP(_index->getPointer());
526   mcIdType initValSz = _values->getNbOfElems();
527   mcIdType *vP(_values->getPointer());
528   mcIdType end_prec(0),start_prec(0);
529   for(std::set<mcIdType>::const_iterator ii=packsToDelete.begin();ii!=packsToDelete.end();ii++)
530     {
531       mcIdType start = iP[*ii];
532       if (end_prec != 0)
533         std::copy(vP+end_prec, vP+start, vP+start_prec);
534       start_prec += start-end_prec;
535       end_prec = iP[*ii+1];
536     }
537   if (end_prec != 0)
538     std::copy(vP+end_prec, vP+initValSz, vP+start_prec);
539   _values->reAlloc(initValSz-(end_prec-start_prec));
540     
541   // _index
542   mcIdType nt = _index->getNbOfElems();
543   mcIdType offset = 0;
544   end_prec = 0;
545   start_prec = 0;
546   mcIdType deleted = 0;
547   for(std::set<mcIdType>::const_iterator ii=packsToDelete.begin();ii!=packsToDelete.end();ii++)
548     {
549       if (end_prec != 0)
550         {
551           std::copy(iP+end_prec, iP+*ii, iP+start_prec);
552           for (mcIdType i=start_prec; i<*ii; i++)
553             iP[i] -= offset;
554         }
555       offset += iP[*ii+1] - iP[*ii];
556       start_prec = *ii-deleted;
557       end_prec = *ii+1;
558       deleted += 1;
559     }
560   if (end_prec != 0)
561     {
562       std::copy(iP+end_prec, iP+nt, iP+start_prec);
563       for (mcIdType i=start_prec; i<nt; i++)
564         iP[i] -= offset;
565     }
566   _index->reAlloc(nt-deleted);
567 }
568
569 /**!
570  * Insert a new pack in super-pack at index 'superIdx'. The pack is inserted at the end of the pack list of the chosen super-pack.
571  */
572 void MEDCouplingSkyLineArray::pushBackPack(const mcIdType superIdx, const mcIdType * packBg, const mcIdType * packEnd)
573 {
574   using namespace std;
575
576   checkSuperIndex("pushBackPack");
577   validSuperIndex("pushBackPack", superIdx);
578
579   mcIdType *siP(_super_index->getPointer()), *iP(_index->getPointer());
580   const mcIdType sz(ToIdType(distance(packBg, packEnd)));
581
582   // _values
583   _values->reAlloc(_values->getNbOfElems()+sz);
584   mcIdType * vPE(_values->getPointer()+_values->getNbOfElems());
585   mcIdType *vP(_values->getPointer());
586   copy(vP+iP[siP[superIdx+1]], vPE-sz, vP+iP[siP[superIdx+1]]+sz);
587   // insert pack
588   copy(packBg, packEnd, vP+iP[siP[superIdx+1]]);
589
590   // _index
591   mcIdType nt = ToIdType(_index->getNbOfElems());
592   _index->reAlloc(nt+1); iP = _index->getPointer();
593   copy(iP+siP[superIdx+1]+1, iP+nt, iP+siP[superIdx+1]+2);
594   iP[siP[superIdx+1]+1] = iP[siP[superIdx+1]] + sz;
595   for(mcIdType ii = siP[superIdx+1]+2; ii < nt+1; ii++)
596     iP[ii] += sz;
597
598   // _super_index
599   for(mcIdType ii = superIdx+1; ii < _super_index->getNbOfElems(); ii++)
600     (siP[ii])++;
601 }
602
603 /**
604  * Replace pack with absolute index 'idx' with the provided new pack. Function can be used either
605  * for 2-level SkyLine or 3-level SkyLine.
606  */
607 void MEDCouplingSkyLineArray::replaceSimplePack(const mcIdType idx, const mcIdType * packBg, const mcIdType * packEnd)
608 {
609   validIndex("replaceSimplePack", idx);
610
611   mcIdType * iP(_index->getPointer());
612   mcIdType newSz = ToIdType(std::distance(packBg, packEnd));
613   const mcIdType start = iP[idx], end = iP[idx+1];
614
615   // _values
616   mcIdType initValSz = _values->getNbOfElems();
617   mcIdType deltaSz = newSz-(end-start);  // can be negative
618   if (deltaSz)
619     {
620       if (deltaSz > 0)
621         _values->reAlloc(initValSz+deltaSz);
622       mcIdType *vP(_values->getPointer());
623       std::copy(vP+end, vP+initValSz, vP+end+deltaSz);
624       if (deltaSz < 0)
625         _values->reAlloc(initValSz+deltaSz);
626     }
627
628   // copy new pack
629   std::copy(packBg, packEnd, _values->getPointer()+start);
630
631   // _index
632   for(mcIdType ii = idx+1; ii < _index->getNbOfElems(); ii++)
633     iP[ii] += deltaSz;
634 }
635
636 /**
637  * Replace pack with super index 'superIdx' and index 'idx' with the provided new pack.
638  * Function can be used only for 3-level SkyLine.
639  */
640 void MEDCouplingSkyLineArray::replacePack(const mcIdType superIdx, const mcIdType idx, const mcIdType *packBg, const mcIdType *packEnd)
641 {
642   checkSuperIndex("replacePack");
643   validSuperIndexAndIndex("replacePack", superIdx, idx);
644
645   mcIdType * siP(_super_index->getPointer()), *iP(_index->getPointer());
646   mcIdType newSz = ToIdType(std::distance(packBg, packEnd));
647   const mcIdType start = iP[siP[superIdx]+idx], end = iP[siP[superIdx]+idx+1];
648
649   // _values
650   mcIdType initValSz = _values->getNbOfElems();
651   mcIdType deltaSz = newSz-(end-start);  // can be negative
652   if (deltaSz)
653     {
654       if (deltaSz > 0)
655         _values->reAlloc(initValSz+deltaSz);
656       mcIdType *vP(_values->getPointer());
657       std::copy(vP+end, vP+initValSz, vP+end+deltaSz);
658       if (deltaSz < 0)
659         _values->reAlloc(initValSz+deltaSz);
660     }
661
662   // copy new pack
663   std::copy(packBg, packEnd, _values->getPointer()+start);
664
665   // _index
666   for(mcIdType ii = siP[superIdx]+idx+1; ii < _index->getNbOfElems(); ii++)
667     iP[ii] += deltaSz;
668 }