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"
24 using namespace MEDCoupling;
26 MEDCouplingSkyLineArray::MEDCouplingSkyLineArray():
27 _index( DataArrayInt::New() ), _values( DataArrayInt::New() ), _super_index( DataArrayInt::New() )
31 MEDCouplingSkyLineArray::~MEDCouplingSkyLineArray()
35 MEDCouplingSkyLineArray* MEDCouplingSkyLineArray::New()
37 return new MEDCouplingSkyLineArray();
40 MEDCouplingSkyLineArray* MEDCouplingSkyLineArray::New( const std::vector<int>& index,
41 const std::vector<int>& value )
43 MEDCouplingSkyLineArray * ret = new MEDCouplingSkyLineArray();
44 ret->_index->reserve( index.size() );
45 ret->_index->insertAtTheEnd( index.begin(), index.end() );
46 ret->_values->reserve( value.size() );
47 ret->_values->insertAtTheEnd( value.begin(), value.end() );
51 MEDCouplingSkyLineArray* MEDCouplingSkyLineArray::New( DataArrayInt* index, DataArrayInt* value )
53 MEDCouplingSkyLineArray* ret = new MEDCouplingSkyLineArray();
54 ret->set(index, value);
58 MEDCouplingSkyLineArray* MEDCouplingSkyLineArray::New( const MEDCouplingSkyLineArray & other )
60 MEDCouplingSkyLineArray* ret = new MEDCouplingSkyLineArray();
61 ret->_super_index = other._super_index;
62 ret->_index = other._index;
63 ret->_values = other._values;
67 /**! Build a three level SkyLine array from the dynamic connectivity of a dynamic mesh (i.e. containing only
68 * polyhedrons or polygons).
69 * The input arrays are deep copied, contrary to the other ctors.
71 MEDCouplingSkyLineArray * MEDCouplingSkyLineArray::BuildFromPolyhedronConn( const DataArrayInt* c, const DataArrayInt* cI )
75 MEDCouplingSkyLineArray* ret = new MEDCouplingSkyLineArray();
77 const int * cP(c->begin()), * cIP(cI->begin());
79 if (c->getNbOfElems() != *(cI->end()-1))
80 throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::BuildFromDynamicConn: misformatted connectivity (wrong nb of tuples)!");
81 for (int i=0; i < cI->getNbOfElems(); i++)
85 throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::BuildFromDynamicConn: misformatted connectivity (indices not monotonic ascending)!");
87 if (i!=cI->getNbOfElems()-1)
88 if (cP[j] != INTERP_KERNEL::NORM_POLYHED)
89 throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::BuildFromDynamicConn: connectivity containing other types than POLYHED!");
92 vector<int> superIdx, idx, vals;
93 int cnt = 0, cnt2 = 0;
94 superIdx.reserve(cI->getNbOfElems());
95 superIdx.push_back(0);
97 vals.resize(c->getNbOfElems()); // too much because of the type and the -1, but still better than push_back().
98 for (int i=0; i < cI->getNbOfElems()-1; i++)
100 int start = cIP[i]+1, end = cIP[i+1];
101 int * work = vals.data() + cnt;
102 const int * w = cP+start;
103 const int * w2 = find(w, cP+end, -1);
107 int d = distance(w, w2);
109 idx.push_back(cnt); cnt2++;
110 w = w2+1; // skip the -1
111 w2 = find(w, cP+end, -1);
113 copy(w, cP+end, work);
114 cnt += distance(w, cP+end);
115 idx.push_back(cnt); cnt2++;
116 superIdx.push_back(cnt2);
118 ret->_super_index->alloc(superIdx.size(),1);
119 copy(superIdx.begin(), superIdx.end(), ret->_super_index->getPointer());
120 ret->_index->alloc(idx.size(),1);
121 copy(idx.begin(), idx.end(), ret->_index->getPointer());
122 ret->_values->alloc(cnt,1);
123 copy(vals.begin(), vals.begin()+cnt, ret->_values->getPointer());
129 * Convert a three-level SkyLineArray into a polyhedral connectivity.
130 * The super-packs are interpreted as cell description, and the packs represent the face connectivity.
132 void MEDCouplingSkyLineArray::convertToPolyhedronConn( MCAuto<DataArrayInt>& c, MCAuto<DataArrayInt>& cI) const
134 // TODO: in this case an iterator would be nice
137 checkSuperIndex("convertToPolyhedronConn");
139 const int * siP(_super_index->begin()), * iP(_index->begin()), *vP(_values->begin());
141 cI->alloc(_super_index->getNbOfElems(),1); // same number of super packs as number of cells
142 int * cIVecP(cI->getPointer());
143 MCAuto <DataArrayInt> dsi = _index->deltaShiftIndex();
144 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
146 int * cVecP(c->getPointer());
148 for (int i=0; i < _super_index->getNbOfElems()-1; i++)
151 int endId = siP[i+1];
152 cVecP[cnt++] = INTERP_KERNEL::NORM_POLYHED;
153 for (int j=siP[i]; j < endId; j++)
155 int startId2 = iP[j], endId2 = iP[j+1];
156 copy(vP+startId2, vP+endId2, cVecP+cnt);
157 cnt += endId2-startId2;
162 cIVecP[_super_index->getNbOfElems()-1] = cnt;
165 std::size_t MEDCouplingSkyLineArray::getHeapMemorySizeWithoutChildren() const
167 return _index->getHeapMemorySizeWithoutChildren()+_values->getHeapMemorySizeWithoutChildren()+_super_index->getHeapMemorySizeWithoutChildren();
170 std::vector<const BigMemoryObject *> MEDCouplingSkyLineArray::getDirectChildrenWithNull() const
172 std::vector<const BigMemoryObject *> ret;
173 ret.push_back(_super_index);
174 ret.push_back(_index);
175 ret.push_back(_values);
180 void MEDCouplingSkyLineArray::set( DataArrayInt* index, DataArrayInt* value )
184 if ( (DataArrayInt*)_index ) _index->incrRef();
185 else _index = DataArrayInt::New();
186 if ( (DataArrayInt*)_values ) _values->incrRef();
187 else _values = DataArrayInt::New();
190 void MEDCouplingSkyLineArray::set3( DataArrayInt* superIndex, DataArrayInt* index, DataArrayInt* value )
192 _super_index=superIndex;
193 if ( (DataArrayInt*)_super_index ) _super_index->incrRef();
194 else _super_index = DataArrayInt::New();
198 DataArrayInt* MEDCouplingSkyLineArray::getSuperIndexArray() const
200 return ((MEDCouplingSkyLineArray*)this)->_super_index;
204 DataArrayInt* MEDCouplingSkyLineArray::getIndexArray() const
206 return ((MEDCouplingSkyLineArray*)this)->_index;
209 DataArrayInt* MEDCouplingSkyLineArray::getValuesArray() const
211 return ((MEDCouplingSkyLineArray*)this)->_values;
214 void MEDCouplingSkyLineArray::checkSuperIndex(const std::string& func) const
216 if (!_super_index->getNbOfElems())
218 std::ostringstream oss;
219 oss << "MEDCouplingSkyLineArray::"<< func << ": not a three level SkyLineArray! Method is not available for two-level SkyLineArray.";
220 throw INTERP_KERNEL::Exception(oss.str());
224 void MEDCouplingSkyLineArray::validSuperIndex(const std::string& func, int superIndex) const
226 if(superIndex < 0 || superIndex >= _super_index->getNbOfElems())
228 std::ostringstream oss;
229 oss << "MEDCouplingSkyLineArray::" << func << ": invalid super index!";
230 throw INTERP_KERNEL::Exception(oss.str());
234 void MEDCouplingSkyLineArray::validIndex(const std::string& func, int idx) const
236 if(idx < 0 || idx >= _index->getNbOfElems())
238 std::ostringstream oss;
239 oss << "MEDCouplingSkyLineArray::" << func << ": invalid index!";
240 throw INTERP_KERNEL::Exception(oss.str());
244 void MEDCouplingSkyLineArray::validSuperIndexAndIndex(const std::string& func, int superIndex, int index) const
246 validSuperIndex(func, superIndex);
247 int idx = _super_index->begin()[superIndex] + index;
248 if(idx < 0 || idx >= _index->getNbOfElems())
250 std::ostringstream oss;
251 oss << "MEDCouplingSkyLineArray::" << func << ": invalid index!";
252 throw INTERP_KERNEL::Exception(oss.str());
256 std::string MEDCouplingSkyLineArray::simpleRepr() const
258 std::ostringstream oss;
259 oss << "MEDCouplingSkyLineArray (" << this << ")" << std::endl;
260 MCAuto<DataArrayInt> super_index = _super_index->deepCopy();
261 if (_super_index->getNbOfElems())
262 oss << " Nb of super-packs: " << getSuperNumberOf() << std::endl;
265 super_index->alloc(2,1);
266 super_index->setIJSilent(0,0,0);
267 super_index->setIJSilent(1,0,_index->getNbOfElems()-1);
269 oss << " Nb of packs: " << getNumberOf() << std::endl;
270 oss << " Nb of values: " << getLength() << std::endl;
272 if (_super_index->getNbOfElems())
274 oss << " Super-indices:" << std::endl;
276 const int * i = _super_index->begin();
277 for ( ; i != _super_index->end(); ++i )
282 oss << " Indices:" << std::endl;
284 const int * i = _index->begin();
285 for ( ; i != _index->end(); ++i )
288 oss << " Values:" << std::endl;
290 const int * v = _values->begin();
291 int cnt = 0, cntI = 0;
293 for ( const int * si = super_index->begin()+1; v != _values->end(); ++v, ++cnt )
297 if ( cntI == *si && cnt != 0)
299 oss << std::endl << " ";
314 * For a 2- or 3-level SkyLine array, return a copy of the absolute pack with given identifier.
316 void MEDCouplingSkyLineArray::getSimplePackSafe(const int absolutePackId, std::vector<int> & pack) const
318 if(absolutePackId < 0 || absolutePackId >= _index->getNbOfElems())
319 throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::getPackSafe: invalid index!");
320 const int * iP(_index->begin()), *vP(_values->begin());
321 int sz = iP[absolutePackId+1]-iP[absolutePackId];
323 std::copy(vP+iP[absolutePackId], vP+iP[absolutePackId+1],pack.begin());
327 * Same as getPackSafe, but directly returns a pointer to the internal data with the size of the pack.
329 const int * MEDCouplingSkyLineArray::getSimplePackSafePtr(const int absolutePackId, int & packSize) const
331 if(absolutePackId < 0 || absolutePackId >= _index->getNbOfElems())
332 throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::getPackSafe: invalid index!");
333 const int * iP(_index->begin()), *vP(_values->begin());
334 packSize = iP[absolutePackId+1]-iP[absolutePackId];
335 return vP+iP[absolutePackId];
340 * For each given super-pack ID, provide the sub-index of the first matching pack. If no matching pack is found for the
341 * given super-pack -1 is returned.
342 * \param[in] superPackIndices the list of super-packs that should be inspected
343 * \param[in] packBg the pack that the function is looking for in each of the provided super-pack
344 * \param[in] packEnd the pack that the function is looking for in each of the provided super-pack
345 * \param[out] a vector of int, having the same size as superPackIndices and containing for each inspected super-pack
346 * the index of the first matching pack, or -1 if none found.
348 void MEDCouplingSkyLineArray::findPackIds(const std::vector<int> & superPackIndices,
349 const int *packBg, const int *packEnd,
350 std::vector<int>& out) const
354 checkSuperIndex("findPackIds");
356 int packSz = std::distance(packBg, packEnd);
358 throw INTERP_KERNEL::Exception("MEDCouplingSkyLineArray::findPackIds: void pack!");
360 out.resize(superPackIndices.size());
362 const int * siP(_super_index->begin()), * iP(_index->begin()), *vP(_values->begin());
363 for(vector<int>::const_iterator it=superPackIndices.begin(); it!=superPackIndices.end(); ++it, i++)
366 const int sPackIdx = *it;
368 for (int idx=siP[sPackIdx], j=0; idx < siP[sPackIdx+1]; idx++, j++)
370 if (packSz == (iP[idx+1] - iP[idx]))
371 if (equal(&vP[iP[idx]], &vP[iP[idx+1]], packBg))
381 * Delete pack number 'idx' in super-pack number 'superIdx'.
382 * \param[in] superIdx is the super-pack number
383 * \param[in] idx is the pack index inside the super-pack 'superIdx'.
385 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 copy(vP+end, vP+_values->getNbOfElems(), vP+start);
397 _values->reAlloc(_values->getNbOfElems() - (end-start));
400 int nt = _index->getNbOfElems();
401 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 < _super_index->getNbOfElems(); ii++)
412 * 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.
414 void MEDCouplingSkyLineArray::pushBackPack(const int superIdx, const int * packBg, const int * packEnd)
418 checkSuperIndex("pushBackPack");
419 validSuperIndex("pushBackPack", superIdx);
421 int *siP(_super_index->getPointer()), *iP(_index->getPointer());
422 const int sz(distance(packBg, packEnd));
425 _values->reAlloc(_values->getNbOfElems()+sz);
426 int * vPE(_values->getPointer()+_values->getNbOfElems());
427 int *vP(_values->getPointer());
428 copy(vP+iP[siP[superIdx+1]], vPE-sz, vP+iP[siP[superIdx+1]]+sz);
430 copy(packBg, packEnd, vP+iP[siP[superIdx+1]]);
433 int nt = _index->getNbOfElems();
434 _index->reAlloc(nt+1); iP = _index->getPointer();
435 copy(iP+siP[superIdx+1]+1, iP+nt, iP+siP[superIdx+1]+2);
436 iP[siP[superIdx+1]+1] = iP[siP[superIdx+1]] + sz;
437 for(int ii = siP[superIdx+1]+2; ii < nt+1; ii++)
441 for(int ii = superIdx+1; ii < _super_index->getNbOfElems(); ii++)
446 * Replace pack with absolute index 'idx' with the provided new pack. Function can be used either
447 * for 2-level SkyLine or 3-level SkyLine.
449 void MEDCouplingSkyLineArray::replaceSimplePack(const int idx, const int * packBg, const int * packEnd)
453 validIndex("replaceSimplePack", idx);
455 int * iP(_index->getPointer());
456 int newSz = distance(packBg, packEnd);
457 const int start = iP[idx], end = iP[idx+1];
460 int initValSz = _values->getNbOfElems();
461 int deltaSz = newSz-(end-start); // can be negative
465 _values->reAlloc(initValSz+deltaSz);
466 int *vP(_values->getPointer());
467 copy(vP+end, vP+initValSz, vP+end+deltaSz);
469 _values->reAlloc(initValSz+deltaSz);
473 copy(packBg, packEnd, _values->getPointer()+start);
476 for(int ii = idx+1; ii < _index->getNbOfElems(); ii++)
481 * Replace pack with super index 'superIdx' and index 'idx' with the provided new pack.
482 * Function can be used only for 3-level SkyLine.
484 void MEDCouplingSkyLineArray::replacePack(const int superIdx, const int idx, const int * packBg, const int * packEnd)
488 checkSuperIndex("replacePack");
489 validSuperIndexAndIndex("replacePack", superIdx, idx);
491 int * siP(_super_index->getPointer()), *iP(_index->getPointer());
492 int newSz = distance(packBg, packEnd);
493 const int start = iP[siP[superIdx]+idx], end = iP[siP[superIdx]+idx+1];
496 int initValSz = _values->getNbOfElems();
497 int deltaSz = newSz-(end-start); // can be negative
501 _values->reAlloc(initValSz+deltaSz);
502 int *vP(_values->getPointer());
503 copy(vP+end, vP+initValSz, vP+end+deltaSz);
505 _values->reAlloc(initValSz+deltaSz);
509 copy(packBg, packEnd, _values->getPointer()+start);
512 for(int ii = siP[superIdx]+idx+1; ii < _index->getNbOfElems(); ii++)