1 // Copyright (C) 2007-2016 CEA/DEN, EDF R&D
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.
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.
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
17 // See http://www.salome-platform.org/ or email : webmaster.salome@opencascade.com
20 #include "MEDCouplingSkyLineArray.hxx"
26 using namespace MEDCoupling;
28 MEDCouplingSkyLineArray::MEDCouplingSkyLineArray():
29 _super_index( DataArrayInt::New() ), _index( DataArrayInt::New() ), _values( DataArrayInt::New() )
33 MEDCouplingSkyLineArray::~MEDCouplingSkyLineArray()
37 MEDCouplingSkyLineArray* MEDCouplingSkyLineArray::New()
39 return new MEDCouplingSkyLineArray();
42 MEDCouplingSkyLineArray* MEDCouplingSkyLineArray::New( const std::vector<int>& index,
43 const std::vector<int>& value )
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() );
53 MEDCouplingSkyLineArray* MEDCouplingSkyLineArray::New( DataArrayInt* index, DataArrayInt* value )
55 MEDCouplingSkyLineArray* ret = new MEDCouplingSkyLineArray();
56 ret->set(index, value);
60 MEDCouplingSkyLineArray* MEDCouplingSkyLineArray::New( const MEDCouplingSkyLineArray & other )
62 MEDCouplingSkyLineArray* ret = new MEDCouplingSkyLineArray();
63 ret->_super_index = other._super_index;
64 ret->_index = other._index;
65 ret->_values = other._values;
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.
73 MEDCouplingSkyLineArray * MEDCouplingSkyLineArray::BuildFromPolyhedronConn( const DataArrayInt* c, const DataArrayInt* cI )
77 MEDCouplingSkyLineArray* ret = new MEDCouplingSkyLineArray();
79 const int * cP(c->begin()), * cIP(cI->begin());
81 if ((int)c->getNbOfElems() != *(cI->end()-1))
82 throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::BuildFromDynamicConn: misformatted connectivity (wrong nb of tuples)!");
83 for (std::size_t i=0; i < cI->getNbOfElems(); i++)
87 throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::BuildFromDynamicConn: misformatted connectivity (indices not monotonic ascending)!");
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!");
94 vector<int> superIdx, idx, vals;
95 int cnt = 0, cnt2 = 0;
96 superIdx.reserve(cI->getNbOfElems());
97 superIdx.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 (std::size_t i=0; i < cI->getNbOfElems()-1; i++)
102 int start = cIP[i]+1, end = cIP[i+1];
103 int * work = vals.data() + cnt;
104 const int * w = cP+start;
105 const int * w2 = find(w, cP+end, -1);
109 int d = distance(w, w2);
111 idx.push_back(cnt); cnt2++;
112 w = w2+1; // skip the -1
113 w2 = find(w, cP+end, -1);
115 copy(w, cP+end, work);
116 cnt += distance(w, cP+end);
117 idx.push_back(cnt); cnt2++;
118 superIdx.push_back(cnt2);
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());
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.
134 void MEDCouplingSkyLineArray::convertToPolyhedronConn( MCAuto<DataArrayInt>& c, MCAuto<DataArrayInt>& cI) const
136 // TODO: in this case an iterator would be nice
139 checkSuperIndex("convertToPolyhedronConn");
141 const int * siP(_super_index->begin()), * iP(_index->begin()), *vP(_values->begin());
143 cI->alloc(_super_index->getNbOfElems(),1); // same number of super packs as number of cells
144 int * cIVecP(cI->getPointer());
145 MCAuto <DataArrayInt> dsi = _index->deltaShiftIndex();
146 int sz = dsi->accumulate(0) + dsi->getNbOfElems(); // think about it: one slot for the type, -1 at the end of each face of the cell
148 int * cVecP(c->getPointer());
150 for ( std::size_t i=0; i < _super_index->getNbOfElems()-1; i++)
153 int endId = siP[i+1];
154 cVecP[cnt++] = INTERP_KERNEL::NORM_POLYHED;
155 for (int j=siP[i]; j < endId; j++)
157 int startId2 = iP[j], endId2 = iP[j+1];
158 copy(vP+startId2, vP+endId2, cVecP+cnt);
159 cnt += endId2-startId2;
164 cIVecP[_super_index->getNbOfElems()-1] = cnt;
167 std::size_t MEDCouplingSkyLineArray::getHeapMemorySizeWithoutChildren() const
169 return _index->getHeapMemorySizeWithoutChildren()+_values->getHeapMemorySizeWithoutChildren()+_super_index->getHeapMemorySizeWithoutChildren();
172 std::vector<const BigMemoryObject *> MEDCouplingSkyLineArray::getDirectChildrenWithNull() const
174 std::vector<const BigMemoryObject *> ret;
175 ret.push_back(_super_index);
176 ret.push_back(_index);
177 ret.push_back(_values);
182 void MEDCouplingSkyLineArray::set( DataArrayInt* index, DataArrayInt* value )
186 if ( (DataArrayInt*)_index ) _index->incrRef();
187 else _index = DataArrayInt::New();
188 if ( (DataArrayInt*)_values ) _values->incrRef();
189 else _values = DataArrayInt::New();
192 void MEDCouplingSkyLineArray::set3( DataArrayInt* superIndex, DataArrayInt* index, DataArrayInt* value )
194 _super_index=superIndex;
195 if ( (DataArrayInt*)_super_index ) _super_index->incrRef();
196 else _super_index = DataArrayInt::New();
200 DataArrayInt* MEDCouplingSkyLineArray::getSuperIndexArray() const
202 return const_cast<MEDCouplingSkyLineArray*>(this)->_super_index;
206 DataArrayInt* MEDCouplingSkyLineArray::getIndexArray() const
208 return const_cast<MEDCouplingSkyLineArray*>(this)->_index;
211 DataArrayInt* MEDCouplingSkyLineArray::getValuesArray() const
213 return const_cast<MEDCouplingSkyLineArray*>(this)->_values;
216 void MEDCouplingSkyLineArray::checkSuperIndex(const std::string& func) const
218 if (!_super_index->getNbOfElems())
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());
226 void MEDCouplingSkyLineArray::validSuperIndex(const std::string& func, int superIndex) const
228 if(superIndex < 0 || superIndex >= (int)_super_index->getNbOfElems())
230 std::ostringstream oss;
231 oss << "MEDCouplingSkyLineArray::" << func << ": invalid super index!";
232 throw INTERP_KERNEL::Exception(oss.str());
236 void MEDCouplingSkyLineArray::validIndex(const std::string& func, int idx) const
238 if(idx < 0 || idx >= (int)_index->getNbOfElems())
240 std::ostringstream oss;
241 oss << "MEDCouplingSkyLineArray::" << func << ": invalid index!";
242 throw INTERP_KERNEL::Exception(oss.str());
246 void MEDCouplingSkyLineArray::validSuperIndexAndIndex(const std::string& func, int superIndex, int index) const
248 validSuperIndex(func, superIndex);
249 int idx = _super_index->begin()[superIndex] + index;
250 if(idx < 0 || idx >= (int)_index->getNbOfElems())
252 std::ostringstream oss;
253 oss << "MEDCouplingSkyLineArray::" << func << ": invalid index!";
254 throw INTERP_KERNEL::Exception(oss.str());
258 std::string MEDCouplingSkyLineArray::simpleRepr() const
260 std::ostringstream oss;
261 oss << "MEDCouplingSkyLineArray (" << this << ")" << std::endl;
262 MCAuto<DataArrayInt> super_index = _super_index->deepCopy();
263 if (_super_index->getNbOfElems())
264 oss << " Nb of super-packs: " << getSuperNumberOf() << std::endl;
267 super_index->alloc(2,1);
268 super_index->setIJSilent(0,0,0);
269 super_index->setIJSilent(1,0,_index->getNbOfElems()-1);
271 oss << " Nb of packs: " << getNumberOf() << std::endl;
272 oss << " Nb of values: " << getLength() << std::endl;
274 if (_super_index->getNbOfElems())
276 oss << " Super-indices:" << std::endl;
278 const int * i = _super_index->begin();
279 for ( ; i != _super_index->end(); ++i )
284 oss << " Indices:" << std::endl;
286 const int * i = _index->begin();
287 for ( ; i != _index->end(); ++i )
290 oss << " Values:" << std::endl;
292 const int * v = _values->begin();
293 int cnt = 0, cntI = 0;
295 for ( const int * si = super_index->begin()+1; v != _values->end(); ++v, ++cnt )
299 if ( cntI == *si && cnt != 0)
301 oss << std::endl << " ";
316 * For a 2- or 3-level SkyLine array, return a copy of the absolute pack with given identifier.
318 void MEDCouplingSkyLineArray::getSimplePackSafe(const int absolutePackId, std::vector<int> & pack) const
320 if(absolutePackId < 0 || absolutePackId >= (int)_index->getNbOfElems())
321 throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::getPackSafe: invalid index!");
322 const int * iP(_index->begin()), *vP(_values->begin());
323 int sz = iP[absolutePackId+1]-iP[absolutePackId];
325 std::copy(vP+iP[absolutePackId], vP+iP[absolutePackId+1],pack.begin());
329 * Same as getPackSafe, but directly returns a pointer to the internal data with the size of the pack.
331 const int * MEDCouplingSkyLineArray::getSimplePackSafePtr(const int absolutePackId, int & packSize) const
333 if(absolutePackId < 0 || absolutePackId >= (int)_index->getNbOfElems())
334 throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::getPackSafe: invalid index!");
335 const int * iP(_index->begin()), *vP(_values->begin());
336 packSize = iP[absolutePackId+1]-iP[absolutePackId];
337 return vP+iP[absolutePackId];
342 * For each given super-pack ID, provide the sub-index of the first matching pack. If no matching pack is found for the
343 * given super-pack -1 is returned.
344 * \param[in] superPackIndices the list of super-packs that should be inspected
345 * \param[in] packBg the pack that the function is looking for in each of the provided super-pack
346 * \param[in] packEnd the pack that the function is looking for in each of the provided super-pack
347 * \param[out] a vector of int, having the same size as superPackIndices and containing for each inspected super-pack
348 * the index of the first matching pack, or -1 if none found.
350 void MEDCouplingSkyLineArray::findPackIds(const std::vector<int> & superPackIndices,
351 const int *packBg, const int *packEnd,
352 std::vector<int>& out) const
356 checkSuperIndex("findPackIds");
358 int packSz = std::distance(packBg, packEnd);
360 throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::findPackIds: void pack!");
362 out.resize(superPackIndices.size());
364 const int * siP(_super_index->begin()), * iP(_index->begin()), *vP(_values->begin());
365 for(vector<int>::const_iterator it=superPackIndices.begin(); it!=superPackIndices.end(); ++it, i++)
368 const int sPackIdx = *it;
370 for (int idx=siP[sPackIdx], j=0; idx < siP[sPackIdx+1]; idx++, j++)
372 if (packSz == (iP[idx+1] - iP[idx]))
373 if (equal(&vP[iP[idx]], &vP[iP[idx+1]], packBg))
383 * Delete pack number 'idx' in super-pack number 'superIdx'.
384 * \param[in] superIdx is the super-pack number
385 * \param[in] idx is the pack index inside the super-pack 'superIdx'.
387 void MEDCouplingSkyLineArray::deletePack(const int superIdx, const int idx)
389 checkSuperIndex("deletePack");
390 validSuperIndexAndIndex("deletePack", superIdx, idx);
392 int * vP = _values->getPointer();
393 int * siP(_super_index->getPointer()), *iP(_index->getPointer());
394 const int start = iP[siP[superIdx]+idx], end = iP[siP[superIdx]+idx+1];
396 std::copy(vP+end, vP+_values->getNbOfElems(), vP+start);
397 _values->reAlloc(_values->getNbOfElems() - (end-start));
400 int nt = _index->getNbOfElems();
401 std::copy(iP+siP[superIdx]+idx+1, iP+nt, iP+siP[superIdx]+idx);
402 _index->reAlloc(nt-1); iP = _index->getPointer(); // better not forget this ...
403 for(int ii = siP[superIdx]+idx; ii < nt-1; ii++)
404 iP[ii] -= (end-start);
407 for(int ii = superIdx+1; ii < (int)_super_index->getNbOfElems(); ii++)
411 void MEDCouplingSkyLineArray::deleteSimplePack(const int idx)
413 validIndex("deleteSimplePack", idx);
415 int* iP(_index->getPointer());
416 const int start(iP[idx]), end(iP[idx+1]);
419 int initValSz( _values->getNbOfElems() );
420 int deltaSz( start-end ); // should be negative
421 int *vP(_values->getPointer());
424 std::copy(vP+end, vP+initValSz, vP+start);
425 _values->reAlloc(initValSz+deltaSz);
428 throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::deleteSimplePack");
430 int nt(_index->getNbOfElems());
431 std::copy(iP+idx+1, iP+nt, iP+idx);
432 for(int ii = idx; ii < nt-1; ii++)
434 _index->reAlloc(nt-1);
437 void MEDCouplingSkyLineArray::replaceSimplePacks(const DataArrayInt* idx, const std::vector<const DataArrayInt*>& packs)
442 for (const int * id = idx->begin(); id != idx->end(); id++)
443 validIndex("deleteSimplePacks", *id);
445 if (idx->getNbOfElems() != packs.size())
446 throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::deleteSimplePacks: size of list of pack is incorrect");
448 // copy _index, _values into a deque<set<int>>
449 std::deque< std::set<int> > valuesByIdx;
450 int* vP(_values->getPointer());
451 int* iP(_index->getPointer());
452 std::size_t nt ( _index->getNbOfElems() );
453 for (int ii = 0; ii < nt-1; ii++)
454 valuesByIdx.push_back(std::set<int>(vP+iP[ii], vP+iP[ii+1]));
456 // modify the deque<set<int>> according to idx and packs
458 for (const int *id = idx->begin(); id != idx->end(); id++)
460 valuesByIdx[*id] = std::set<int>(packs[ii]->begin(), packs[ii]->end());
463 // copy back the deque<set<int>> into _index, _values
466 for (std::deque< std::set<int> >::const_iterator values=valuesByIdx.begin();values!=valuesByIdx.end();values++)
468 valSz += (*values).size();
471 _values->reAlloc(valSz);
472 iP = _index->getPointer();
473 vP = _values->getPointer();
474 for (auto values : valuesByIdx)
476 std::copy(values.begin(), values.end(), vP+(*iP));
481 void MEDCouplingSkyLineArray::deleteSimplePacks(const DataArrayInt* idx)
483 for (auto id = idx->begin(); id != idx->end(); id++)
484 validIndex("deleteSimplePacks", *id);
486 std::set<int> packsToDelete(idx->begin(), idx->end());
489 int* iP(_index->getPointer());
490 int initValSz = _values->getNbOfElems();
491 int *vP(_values->getPointer());
492 int end_prec(0),start_prec(0);
493 for(std::set<int>::const_iterator ii=packsToDelete.begin();ii!=packsToDelete.end();ii++)
497 std::copy(vP+end_prec, vP+start, vP+start_prec);
498 start_prec += start-end_prec;
499 end_prec = iP[*ii+1];
502 std::copy(vP+end_prec, vP+initValSz, vP+start_prec);
503 _values->reAlloc(initValSz-(end_prec-start_prec));
506 int nt = _index->getNbOfElems();
511 for(std::set<int>::const_iterator ii=packsToDelete.begin();ii!=packsToDelete.end();ii++)
515 std::copy(iP+end_prec, iP+*ii, iP+start_prec);
516 for (int i=start_prec; i<*ii; i++)
519 offset += iP[*ii+1] - iP[*ii];
520 start_prec = *ii-deleted;
526 std::copy(iP+end_prec, iP+nt, iP+start_prec);
527 for (int i=start_prec; i<nt; i++)
530 _index->reAlloc(nt-deleted);
534 * 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.
536 void MEDCouplingSkyLineArray::pushBackPack(const int superIdx, const int * packBg, const int * packEnd)
540 checkSuperIndex("pushBackPack");
541 validSuperIndex("pushBackPack", superIdx);
543 int *siP(_super_index->getPointer()), *iP(_index->getPointer());
544 const int sz(distance(packBg, packEnd));
547 _values->reAlloc(_values->getNbOfElems()+sz);
548 int * vPE(_values->getPointer()+_values->getNbOfElems());
549 int *vP(_values->getPointer());
550 copy(vP+iP[siP[superIdx+1]], vPE-sz, vP+iP[siP[superIdx+1]]+sz);
552 copy(packBg, packEnd, vP+iP[siP[superIdx+1]]);
555 int nt = _index->getNbOfElems();
556 _index->reAlloc(nt+1); iP = _index->getPointer();
557 copy(iP+siP[superIdx+1]+1, iP+nt, iP+siP[superIdx+1]+2);
558 iP[siP[superIdx+1]+1] = iP[siP[superIdx+1]] + sz;
559 for(int ii = siP[superIdx+1]+2; ii < nt+1; ii++)
563 for(int ii = superIdx+1; ii < (int)_super_index->getNbOfElems(); ii++)
568 * Replace pack with absolute index 'idx' with the provided new pack. Function can be used either
569 * for 2-level SkyLine or 3-level SkyLine.
571 void MEDCouplingSkyLineArray::replaceSimplePack(const int idx, const int * packBg, const int * packEnd)
573 validIndex("replaceSimplePack", idx);
575 int * iP(_index->getPointer());
576 int newSz = std::distance(packBg, packEnd);
577 const int start = iP[idx], end = iP[idx+1];
580 int initValSz = _values->getNbOfElems();
581 int deltaSz = newSz-(end-start); // can be negative
585 _values->reAlloc(initValSz+deltaSz);
586 int *vP(_values->getPointer());
587 std::copy(vP+end, vP+initValSz, vP+end+deltaSz);
589 _values->reAlloc(initValSz+deltaSz);
593 std::copy(packBg, packEnd, _values->getPointer()+start);
596 for(int ii = idx+1; ii < (int)_index->getNbOfElems(); ii++)
601 * Replace pack with super index 'superIdx' and index 'idx' with the provided new pack.
602 * Function can be used only for 3-level SkyLine.
604 void MEDCouplingSkyLineArray::replacePack(const int superIdx, const int idx, const int *packBg, const int *packEnd)
606 checkSuperIndex("replacePack");
607 validSuperIndexAndIndex("replacePack", superIdx, idx);
609 int * siP(_super_index->getPointer()), *iP(_index->getPointer());
610 int newSz = std::distance(packBg, packEnd);
611 const int start = iP[siP[superIdx]+idx], end = iP[siP[superIdx]+idx+1];
614 int initValSz = _values->getNbOfElems();
615 int deltaSz = newSz-(end-start); // can be negative
619 _values->reAlloc(initValSz+deltaSz);
620 int *vP(_values->getPointer());
621 std::copy(vP+end, vP+initValSz, vP+end+deltaSz);
623 _values->reAlloc(initValSz+deltaSz);
627 std::copy(packBg, packEnd, _values->getPointer()+start);
630 for(int ii = siP[superIdx]+idx+1; ii < (int)_index->getNbOfElems(); ii++)