1 // Copyright (C) 2007-2014 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
19 // Author : Anthony Geay (CEA/DEN)
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"
30 #include "BBTreeDst.txx"
31 #include "SplitterTetra.hxx"
32 #include "DirectedBoundingBox.hxx"
33 #include "InterpKernelMatrixTools.hxx"
34 #include "InterpKernelMeshQuality.hxx"
35 #include "InterpKernelCellSimplify.hxx"
36 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
37 #include "InterpKernelAutoPtr.hxx"
38 #include "InterpKernelGeo2DNode.hxx"
39 #include "InterpKernelGeo2DEdgeLin.hxx"
40 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
41 #include "InterpKernelGeo2DQuadraticPolygon.hxx"
50 using namespace ParaMEDMEM;
52 double MEDCouplingUMesh::EPS_FOR_POLYH_ORIENTATION=1.e-14;
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 };
56 MEDCouplingUMesh *MEDCouplingUMesh::New()
58 return new MEDCouplingUMesh;
61 MEDCouplingUMesh *MEDCouplingUMesh::New(const std::string& meshName, int meshDim)
63 MEDCouplingUMesh *ret=new MEDCouplingUMesh;
64 ret->setName(meshName);
65 ret->setMeshDimension(meshDim);
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.
75 MEDCouplingMesh *MEDCouplingUMesh::deepCpy() const
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.
87 MEDCouplingUMesh *MEDCouplingUMesh::clone(bool recDeepCpy) const
89 return new MEDCouplingUMesh(*this,recDeepCpy);
93 * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
94 * The coordinates are shared between \a this and the returned instance.
96 * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
97 * \sa MEDCouplingUMesh::deepCpy
99 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const
101 checkConnectivityFullyDefined();
102 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
103 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
104 ret->setConnectivity(c,ci);
108 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other)
111 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
112 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
114 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
115 MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
116 setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
119 std::size_t MEDCouplingUMesh::getHeapMemorySizeWithoutChildren() const
121 std::size_t ret(MEDCouplingPointSet::getHeapMemorySizeWithoutChildren());
125 std::vector<const BigMemoryObject *> MEDCouplingUMesh::getDirectChildren() const
127 std::vector<const BigMemoryObject *> ret(MEDCouplingPointSet::getDirectChildren());
129 ret.push_back(_nodal_connec);
130 if(_nodal_connec_index)
131 ret.push_back(_nodal_connec_index);
135 void MEDCouplingUMesh::updateTime() const
137 MEDCouplingPointSet::updateTime();
140 updateTimeWith(*_nodal_connec);
142 if(_nodal_connec_index)
144 updateTimeWith(*_nodal_connec_index);
148 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
153 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
154 * then \a this mesh is most probably is writable, exchangeable and available for most
155 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
156 * this method to check that all is in order with \a this mesh.
157 * \throw If the mesh dimension is not set.
158 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
159 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
160 * \throw If the connectivity data array has more than one component.
161 * \throw If the connectivity data array has a named component.
162 * \throw If the connectivity index data array has more than one component.
163 * \throw If the connectivity index data array has a named component.
165 void MEDCouplingUMesh::checkCoherency() const
168 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
170 MEDCouplingPointSet::checkCoherency();
171 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
173 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
175 std::ostringstream message;
176 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
177 throw INTERP_KERNEL::Exception(message.str().c_str());
182 if(_nodal_connec->getNumberOfComponents()!=1)
183 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
184 if(_nodal_connec->getInfoOnComponent(0)!="")
185 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
189 throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
190 if(_nodal_connec_index)
192 if(_nodal_connec_index->getNumberOfComponents()!=1)
193 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
194 if(_nodal_connec_index->getInfoOnComponent(0)!="")
195 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
199 throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
203 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
204 * then \a this mesh is most probably is writable, exchangeable and available for all
205 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
206 * method thoroughly checks the nodal connectivity.
207 * \param [in] eps - a not used parameter.
208 * \throw If the mesh dimension is not set.
209 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
210 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
211 * \throw If the connectivity data array has more than one component.
212 * \throw If the connectivity data array has a named component.
213 * \throw If the connectivity index data array has more than one component.
214 * \throw If the connectivity index data array has a named component.
215 * \throw If number of nodes defining an element does not correspond to the type of element.
216 * \throw If the nodal connectivity includes an invalid node id.
218 void MEDCouplingUMesh::checkCoherency1(double eps) const
223 int meshDim=getMeshDimension();
224 int nbOfNodes=getNumberOfNodes();
225 int nbOfCells=getNumberOfCells();
226 const int *ptr=_nodal_connec->getConstPointer();
227 const int *ptrI=_nodal_connec_index->getConstPointer();
228 for(int i=0;i<nbOfCells;i++)
230 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
231 if((int)cm.getDimension()!=meshDim)
233 std::ostringstream oss;
234 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
235 throw INTERP_KERNEL::Exception(oss.str().c_str());
237 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
239 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
241 std::ostringstream oss;
242 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
243 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
244 throw INTERP_KERNEL::Exception(oss.str().c_str());
246 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
251 if(nodeId>=nbOfNodes)
253 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
254 throw INTERP_KERNEL::Exception(oss.str().c_str());
259 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
260 throw INTERP_KERNEL::Exception(oss.str().c_str());
264 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
266 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
267 throw INTERP_KERNEL::Exception(oss.str().c_str());
276 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
277 * then \a this mesh is most probably is writable, exchangeable and available for all
278 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
279 * \param [in] eps - a not used parameter.
280 * \throw If the mesh dimension is not set.
281 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
282 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
283 * \throw If the connectivity data array has more than one component.
284 * \throw If the connectivity data array has a named component.
285 * \throw If the connectivity index data array has more than one component.
286 * \throw If the connectivity index data array has a named component.
287 * \throw If number of nodes defining an element does not correspond to the type of element.
288 * \throw If the nodal connectivity includes an invalid node id.
290 void MEDCouplingUMesh::checkCoherency2(double eps) const
292 checkCoherency1(eps);
296 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
297 * elements contained in the mesh. For more info on the mesh dimension see
298 * \ref MEDCouplingUMeshPage.
299 * \param [in] meshDim - a new mesh dimension.
300 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
302 void MEDCouplingUMesh::setMeshDimension(int meshDim)
304 if(meshDim<-1 || meshDim>3)
305 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
311 * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
312 * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
313 * If a nodal connectivity previouly existed before the call of this method, it will be reset.
315 * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
317 * \if ENABLE_EXAMPLES
318 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
319 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
322 void MEDCouplingUMesh::allocateCells(int nbOfCells)
325 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
326 if(_nodal_connec_index)
328 _nodal_connec_index->decrRef();
332 _nodal_connec->decrRef();
334 _nodal_connec_index=DataArrayInt::New();
335 _nodal_connec_index->reserve(nbOfCells+1);
336 _nodal_connec_index->pushBackSilent(0);
337 _nodal_connec=DataArrayInt::New();
338 _nodal_connec->reserve(2*nbOfCells);
344 * Appends a cell to the connectivity array. For deeper understanding what is
345 * happening see \ref MEDCouplingUMeshNodalConnectivity.
346 * \param [in] type - type of cell to add.
347 * \param [in] size - number of nodes constituting this cell.
348 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
350 * \if ENABLE_EXAMPLES
351 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
352 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
355 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell)
357 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
358 if(_nodal_connec_index==0)
359 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
360 if((int)cm.getDimension()==_mesh_dim)
363 if(size!=(int)cm.getNumberOfNodes())
365 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
366 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
367 throw INTERP_KERNEL::Exception(oss.str().c_str());
369 int idx=_nodal_connec_index->back();
371 _nodal_connec_index->pushBackSilent(val);
372 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
377 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
378 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
379 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
380 throw INTERP_KERNEL::Exception(oss.str().c_str());
385 * Compacts data arrays to release unused memory. This method is to be called after
386 * finishing cell insertion using \a this->insertNextCell().
388 * \if ENABLE_EXAMPLES
389 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
390 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
393 void MEDCouplingUMesh::finishInsertingCells()
395 _nodal_connec->pack();
396 _nodal_connec_index->pack();
397 _nodal_connec->declareAsNew();
398 _nodal_connec_index->declareAsNew();
403 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
404 * Useful for python users.
406 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
408 return new MEDCouplingUMeshCellIterator(this);
412 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
413 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
414 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
415 * Useful for python users.
417 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType()
419 if(!checkConsecutiveCellTypes())
420 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
421 return new MEDCouplingUMeshCellByTypeEntry(this);
425 * Returns a set of all cell types available in \a this mesh.
426 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
427 * \warning this method does not throw any exception even if \a this is not defined.
428 * \sa MEDCouplingUMesh::getAllGeoTypesSorted
430 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
436 * This method returns the sorted list of geometric types in \a this.
437 * Sorted means in the same order than the cells in \a this. A single entry in return vector means the maximal chunk of consecutive cells in \a this
438 * having the same geometric type. So a same geometric type can appear more than once if the cells are not sorted per geometric type.
440 * \throw if connectivity in \a this is not correctly defined.
442 * \sa MEDCouplingMesh::getAllGeoTypes
444 std::vector<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypesSorted() const
446 std::vector<INTERP_KERNEL::NormalizedCellType> ret;
447 checkConnectivityFullyDefined();
448 int nbOfCells(getNumberOfCells());
451 if(getMeshLength()<1)
452 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAllGeoTypesSorted : the connectivity in this seems invalid !");
453 const int *c(_nodal_connec->begin()),*ci(_nodal_connec_index->begin());
454 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci++]);
455 for(int i=1;i<nbOfCells;i++,ci++)
456 if(ret.back()!=((INTERP_KERNEL::NormalizedCellType)c[*ci]))
457 ret.push_back((INTERP_KERNEL::NormalizedCellType)c[*ci]);
462 * This method is a method that compares \a this and \a other.
463 * This method compares \b all attributes, even names and component names.
465 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const
468 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
469 std::ostringstream oss; oss.precision(15);
470 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
473 reason="mesh given in input is not castable in MEDCouplingUMesh !";
476 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
478 if(_mesh_dim!=otherC->_mesh_dim)
480 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
484 if(_types!=otherC->_types)
486 oss << "umesh geometric type mismatch :\nThis geometric types are :";
487 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
488 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
489 oss << "\nOther geometric types are :";
490 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
491 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
495 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
496 if(_nodal_connec==0 || otherC->_nodal_connec==0)
498 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
501 if(_nodal_connec!=otherC->_nodal_connec)
502 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
504 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
507 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
508 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
510 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
513 if(_nodal_connec_index!=otherC->_nodal_connec_index)
514 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
516 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
523 * Checks if data arrays of this mesh (node coordinates, nodal
524 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
526 * \param [in] other - the mesh to compare with.
527 * \param [in] prec - precision value used to compare node coordinates.
528 * \return bool - \a true if the two meshes are same.
530 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
532 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
535 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
537 if(_mesh_dim!=otherC->_mesh_dim)
539 if(_types!=otherC->_types)
541 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
542 if(_nodal_connec==0 || otherC->_nodal_connec==0)
544 if(_nodal_connec!=otherC->_nodal_connec)
545 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
547 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
548 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
550 if(_nodal_connec_index!=otherC->_nodal_connec_index)
551 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
557 * Checks if \a this and \a other meshes are geometrically equivalent with high
558 * probability, else an exception is thrown. The meshes are considered equivalent if
559 * (1) meshes contain the same number of nodes and the same number of elements of the
560 * same types (2) three cells of the two meshes (first, last and middle) are based
561 * on coincident nodes (with a specified precision).
562 * \param [in] other - the mesh to compare with.
563 * \param [in] prec - the precision used to compare nodes of the two meshes.
564 * \throw If the two meshes do not match.
566 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const
568 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
569 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
571 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
575 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
576 * cells each node belongs to.
577 * \warning For speed reasons, this method does not check if node ids in the nodal
578 * connectivity correspond to the size of node coordinates array.
579 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
580 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
581 * dividing cell ids in \a revNodal into groups each referring to one
582 * node. Its every element (except the last one) is an index pointing to the
583 * first id of a group of cells. For example cells sharing the node #1 are
584 * described by following range of indices:
585 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
586 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
587 * Number of cells sharing the *i*-th node is
588 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
589 * \throw If the coordinates array is not set.
590 * \throw If the nodal connectivity of cells is not defined.
592 * \if ENABLE_EXAMPLES
593 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
594 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
597 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const
600 int nbOfNodes=getNumberOfNodes();
601 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
602 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
603 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
604 const int *conn=_nodal_connec->getConstPointer();
605 const int *connIndex=_nodal_connec_index->getConstPointer();
606 int nbOfCells=getNumberOfCells();
607 int nbOfEltsInRevNodal=0;
608 for(int eltId=0;eltId<nbOfCells;eltId++)
610 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
611 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
612 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
613 if(*iter>=0)//for polyhedrons
615 nbOfEltsInRevNodal++;
616 revNodalIndxPtr[(*iter)+1]++;
619 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
620 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
621 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
622 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
623 for(int eltId=0;eltId<nbOfCells;eltId++)
625 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
626 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
627 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
628 if(*iter>=0)//for polyhedrons
629 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
635 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
640 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
646 if(cm.getOrientationStatus(nb,conn1,conn2))
653 class MinusOneSonsGenerator
656 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
657 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
658 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
659 static const int DELTA=1;
661 const INTERP_KERNEL::CellModel& _cm;
664 class MinusOneSonsGeneratorBiQuadratic
667 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
668 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
669 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
670 static const int DELTA=1;
672 const INTERP_KERNEL::CellModel& _cm;
675 class MinusTwoSonsGenerator
678 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
679 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
680 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
681 static const int DELTA=2;
683 const INTERP_KERNEL::CellModel& _cm;
689 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
690 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
691 * describing correspondence between cells of \a this and the result meshes are
692 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
693 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
694 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
695 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
696 * \warning For speed reasons, this method does not check if node ids in the nodal
697 * connectivity correspond to the size of node coordinates array.
698 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
699 * to write this mesh to the MED file, its cells must be sorted using
700 * sortCellsInMEDFileFrmt().
701 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
702 * each cell of \a this mesh.
703 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
704 * dividing cell ids in \a desc into groups each referring to one
705 * cell of \a this mesh. Its every element (except the last one) is an index
706 * pointing to the first id of a group of cells. For example cells of the
707 * result mesh bounding the cell #1 of \a this mesh are described by following
709 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
710 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
711 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
712 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
713 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
714 * by each cell of the result mesh.
715 * \param [in,out] revDescIndx - the array, of length one more than number of cells
716 * in the result mesh,
717 * dividing cell ids in \a revDesc into groups each referring to one
718 * cell of the result mesh the same way as \a descIndx divides \a desc.
719 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
720 * delete this mesh using decrRef() as it is no more needed.
721 * \throw If the coordinates array is not set.
722 * \throw If the nodal connectivity of cells is node defined.
723 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
724 * revDescIndx == NULL.
726 * \if ENABLE_EXAMPLES
727 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
728 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
730 * \sa buildDescendingConnectivity2()
732 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
734 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
738 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
739 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
740 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
741 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
742 * \sa MEDCouplingUMesh::buildDescendingConnectivity
744 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
747 if(getMeshDimension()!=3)
748 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
749 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
753 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
754 * this->getMeshDimension(), that bound cells of \a this mesh. In
755 * addition arrays describing correspondence between cells of \a this and the result
756 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
757 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
758 * mesh. This method differs from buildDescendingConnectivity() in that apart
759 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
760 * result meshes. So a positive id means that order of nodes in corresponding cells
761 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
762 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
763 * i.e. cell ids are one-based.
764 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
765 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
766 * \warning For speed reasons, this method does not check if node ids in the nodal
767 * connectivity correspond to the size of node coordinates array.
768 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
769 * to write this mesh to the MED file, its cells must be sorted using
770 * sortCellsInMEDFileFrmt().
771 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
772 * each cell of \a this mesh.
773 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
774 * dividing cell ids in \a desc into groups each referring to one
775 * cell of \a this mesh. Its every element (except the last one) is an index
776 * pointing to the first id of a group of cells. For example cells of the
777 * result mesh bounding the cell #1 of \a this mesh are described by following
779 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
780 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
781 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
782 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
783 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
784 * by each cell of the result mesh.
785 * \param [in,out] revDescIndx - the array, of length one more than number of cells
786 * in the result mesh,
787 * dividing cell ids in \a revDesc into groups each referring to one
788 * cell of the result mesh the same way as \a descIndx divides \a desc.
789 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
790 * shares the node coordinates array with \a this mesh. The caller is to
791 * delete this mesh using decrRef() as it is no more needed.
792 * \throw If the coordinates array is not set.
793 * \throw If the nodal connectivity of cells is node defined.
794 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
795 * revDescIndx == NULL.
797 * \if ENABLE_EXAMPLES
798 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
799 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
801 * \sa buildDescendingConnectivity()
803 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const
805 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
809 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
810 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
811 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
812 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
814 * \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
815 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
816 * \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.
818 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const
820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
821 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
822 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
823 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
824 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
826 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
830 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
831 * 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,
832 * excluding a set of meshdim-1 cells in input descending connectivity.
833 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
834 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
835 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
837 * \param [in] desc descending connectivity array.
838 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
839 * \param [in] revDesc reverse descending connectivity array.
840 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
841 * \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
842 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
843 * \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.
845 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
846 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
848 if(!desc || !descIndx || !revDesc || !revDescIndx)
849 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
850 const int *descPtr=desc->getConstPointer();
851 const int *descIPtr=descIndx->getConstPointer();
852 const int *revDescPtr=revDesc->getConstPointer();
853 const int *revDescIPtr=revDescIndx->getConstPointer();
855 int nbCells=descIndx->getNumberOfTuples()-1;
856 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
857 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
858 int *out1Ptr=out1->getPointer();
860 out0->reserve(desc->getNumberOfTuples());
861 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
863 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
865 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
867 out0->insertAtTheEnd(s.begin(),s.end());
869 *out1Ptr=out0->getNumberOfTuples();
871 neighbors=out0.retn();
872 neighborsIndx=out1.retn();
878 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
879 * For speed reasons no check of this will be done.
881 template<class SonsGenerator>
882 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const
884 if(!desc || !descIndx || !revDesc || !revDescIndx)
885 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
886 checkConnectivityFullyDefined();
887 int nbOfCells=getNumberOfCells();
888 int nbOfNodes=getNumberOfNodes();
889 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
890 int *revNodalIndxPtr=revNodalIndx->getPointer();
891 const int *conn=_nodal_connec->getConstPointer();
892 const int *connIndex=_nodal_connec_index->getConstPointer();
893 std::string name="Mesh constituent of "; name+=getName();
894 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name,getMeshDimension()-SonsGenerator::DELTA);
895 ret->setCoords(getCoords());
896 ret->allocateCells(2*nbOfCells);
897 descIndx->alloc(nbOfCells+1,1);
898 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
899 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
900 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
902 int pos=connIndex[eltId];
903 int posP1=connIndex[eltId+1];
904 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
905 SonsGenerator sg(cm);
906 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
907 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
908 for(unsigned i=0;i<nbOfSons;i++)
910 INTERP_KERNEL::NormalizedCellType cmsId;
911 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
912 for(unsigned k=0;k<nbOfNodesSon;k++)
914 revNodalIndxPtr[tmp[k]+1]++;
915 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
916 revDesc2->pushBackSilent(eltId);
918 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
920 int nbOfCellsM1=ret->getNumberOfCells();
921 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
922 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
923 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
924 int *revNodalPtr=revNodal->getPointer();
925 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
926 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
927 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
929 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
930 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
931 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
932 if(*iter>=0)//for polyhedrons
933 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
936 DataArrayInt *commonCells=0,*commonCellsI=0;
937 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
938 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
939 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
940 int newNbOfCellsM1=-1;
941 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
942 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
943 std::vector<bool> isImpacted(nbOfCellsM1,false);
944 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
945 for(int work2=work[0];work2!=work[1];work2++)
946 isImpacted[commonCellsPtr[work2]]=true;
947 const int *o2nM1Ptr=o2nM1->getConstPointer();
948 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
949 const int *n2oM1Ptr=n2oM1->getConstPointer();
950 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
951 ret2->copyTinyInfoFrom(this);
952 desc->alloc(descIndx->back(),1);
953 int *descPtr=desc->getPointer();
954 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
955 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
958 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
961 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
963 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
964 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
967 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
970 revDesc->reserve(newNbOfCellsM1);
971 revDescIndx->alloc(newNbOfCellsM1+1,1);
972 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
973 const int *revDesc2Ptr=revDesc2->getConstPointer();
974 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
976 int oldCellIdM1=n2oM1Ptr[i];
977 if(!isImpacted[oldCellIdM1])
979 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
980 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
984 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
985 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
986 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
994 struct MEDCouplingAccVisit
996 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
997 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
998 int _new_nb_of_nodes;
1004 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
1005 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
1006 * array of cell ids. Pay attention that after conversion all algorithms work slower
1007 * with \a this mesh than before conversion. <br> If an exception is thrown during the
1008 * conversion due presence of invalid ids in the array of cells to convert, as a
1009 * result \a this mesh contains some already converted elements. In this case the 2D
1010 * mesh remains valid but 3D mesh becomes \b inconsistent!
1011 * \warning This method can significantly modify the order of geometric types in \a this,
1012 * hence, to write this mesh to the MED file, its cells must be sorted using
1013 * sortCellsInMEDFileFrmt().
1014 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
1015 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
1016 * cellIdsToConvertBg.
1017 * \throw If the coordinates array is not set.
1018 * \throw If the nodal connectivity of cells is node defined.
1019 * \throw If dimension of \a this mesh is not either 2 or 3.
1021 * \if ENABLE_EXAMPLES
1022 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
1023 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
1026 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
1028 checkFullyDefined();
1029 int dim=getMeshDimension();
1031 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
1032 int nbOfCells(getNumberOfCells());
1035 const int *connIndex=_nodal_connec_index->getConstPointer();
1036 int *conn=_nodal_connec->getPointer();
1037 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1039 if(*iter>=0 && *iter<nbOfCells)
1041 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
1042 if(!cm.isQuadratic())
1043 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
1045 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1049 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1050 oss << " in range [0," << nbOfCells << ") !";
1051 throw INTERP_KERNEL::Exception(oss.str().c_str());
1057 int *connIndex(_nodal_connec_index->getPointer());
1058 const int *connOld(_nodal_connec->getConstPointer());
1059 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew(DataArrayInt::New()),connNewI(DataArrayInt::New()); connNew->alloc(0,1); connNewI->alloc(1,1); connNewI->setIJ(0,0,0);
1060 std::vector<bool> toBeDone(nbOfCells,false);
1061 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1063 if(*iter>=0 && *iter<nbOfCells)
1064 toBeDone[*iter]=true;
1067 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1068 oss << " in range [0," << nbOfCells << ") !";
1069 throw INTERP_KERNEL::Exception(oss.str().c_str());
1072 for(int cellId=0;cellId<nbOfCells;cellId++)
1074 int pos(connIndex[cellId]),posP1(connIndex[cellId+1]);
1075 int lgthOld(posP1-pos-1);
1076 if(toBeDone[cellId])
1078 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connOld[pos]);
1079 unsigned nbOfFaces(cm.getNumberOfSons2(connOld+pos+1,lgthOld));
1080 int *tmp(new int[nbOfFaces*lgthOld+1]);
1081 int *work=tmp; *work++=INTERP_KERNEL::NORM_POLYHED;
1082 for(unsigned j=0;j<nbOfFaces;j++)
1084 INTERP_KERNEL::NormalizedCellType type;
1085 unsigned offset=cm.fillSonCellNodalConnectivity2(j,connOld+pos+1,lgthOld,work,type);
1089 std::size_t newLgth(std::distance(tmp,work)-1);//-1 for last -1
1090 connNew->pushBackValsSilent(tmp,tmp+newLgth);
1091 connNewI->pushBackSilent(connNewI->back()+(int)newLgth);
1096 connNew->pushBackValsSilent(connOld+pos,connOld+posP1);
1097 connNewI->pushBackSilent(connNewI->back()+posP1-pos);
1100 setConnectivity(connNew,connNewI,false);//false because computeTypes called just behind.
1106 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1107 * polyhedrons (if \a this is a 3D mesh).
1108 * \warning As this method is purely for user-friendliness and no optimization is
1109 * done to avoid construction of a useless vector, this method can be costly
1111 * \throw If the coordinates array is not set.
1112 * \throw If the nodal connectivity of cells is node defined.
1113 * \throw If dimension of \a this mesh is not either 2 or 3.
1115 void MEDCouplingUMesh::convertAllToPoly()
1117 int nbOfCells=getNumberOfCells();
1118 std::vector<int> cellIds(nbOfCells);
1119 for(int i=0;i<nbOfCells;i++)
1121 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1125 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1126 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1127 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1128 * base facet of the volume and the second half of nodes describes an opposite facet
1129 * having the same number of nodes as the base one. This method converts such
1130 * connectivity to a valid polyhedral format where connectivity of each facet is
1131 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1132 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1133 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1134 * a correct orientation of the first facet of a polyhedron, else orientation of a
1135 * corrected cell is reverse.<br>
1136 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1137 * it releases the user from boring description of polyhedra connectivity in the valid
1139 * \throw If \a this->getMeshDimension() != 3.
1140 * \throw If \a this->getSpaceDimension() != 3.
1141 * \throw If the nodal connectivity of cells is not defined.
1142 * \throw If the coordinates array is not set.
1143 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1144 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1146 * \if ENABLE_EXAMPLES
1147 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1148 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1151 void MEDCouplingUMesh::convertExtrudedPolyhedra()
1153 checkFullyDefined();
1154 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1155 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1156 int nbOfCells=getNumberOfCells();
1157 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1158 newCi->alloc(nbOfCells+1,1);
1159 int *newci=newCi->getPointer();
1160 const int *ci=_nodal_connec_index->getConstPointer();
1161 const int *c=_nodal_connec->getConstPointer();
1163 for(int i=0;i<nbOfCells;i++)
1165 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1166 if(type==INTERP_KERNEL::NORM_POLYHED)
1168 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1170 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1171 throw INTERP_KERNEL::Exception(oss.str().c_str());
1173 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1176 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 !";
1177 throw INTERP_KERNEL::Exception(oss.str().c_str());
1180 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)
1183 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1185 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1186 newC->alloc(newci[nbOfCells],1);
1187 int *newc=newC->getPointer();
1188 for(int i=0;i<nbOfCells;i++)
1190 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1191 if(type==INTERP_KERNEL::NORM_POLYHED)
1193 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1194 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1196 for(std::size_t j=0;j<n1;j++)
1198 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1200 newc[n1+5*j+1]=c[ci[i]+1+j];
1201 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1202 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1203 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1208 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1210 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1211 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1216 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1217 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1218 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1219 * to write this mesh to the MED file, its cells must be sorted using
1220 * sortCellsInMEDFileFrmt().
1221 * \return \c true if at least one cell has been converted, \c false else. In the
1222 * last case the nodal connectivity remains unchanged.
1223 * \throw If the coordinates array is not set.
1224 * \throw If the nodal connectivity of cells is not defined.
1225 * \throw If \a this->getMeshDimension() < 0.
1227 bool MEDCouplingUMesh::unPolyze()
1229 checkFullyDefined();
1230 int mdim=getMeshDimension();
1232 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1235 int nbOfCells=getNumberOfCells();
1238 int initMeshLgth=getMeshLength();
1239 int *conn=_nodal_connec->getPointer();
1240 int *index=_nodal_connec_index->getPointer();
1245 for(int i=0;i<nbOfCells;i++)
1247 lgthOfCurCell=index[i+1]-posOfCurCell;
1248 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1249 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1250 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1254 switch(cm.getDimension())
1258 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1259 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1260 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1265 int nbOfFaces,lgthOfPolyhConn;
1266 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1267 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1272 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1276 ret=ret || (newType!=type);
1277 conn[newPos]=newType;
1279 posOfCurCell=index[i+1];
1284 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1285 newPos+=lgthOfCurCell;
1286 posOfCurCell+=lgthOfCurCell;
1290 if(newPos!=initMeshLgth)
1291 _nodal_connec->reAlloc(newPos);
1298 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1299 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1300 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1302 * \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
1305 void MEDCouplingUMesh::simplifyPolyhedra(double eps)
1307 checkFullyDefined();
1308 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1309 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1310 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1311 coords->recenterForMaxPrecision(eps);
1313 int nbOfCells=getNumberOfCells();
1314 const int *conn=_nodal_connec->getConstPointer();
1315 const int *index=_nodal_connec_index->getConstPointer();
1316 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1317 connINew->alloc(nbOfCells+1,1);
1318 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1319 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1321 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1323 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1325 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1329 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1330 *connINewPtr=connNew->getNumberOfTuples();
1333 setConnectivity(connNew,connINew,false);
1337 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1338 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1339 * the format of returned DataArrayInt instance.
1341 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1342 * \sa MEDCouplingUMesh::getNodeIdsInUse
1344 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const
1346 checkConnectivityFullyDefined();
1347 int nbOfCells=getNumberOfCells();
1348 const int *connIndex=_nodal_connec_index->getConstPointer();
1349 const int *conn=_nodal_connec->getConstPointer();
1350 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1351 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1352 std::vector<bool> retS(maxElt,false);
1353 for(int i=0;i<nbOfCells;i++)
1354 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1358 for(int i=0;i<maxElt;i++)
1361 DataArrayInt *ret=DataArrayInt::New();
1363 int *retPtr=ret->getPointer();
1364 for(int i=0;i<maxElt;i++)
1371 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1372 * \sa MEDCouplingUMesh::getNodeIdsInUse
1374 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const
1376 int nbOfNodes=(int)nodeIdsInUse.size();
1377 int nbOfCells=getNumberOfCells();
1378 const int *connIndex=_nodal_connec_index->getConstPointer();
1379 const int *conn=_nodal_connec->getConstPointer();
1380 for(int i=0;i<nbOfCells;i++)
1381 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1384 if(conn[j]<nbOfNodes)
1385 nodeIdsInUse[conn[j]]=true;
1388 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1389 throw INTERP_KERNEL::Exception(oss.str().c_str());
1395 * Finds nodes not used in any cell and returns an array giving a new id to every node
1396 * by excluding the unused nodes, for which the array holds -1. The result array is
1397 * a mapping in "Old to New" mode.
1398 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1399 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1400 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1401 * if the node is unused or a new id else. The caller is to delete this
1402 * array using decrRef() as it is no more needed.
1403 * \throw If the coordinates array is not set.
1404 * \throw If the nodal connectivity of cells is not defined.
1405 * \throw If the nodal connectivity includes an invalid id.
1407 * \if ENABLE_EXAMPLES
1408 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1409 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1411 * \sa computeNodeIdsAlg()
1413 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const
1416 int nbOfNodes=getNumberOfNodes();
1417 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1418 ret->alloc(nbOfNodes,1);
1419 int *traducer=ret->getPointer();
1420 std::fill(traducer,traducer+nbOfNodes,-1);
1421 int nbOfCells=getNumberOfCells();
1422 const int *connIndex=_nodal_connec_index->getConstPointer();
1423 const int *conn=_nodal_connec->getConstPointer();
1424 for(int i=0;i<nbOfCells;i++)
1425 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1428 if(conn[j]<nbOfNodes)
1429 traducer[conn[j]]=1;
1432 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1433 throw INTERP_KERNEL::Exception(oss.str().c_str());
1436 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1437 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1442 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1443 * For each cell in \b this the number of nodes constituting cell is computed.
1444 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1445 * So for pohyhedrons some nodes can be counted several times in the returned result.
1447 * \return a newly allocated array
1448 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1450 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const
1452 checkConnectivityFullyDefined();
1453 int nbOfCells=getNumberOfCells();
1454 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1455 ret->alloc(nbOfCells,1);
1456 int *retPtr=ret->getPointer();
1457 const int *conn=getNodalConnectivity()->getConstPointer();
1458 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1459 for(int i=0;i<nbOfCells;i++,retPtr++)
1461 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1462 *retPtr=connI[i+1]-connI[i]-1;
1464 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1470 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1471 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1473 * \return DataArrayInt * - new object to be deallocated by the caller.
1474 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1476 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const
1478 checkConnectivityFullyDefined();
1479 int nbOfCells=getNumberOfCells();
1480 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1481 ret->alloc(nbOfCells,1);
1482 int *retPtr=ret->getPointer();
1483 const int *conn=getNodalConnectivity()->getConstPointer();
1484 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1485 for(int i=0;i<nbOfCells;i++,retPtr++)
1487 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1488 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1489 *retPtr=(int)s.size();
1493 *retPtr=(int)s.size();
1500 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1501 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1503 * \return a newly allocated array
1505 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const
1507 checkConnectivityFullyDefined();
1508 int nbOfCells=getNumberOfCells();
1509 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1510 ret->alloc(nbOfCells,1);
1511 int *retPtr=ret->getPointer();
1512 const int *conn=getNodalConnectivity()->getConstPointer();
1513 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1514 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1516 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1517 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1523 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1524 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1525 * array mean that the corresponding old node is no more used.
1526 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1527 * this->getNumberOfNodes() before call of this method. The caller is to
1528 * delete this array using decrRef() as it is no more needed.
1529 * \throw If the coordinates array is not set.
1530 * \throw If the nodal connectivity of cells is not defined.
1531 * \throw If the nodal connectivity includes an invalid id.
1533 * \if ENABLE_EXAMPLES
1534 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1535 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1538 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer()
1540 return MEDCouplingPointSet::zipCoordsTraducer();
1544 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1545 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1547 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1552 return AreCellsEqual0(conn,connI,cell1,cell2);
1554 return AreCellsEqual1(conn,connI,cell1,cell2);
1556 return AreCellsEqual2(conn,connI,cell1,cell2);
1558 return AreCellsEqual3(conn,connI,cell1,cell2);
1560 return AreCellsEqual7(conn,connI,cell1,cell2);
1562 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1566 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1568 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1570 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1571 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1576 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1578 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1580 int sz=connI[cell1+1]-connI[cell1];
1581 if(sz==connI[cell2+1]-connI[cell2])
1583 if(conn[connI[cell1]]==conn[connI[cell2]])
1585 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1586 unsigned dim=cm.getDimension();
1592 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1593 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1594 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1595 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1596 return work!=tmp+sz1?1:0;
1599 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1602 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1609 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1611 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1613 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1615 if(conn[connI[cell1]]==conn[connI[cell2]])
1617 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1618 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1626 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1628 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1630 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1632 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1633 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1640 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1642 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1644 int sz=connI[cell1+1]-connI[cell1];
1645 if(sz==connI[cell2+1]-connI[cell2])
1647 if(conn[connI[cell1]]==conn[connI[cell2]])
1649 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1650 unsigned dim=cm.getDimension();
1656 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1657 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1658 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1659 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1664 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1665 std::reverse_iterator<int *> it2((int *)tmp);
1666 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1672 return work!=tmp+sz1?1:0;
1675 {//case of SEG2 and SEG3
1676 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1678 if(!cm.isQuadratic())
1680 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1681 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1682 if(std::equal(it1,it2,conn+connI[cell2]+1))
1688 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])
1695 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1702 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1703 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1704 * and result remains unchanged.
1705 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1706 * If in 'candidates' pool -1 value is considered as an empty value.
1707 * WARNING this method returns only ONE set of result !
1709 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1711 if(candidates.size()<1)
1714 std::vector<int>::const_iterator iter=candidates.begin();
1715 int start=(*iter++);
1716 for(;iter!=candidates.end();iter++)
1718 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1723 result->pushBackSilent(start);
1727 result->pushBackSilent(*iter);
1729 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1736 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1737 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1739 * \param [in] compType input specifying the technique used to compare cells each other.
1740 * - 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.
1741 * - 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)
1742 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1743 * - 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
1744 * can be used for users not sensitive to orientation of cell
1745 * \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.
1746 * \param [out] commonCells
1747 * \param [out] commonCellsI
1748 * \return the correspondance array old to new in a newly allocated array.
1751 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const
1753 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1754 getReverseNodalConnectivity(revNodal,revNodalI);
1755 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1758 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1759 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1761 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1762 int nbOfCells=nodalI->getNumberOfTuples()-1;
1763 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1764 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1765 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1766 std::vector<bool> isFetched(nbOfCells,false);
1769 for(int i=0;i<nbOfCells;i++)
1773 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1774 std::vector<int> v,v2;
1775 if(connOfNode!=connPtr+connIPtr[i+1])
1777 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1778 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1781 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1785 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1786 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1787 v2.resize(std::distance(v2.begin(),it));
1791 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1793 int pos=commonCellsI->back();
1794 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1795 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1796 isFetched[*it]=true;
1804 for(int i=startCellId;i<nbOfCells;i++)
1808 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1809 std::vector<int> v,v2;
1810 if(connOfNode!=connPtr+connIPtr[i+1])
1812 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1815 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1819 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1820 v2.resize(std::distance(v2.begin(),it));
1824 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1826 int pos=commonCellsI->back();
1827 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1828 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1829 isFetched[*it]=true;
1835 commonCellsArr=commonCells.retn();
1836 commonCellsIArr=commonCellsI.retn();
1840 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1841 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1842 * than \a other->getNumberOfCells() in the returned array means that there is no
1843 * corresponding cell in \a this mesh.
1844 * It is expected that \a this and \a other meshes share the same node coordinates
1845 * array, if it is not so an exception is thrown.
1846 * \param [in] other - the mesh to compare with.
1847 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1848 * valid values [0,1,2], see zipConnectivityTraducer().
1849 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1850 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1851 * values. The caller is to delete this array using
1852 * decrRef() as it is no more needed.
1853 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1856 * \if ENABLE_EXAMPLES
1857 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1858 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1860 * \sa checkDeepEquivalOnSameNodesWith()
1861 * \sa checkGeoEquivalWith()
1863 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const
1865 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1866 int nbOfCells=getNumberOfCells();
1867 static const int possibleCompType[]={0,1,2};
1868 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1870 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1871 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1873 throw INTERP_KERNEL::Exception(oss.str().c_str());
1875 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1876 arr=o2n->substr(nbOfCells);
1877 arr->setName(other->getName());
1879 if(other->getNumberOfCells()==0)
1881 return arr->getMaxValue(tmp)<nbOfCells;
1885 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1886 * This method tries to determine if \b other is fully included in \b this.
1887 * The main difference is that this method is not expected to throw exception.
1888 * This method has two outputs :
1890 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1891 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1893 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const
1895 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1896 DataArrayInt *commonCells=0,*commonCellsI=0;
1897 int thisNbCells=getNumberOfCells();
1898 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1899 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1900 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1901 int otherNbCells=other->getNumberOfCells();
1902 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1903 arr2->alloc(otherNbCells,1);
1904 arr2->fillWithZero();
1905 int *arr2Ptr=arr2->getPointer();
1906 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1907 for(int i=0;i<nbOfCommon;i++)
1909 int start=commonCellsPtr[commonCellsIPtr[i]];
1910 if(start<thisNbCells)
1912 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1914 int sig=commonCellsPtr[j]>0?1:-1;
1915 int val=std::abs(commonCellsPtr[j])-1;
1916 if(val>=thisNbCells)
1917 arr2Ptr[val-thisNbCells]=sig*(start+1);
1921 arr2->setName(other->getName());
1922 if(arr2->presenceOfValue(0))
1928 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1931 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1932 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1934 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1935 std::vector<const MEDCouplingUMesh *> ms(2);
1938 return MergeUMeshesOnSameCoords(ms);
1942 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1943 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1944 * cellIds is not given explicitely but by a range python like.
1946 * \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.
1947 * \return a newly allocated
1949 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1950 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1952 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const
1954 if(getMeshDimension()!=-1)
1955 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1958 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1960 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1962 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1964 return const_cast<MEDCouplingUMesh *>(this);
1969 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1970 * The result mesh shares or not the node coordinates array with \a this mesh depending
1971 * on \a keepCoords parameter.
1972 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1973 * to write this mesh to the MED file, its cells must be sorted using
1974 * sortCellsInMEDFileFrmt().
1975 * \param [in] begin - an array of cell ids to include to the new mesh.
1976 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
1977 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1978 * array of \a this mesh, else "free" nodes are removed from the result mesh
1979 * by calling zipCoords().
1980 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1981 * to delete this mesh using decrRef() as it is no more needed.
1982 * \throw If the coordinates array is not set.
1983 * \throw If the nodal connectivity of cells is not defined.
1984 * \throw If any cell id in the array \a begin is not valid.
1986 * \if ENABLE_EXAMPLES
1987 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1988 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
1991 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1993 if(getMeshDimension()!=-1)
1994 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1998 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
2000 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
2002 return const_cast<MEDCouplingUMesh *>(this);
2007 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
2009 * 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.
2010 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
2011 * The number of cells of \b this will remain the same with this method.
2013 * \param [in] begin begin of cell ids (included) of cells in this to assign
2014 * \param [in] end end of cell ids (excluded) of cells in this to assign
2015 * \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 ).
2016 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
2018 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2020 checkConnectivityFullyDefined();
2021 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2022 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2023 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2024 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2026 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2027 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2028 throw INTERP_KERNEL::Exception(oss.str().c_str());
2030 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
2031 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2033 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2034 throw INTERP_KERNEL::Exception(oss.str().c_str());
2036 int nbOfCells=getNumberOfCells();
2037 bool easyAssign=true;
2038 const int *connI=_nodal_connec_index->getConstPointer();
2039 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2040 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
2042 if(*it>=0 && *it<nbOfCells)
2044 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
2048 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
2049 throw INTERP_KERNEL::Exception(oss.str().c_str());
2054 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2059 DataArrayInt *arrOut=0,*arrIOut=0;
2060 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2062 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2063 setConnectivity(arrOut,arrIOut,true);
2067 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis)
2069 checkConnectivityFullyDefined();
2070 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2071 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2072 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2073 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2075 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2076 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2077 throw INTERP_KERNEL::Exception(oss.str().c_str());
2079 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2080 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2082 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2083 throw INTERP_KERNEL::Exception(oss.str().c_str());
2085 int nbOfCells=getNumberOfCells();
2086 bool easyAssign=true;
2087 const int *connI=_nodal_connec_index->getConstPointer();
2088 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2090 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2092 if(it>=0 && it<nbOfCells)
2094 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2098 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2099 throw INTERP_KERNEL::Exception(oss.str().c_str());
2104 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2109 DataArrayInt *arrOut=0,*arrIOut=0;
2110 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2112 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2113 setConnectivity(arrOut,arrIOut,true);
2118 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2119 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2120 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2121 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2123 * \param [in] begin input start of array of node ids.
2124 * \param [in] end input end of array of node ids.
2125 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2126 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2128 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2130 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2131 checkConnectivityFullyDefined();
2133 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2134 std::vector<bool> fastFinder(sz,false);
2135 for(const int *work=begin;work!=end;work++)
2136 if(*work>=0 && *work<sz)
2137 fastFinder[*work]=true;
2138 int nbOfCells=getNumberOfCells();
2139 const int *conn=getNodalConnectivity()->getConstPointer();
2140 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2141 for(int i=0;i<nbOfCells;i++)
2143 int ref=0,nbOfHit=0;
2144 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2148 if(fastFinder[*work2])
2151 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2152 cellIdsKept->pushBackSilent(i);
2154 cellIdsKeptArr=cellIdsKept.retn();
2158 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2159 * this->getMeshDimension(), that bound some cells of \a this mesh.
2160 * The cells of lower dimension to include to the result mesh are selected basing on
2161 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2162 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2163 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2164 * created mesh shares the node coordinates array with \a this mesh.
2165 * \param [in] begin - the array of node ids.
2166 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2167 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2168 * array \a begin are added, else cells whose any node is in the
2169 * array \a begin are added.
2170 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2171 * to delete this mesh using decrRef() as it is no more needed.
2172 * \throw If the coordinates array is not set.
2173 * \throw If the nodal connectivity of cells is not defined.
2174 * \throw If any node id in \a begin is not valid.
2176 * \if ENABLE_EXAMPLES
2177 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2178 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2181 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2183 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2184 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2185 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2186 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2187 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2191 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2192 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2193 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2194 * array of \a this mesh, else "free" nodes are removed from the result mesh
2195 * by calling zipCoords().
2196 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2197 * to delete this mesh using decrRef() as it is no more needed.
2198 * \throw If the coordinates array is not set.
2199 * \throw If the nodal connectivity of cells is not defined.
2201 * \if ENABLE_EXAMPLES
2202 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2203 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2206 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2208 DataArrayInt *desc=DataArrayInt::New();
2209 DataArrayInt *descIndx=DataArrayInt::New();
2210 DataArrayInt *revDesc=DataArrayInt::New();
2211 DataArrayInt *revDescIndx=DataArrayInt::New();
2213 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2216 descIndx->decrRef();
2217 int nbOfCells=meshDM1->getNumberOfCells();
2218 const int *revDescIndxC=revDescIndx->getConstPointer();
2219 std::vector<int> boundaryCells;
2220 for(int i=0;i<nbOfCells;i++)
2221 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2222 boundaryCells.push_back(i);
2223 revDescIndx->decrRef();
2224 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2229 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2230 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2231 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2233 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const
2235 checkFullyDefined();
2236 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2237 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2238 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2239 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2241 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2242 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2244 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2245 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2246 const int *revDescPtr=revDesc->getConstPointer();
2247 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2248 int nbOfCells=getNumberOfCells();
2249 std::vector<bool> ret1(nbOfCells,false);
2251 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2252 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2253 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2255 DataArrayInt *ret2=DataArrayInt::New();
2257 int *ret2Ptr=ret2->getPointer();
2259 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2262 ret2->setName("BoundaryCells");
2267 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2268 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2269 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2270 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2272 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2273 * This method method returns cells ids set s = s1 + s2 where :
2275 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2276 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2278 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2279 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2281 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2282 * \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
2283 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2285 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const
2287 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2288 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2289 checkConnectivityFullyDefined();
2290 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2291 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2292 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2293 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2294 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2295 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2296 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2297 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2298 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2299 DataArrayInt *idsOtherInConsti=0;
2300 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2301 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2303 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2305 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2306 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2307 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2308 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2309 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2310 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2311 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2312 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2313 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2314 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2315 neighThisPartAuto=0;
2316 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2317 const int li[2]={0,1};
2318 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2319 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2320 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2323 cellIdsRk0=s0arr.retn();
2324 cellIdsRk1=s_renum1.retn();
2328 * 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
2329 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2331 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2333 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const
2335 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2336 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2337 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2338 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2340 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2341 revDesc=0; desc=0; descIndx=0;
2342 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2343 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2344 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2348 * Finds nodes lying on the boundary of \a this mesh.
2349 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2350 * nodes. The caller is to delete this array using decrRef() as it is no
2352 * \throw If the coordinates array is not set.
2353 * \throw If the nodal connectivity of cells is node defined.
2355 * \if ENABLE_EXAMPLES
2356 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2357 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2360 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2362 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2363 return skin->computeFetchedNodeIds();
2366 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const
2369 return const_cast<MEDCouplingUMesh *>(this);
2373 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2374 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2375 * 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.
2376 * 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.
2377 * 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.
2379 * \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
2380 * parameter is altered during the call.
2381 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2382 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2383 * \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.
2385 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2387 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2388 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2390 checkFullyDefined();
2391 otherDimM1OnSameCoords.checkFullyDefined();
2392 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2393 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2394 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2395 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2396 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2397 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2398 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2399 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2400 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2401 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2402 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2403 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2404 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2405 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2407 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2408 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2409 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2410 DataArrayInt *idsTmp=0;
2411 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2412 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2414 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2415 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2416 DataArrayInt *tmp0=0,*tmp1=0;
2417 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2418 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2419 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2420 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2421 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2422 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2423 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2425 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2426 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2427 nodeIdsToDuplicate=s3.retn();
2431 * This method operates a modification of the connectivity and coords in \b this.
2432 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2433 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2434 * 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
2435 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2436 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2438 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2440 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2441 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2443 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd)
2445 int nbOfNodes=getNumberOfNodes();
2446 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2447 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2451 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2452 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2453 * This method is a generalization of shiftNodeNumbersInConn().
2454 * \warning This method performs no check of validity of new ids. **Use it with care !**
2455 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2456 * this->getNumberOfNodes(), in "Old to New" mode.
2457 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2458 * \throw If the nodal connectivity of cells is not defined.
2460 * \if ENABLE_EXAMPLES
2461 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2462 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2465 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2467 checkConnectivityFullyDefined();
2468 int *conn=getNodalConnectivity()->getPointer();
2469 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2470 int nbOfCells=getNumberOfCells();
2471 for(int i=0;i<nbOfCells;i++)
2472 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2474 int& node=conn[iconn];
2475 if(node>=0)//avoid polyhedron separator
2477 node=newNodeNumbersO2N[node];
2480 _nodal_connec->declareAsNew();
2485 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2486 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2487 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2489 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2491 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta)
2493 checkConnectivityFullyDefined();
2494 int *conn=getNodalConnectivity()->getPointer();
2495 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2496 int nbOfCells=getNumberOfCells();
2497 for(int i=0;i<nbOfCells;i++)
2498 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2500 int& node=conn[iconn];
2501 if(node>=0)//avoid polyhedron separator
2506 _nodal_connec->declareAsNew();
2511 * This method operates a modification of the connectivity in \b this.
2512 * 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.
2513 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2514 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2515 * 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
2516 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2517 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2519 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2520 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2522 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2523 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2524 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2526 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset)
2528 checkConnectivityFullyDefined();
2529 std::map<int,int> m;
2531 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2533 int *conn=getNodalConnectivity()->getPointer();
2534 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2535 int nbOfCells=getNumberOfCells();
2536 for(int i=0;i<nbOfCells;i++)
2537 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2539 int& node=conn[iconn];
2540 if(node>=0)//avoid polyhedron separator
2542 std::map<int,int>::iterator it=m.find(node);
2551 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2553 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2554 * After the call of this method the number of cells remains the same as before.
2556 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2557 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2558 * be strictly in [0;this->getNumberOfCells()).
2560 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2561 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2562 * should be contained in[0;this->getNumberOfCells()).
2564 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2566 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check)
2568 checkConnectivityFullyDefined();
2569 int nbCells=getNumberOfCells();
2570 const int *array=old2NewBg;
2572 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2574 const int *conn=_nodal_connec->getConstPointer();
2575 const int *connI=_nodal_connec_index->getConstPointer();
2576 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2577 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2578 const int *n2oPtr=n2o->begin();
2579 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2580 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2581 newConn->copyStringInfoFrom(*_nodal_connec);
2582 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2583 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2584 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2586 int *newC=newConn->getPointer();
2587 int *newCI=newConnI->getPointer();
2590 for(int i=0;i<nbCells;i++)
2593 int nbOfElts=connI[pos+1]-connI[pos];
2594 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2599 setConnectivity(newConn,newConnI);
2601 free(const_cast<int *>(array));
2605 * Finds cells whose bounding boxes intersect a given bounding box.
2606 * \param [in] bbox - an array defining the bounding box via coordinates of its
2607 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2609 * \param [in] eps - a factor used to increase size of the bounding box of cell
2610 * before comparing it with \a bbox. This factor is multiplied by the maximal
2611 * extent of the bounding box of cell to produce an addition to this bounding box.
2612 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2613 * cells. The caller is to delete this array using decrRef() as it is no more
2615 * \throw If the coordinates array is not set.
2616 * \throw If the nodal connectivity of cells is not defined.
2618 * \if ENABLE_EXAMPLES
2619 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2620 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2623 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2625 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2626 if(getMeshDimension()==-1)
2628 elems->pushBackSilent(0);
2629 return elems.retn();
2631 int dim=getSpaceDimension();
2632 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2633 const int* conn = getNodalConnectivity()->getConstPointer();
2634 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2635 const double* coords = getCoords()->getConstPointer();
2636 int nbOfCells=getNumberOfCells();
2637 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2639 for (int i=0; i<dim; i++)
2641 elem_bb[i*2]=std::numeric_limits<double>::max();
2642 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2645 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2647 int node= conn[inode];
2648 if(node>=0)//avoid polyhedron separator
2650 for (int idim=0; idim<dim; idim++)
2652 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2654 elem_bb[idim*2] = coords[node*dim+idim] ;
2656 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2658 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2663 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2664 elems->pushBackSilent(ielem);
2666 return elems.retn();
2670 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2671 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2672 * added in 'elems' parameter.
2674 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2676 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2677 if(getMeshDimension()==-1)
2679 elems->pushBackSilent(0);
2680 return elems.retn();
2682 int dim=getSpaceDimension();
2683 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2684 const int* conn = getNodalConnectivity()->getConstPointer();
2685 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2686 const double* coords = getCoords()->getConstPointer();
2687 int nbOfCells=getNumberOfCells();
2688 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2690 for (int i=0; i<dim; i++)
2692 elem_bb[i*2]=std::numeric_limits<double>::max();
2693 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2696 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2698 int node= conn[inode];
2699 if(node>=0)//avoid polyhedron separator
2701 for (int idim=0; idim<dim; idim++)
2703 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2705 elem_bb[idim*2] = coords[node*dim+idim] ;
2707 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2709 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2714 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2715 elems->pushBackSilent(ielem);
2717 return elems.retn();
2721 * Returns a type of a cell by its id.
2722 * \param [in] cellId - the id of the cell of interest.
2723 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2724 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2726 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2728 const int *ptI=_nodal_connec_index->getConstPointer();
2729 const int *pt=_nodal_connec->getConstPointer();
2730 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2731 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2734 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2735 throw INTERP_KERNEL::Exception(oss.str().c_str());
2740 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2741 * This method does not throw exception if geometric type \a type is not in \a this.
2742 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2743 * The coordinates array is not considered here.
2745 * \param [in] type the geometric type
2746 * \return cell ids in this having geometric type \a type.
2748 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2751 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2753 checkConnectivityFullyDefined();
2754 int nbCells=getNumberOfCells();
2755 int mdim=getMeshDimension();
2756 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2757 if(mdim!=(int)cm.getDimension())
2758 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2759 const int *ptI=_nodal_connec_index->getConstPointer();
2760 const int *pt=_nodal_connec->getConstPointer();
2761 for(int i=0;i<nbCells;i++)
2763 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2764 ret->pushBackSilent(i);
2770 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2772 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2774 const int *ptI=_nodal_connec_index->getConstPointer();
2775 const int *pt=_nodal_connec->getConstPointer();
2776 int nbOfCells=getNumberOfCells();
2778 for(int i=0;i<nbOfCells;i++)
2779 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2785 * Returns the nodal connectivity of a given cell.
2786 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2787 * all returned node ids can be used in getCoordinatesOfNode().
2788 * \param [in] cellId - an id of the cell of interest.
2789 * \param [in,out] conn - a vector where the node ids are appended. It is not
2790 * cleared before the appending.
2791 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2793 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2795 const int *ptI=_nodal_connec_index->getConstPointer();
2796 const int *pt=_nodal_connec->getConstPointer();
2797 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2802 std::string MEDCouplingUMesh::simpleRepr() const
2804 static const char msg0[]="No coordinates specified !";
2805 std::ostringstream ret;
2806 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2807 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2809 double tt=getTime(tmpp1,tmpp2);
2810 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2811 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2813 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2815 { ret << " Mesh dimension has not been set or is invalid !"; }
2818 const int spaceDim=getSpaceDimension();
2819 ret << spaceDim << "\nInfo attached on space dimension : ";
2820 for(int i=0;i<spaceDim;i++)
2821 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2825 ret << msg0 << "\n";
2826 ret << "Number of nodes : ";
2828 ret << getNumberOfNodes() << "\n";
2830 ret << msg0 << "\n";
2831 ret << "Number of cells : ";
2832 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2833 ret << getNumberOfCells() << "\n";
2835 ret << "No connectivity specified !" << "\n";
2836 ret << "Cell types present : ";
2837 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2839 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2840 ret << cm.getRepr() << " ";
2846 std::string MEDCouplingUMesh::advancedRepr() const
2848 std::ostringstream ret;
2849 ret << simpleRepr();
2850 ret << "\nCoordinates array : \n___________________\n\n";
2852 _coords->reprWithoutNameStream(ret);
2854 ret << "No array set !\n";
2855 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2856 reprConnectivityOfThisLL(ret);
2861 * This method returns a C++ code that is a dump of \a this.
2862 * This method will throw if this is not fully defined.
2864 std::string MEDCouplingUMesh::cppRepr() const
2866 static const char coordsName[]="coords";
2867 static const char connName[]="conn";
2868 static const char connIName[]="connI";
2869 checkFullyDefined();
2870 std::ostringstream ret; ret << "// coordinates" << std::endl;
2871 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2872 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2873 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2874 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2875 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2876 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2877 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2881 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2883 std::ostringstream ret;
2884 reprConnectivityOfThisLL(ret);
2889 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2890 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2891 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2894 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2895 * 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
2896 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2898 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const
2900 int mdim=getMeshDimension();
2902 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2903 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2904 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2905 bool needToCpyCT=true;
2908 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2916 if(!_nodal_connec_index)
2918 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2923 tmp2=_nodal_connec_index;
2926 ret->setConnectivity(tmp1,tmp2,false);
2931 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2932 ret->setCoords(coords);
2935 ret->setCoords(_coords);
2939 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2941 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2943 int nbOfCells=getNumberOfCells();
2944 const int *c=_nodal_connec->getConstPointer();
2945 const int *ci=_nodal_connec_index->getConstPointer();
2946 for(int i=0;i<nbOfCells;i++)
2948 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2949 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2950 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2955 stream << "Connectivity not defined !\n";
2958 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2960 const int *ptI=_nodal_connec_index->getConstPointer();
2961 const int *pt=_nodal_connec->getConstPointer();
2962 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2963 return ptI[cellId+1]-ptI[cellId]-1;
2965 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2969 * Returns types of cells of the specified part of \a this mesh.
2970 * This method avoids computing sub-mesh explicitely to get its types.
2971 * \param [in] begin - an array of cell ids of interest.
2972 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2973 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2974 * describing the cell types.
2975 * \throw If the coordinates array is not set.
2976 * \throw If the nodal connectivity of cells is not defined.
2977 * \sa getAllGeoTypes()
2979 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const
2981 checkFullyDefined();
2982 std::set<INTERP_KERNEL::NormalizedCellType> ret;
2983 const int *conn=_nodal_connec->getConstPointer();
2984 const int *connIndex=_nodal_connec_index->getConstPointer();
2985 for(const int *w=begin;w!=end;w++)
2986 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2991 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2992 * a set of types of cells constituting \a this mesh.
2993 * This method is for advanced users having prepared their connectivity before. For
2994 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2995 * \param [in] conn - the nodal connectivity array.
2996 * \param [in] connIndex - the nodal connectivity index array.
2997 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
3000 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
3002 DataArrayInt::SetArrayIn(conn,_nodal_connec);
3003 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
3004 if(isComputingTypes)
3010 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
3011 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
3013 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
3014 _nodal_connec(0),_nodal_connec_index(0),
3015 _types(other._types)
3017 if(other._nodal_connec)
3018 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3019 if(other._nodal_connec_index)
3020 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3023 MEDCouplingUMesh::~MEDCouplingUMesh()
3026 _nodal_connec->decrRef();
3027 if(_nodal_connec_index)
3028 _nodal_connec_index->decrRef();
3032 * Recomputes a set of cell types of \a this mesh. For more info see
3033 * \ref MEDCouplingUMeshNodalConnectivity.
3035 void MEDCouplingUMesh::computeTypes()
3037 if(_nodal_connec && _nodal_connec_index)
3040 const int *conn=_nodal_connec->getConstPointer();
3041 const int *connIndex=_nodal_connec_index->getConstPointer();
3042 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3044 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3045 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3050 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3052 void MEDCouplingUMesh::checkFullyDefined() const
3054 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3055 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3059 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3061 void MEDCouplingUMesh::checkConnectivityFullyDefined() const
3063 if(!_nodal_connec_index || !_nodal_connec)
3064 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3068 * Returns a number of cells constituting \a this mesh.
3069 * \return int - the number of cells in \a this mesh.
3070 * \throw If the nodal connectivity of cells is not defined.
3072 int MEDCouplingUMesh::getNumberOfCells() const
3074 if(_nodal_connec_index)
3075 return _nodal_connec_index->getNumberOfTuples()-1;
3080 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3084 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3085 * mesh. For more info see \ref MEDCouplingMeshesPage.
3086 * \return int - the dimension of \a this mesh.
3087 * \throw If the mesh dimension is not defined using setMeshDimension().
3089 int MEDCouplingUMesh::getMeshDimension() const
3092 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3097 * Returns a length of the nodal connectivity array.
3098 * This method is for test reason. Normally the integer returned is not useable by
3099 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3100 * \return int - the length of the nodal connectivity array.
3102 int MEDCouplingUMesh::getMeshLength() const
3104 return _nodal_connec->getNbOfElems();
3108 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3110 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3112 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3113 tinyInfo.push_back(getMeshDimension());
3114 tinyInfo.push_back(getNumberOfCells());
3116 tinyInfo.push_back(getMeshLength());
3118 tinyInfo.push_back(-1);
3122 * First step of unserialization process.
3124 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3126 return tinyInfo[6]<=0;
3130 * Second step of serialization process.
3131 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3133 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3135 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3137 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3141 * Third and final step of serialization process.
3143 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3145 MEDCouplingPointSet::serialize(a1,a2);
3146 if(getMeshDimension()>-1)
3148 a1=DataArrayInt::New();
3149 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3150 int *ptA1=a1->getPointer();
3151 const int *conn=getNodalConnectivity()->getConstPointer();
3152 const int *index=getNodalConnectivityIndex()->getConstPointer();
3153 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3154 std::copy(conn,conn+getMeshLength(),ptA1);
3161 * Second and final unserialization process.
3162 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3164 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3166 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3167 setMeshDimension(tinyInfo[5]);
3171 const int *recvBuffer=a1->getConstPointer();
3172 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3173 myConnecIndex->alloc(tinyInfo[6]+1,1);
3174 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3175 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3176 myConnec->alloc(tinyInfo[7],1);
3177 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3178 setConnectivity(myConnec, myConnecIndex);
3183 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3184 * CellIds are given using range specified by a start an end and step.
3186 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3188 checkFullyDefined();
3189 int ncell=getNumberOfCells();
3190 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3191 ret->_mesh_dim=_mesh_dim;
3192 ret->setCoords(_coords);
3193 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3194 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3195 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3197 const int *conn=_nodal_connec->getConstPointer();
3198 const int *connIndex=_nodal_connec_index->getConstPointer();
3199 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3201 if(work>=0 && work<ncell)
3203 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3207 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3208 throw INTERP_KERNEL::Exception(oss.str().c_str());
3211 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3212 int *newConnPtr=newConn->getPointer();
3213 std::set<INTERP_KERNEL::NormalizedCellType> types;
3215 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3217 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3218 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3220 ret->setConnectivity(newConn,newConnI,false);
3222 ret->copyTinyInfoFrom(this);
3227 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3228 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3229 * The return newly allocated mesh will share the same coordinates as \a this.
3231 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3233 checkConnectivityFullyDefined();
3234 int ncell=getNumberOfCells();
3235 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3236 ret->_mesh_dim=_mesh_dim;
3237 ret->setCoords(_coords);
3238 std::size_t nbOfElemsRet=std::distance(begin,end);
3239 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3241 const int *conn=_nodal_connec->getConstPointer();
3242 const int *connIndex=_nodal_connec_index->getConstPointer();
3244 for(const int *work=begin;work!=end;work++,newNbring++)
3246 if(*work>=0 && *work<ncell)
3247 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3251 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3252 throw INTERP_KERNEL::Exception(oss.str().c_str());
3255 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3256 int *connRetWork=connRet;
3257 std::set<INTERP_KERNEL::NormalizedCellType> types;
3258 for(const int *work=begin;work!=end;work++)
3260 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3261 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3263 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3264 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3265 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3266 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3267 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3269 ret->copyTinyInfoFrom(this);
3274 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3276 * For 1D cells, the returned field contains lengths.<br>
3277 * For 2D cells, the returned field contains areas.<br>
3278 * For 3D cells, the returned field contains volumes.
3279 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3280 * orientation, i.e. the volume is always positive.
3281 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3282 * and one time . The caller is to delete this field using decrRef() as it is no
3285 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3287 std::string name="MeasureOfMesh_";
3289 int nbelem=getNumberOfCells();
3290 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3291 field->setName(name);
3292 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3293 array->alloc(nbelem,1);
3294 double *area_vol=array->getPointer();
3295 field->setArray(array) ; array=0;
3296 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3297 field->synchronizeTimeWithMesh();
3298 if(getMeshDimension()!=-1)
3301 INTERP_KERNEL::NormalizedCellType type;
3302 int dim_space=getSpaceDimension();
3303 const double *coords=getCoords()->getConstPointer();
3304 const int *connec=getNodalConnectivity()->getConstPointer();
3305 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3306 for(int iel=0;iel<nbelem;iel++)
3308 ipt=connec_index[iel];
3309 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3310 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);
3313 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3317 area_vol[0]=std::numeric_limits<double>::max();
3319 return field.retn();
3323 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3325 * For 1D cells, the returned array contains lengths.<br>
3326 * For 2D cells, the returned array contains areas.<br>
3327 * For 3D cells, the returned array contains volumes.
3328 * This method avoids building explicitly a part of \a this mesh to perform the work.
3329 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3330 * orientation, i.e. the volume is always positive.
3331 * \param [in] begin - an array of cell ids of interest.
3332 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3333 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3334 * delete this array using decrRef() as it is no more needed.
3336 * \if ENABLE_EXAMPLES
3337 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3338 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3340 * \sa getMeasureField()
3342 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3344 std::string name="PartMeasureOfMesh_";
3346 int nbelem=(int)std::distance(begin,end);
3347 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3348 array->setName(name);
3349 array->alloc(nbelem,1);
3350 double *area_vol=array->getPointer();
3351 if(getMeshDimension()!=-1)
3354 INTERP_KERNEL::NormalizedCellType type;
3355 int dim_space=getSpaceDimension();
3356 const double *coords=getCoords()->getConstPointer();
3357 const int *connec=getNodalConnectivity()->getConstPointer();
3358 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3359 for(const int *iel=begin;iel!=end;iel++)
3361 ipt=connec_index[*iel];
3362 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3363 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3366 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3370 area_vol[0]=std::numeric_limits<double>::max();
3372 return array.retn();
3376 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3377 * \a this one. The returned field contains the dual cell volume for each corresponding
3378 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3379 * the dual mesh in P1 sens of \a this.<br>
3380 * For 1D cells, the returned field contains lengths.<br>
3381 * For 2D cells, the returned field contains areas.<br>
3382 * For 3D cells, the returned field contains volumes.
3383 * This method is useful to check "P1*" conservative interpolators.
3384 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3385 * orientation, i.e. the volume is always positive.
3386 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3387 * nodes and one time. The caller is to delete this array using decrRef() as
3388 * it is no more needed.
3390 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3392 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3393 std::string name="MeasureOnNodeOfMesh_";
3395 int nbNodes=getNumberOfNodes();
3396 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3397 double cst=1./((double)getMeshDimension()+1.);
3398 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3399 array->alloc(nbNodes,1);
3400 double *valsToFill=array->getPointer();
3401 std::fill(valsToFill,valsToFill+nbNodes,0.);
3402 const double *values=tmp->getArray()->getConstPointer();
3403 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3404 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3405 getReverseNodalConnectivity(da,daInd);
3406 const int *daPtr=da->getConstPointer();
3407 const int *daIPtr=daInd->getConstPointer();
3408 for(int i=0;i<nbNodes;i++)
3409 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3410 valsToFill[i]+=cst*values[*cell];
3412 ret->setArray(array);
3417 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3418 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3419 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3420 * and are normalized.
3421 * <br> \a this can be either
3422 * - a 2D mesh in 2D or 3D space or
3423 * - an 1D mesh in 2D space.
3425 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3426 * cells and one time. The caller is to delete this field using decrRef() as
3427 * it is no more needed.
3428 * \throw If the nodal connectivity of cells is not defined.
3429 * \throw If the coordinates array is not set.
3430 * \throw If the mesh dimension is not set.
3431 * \throw If the mesh and space dimension is not as specified above.
3433 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3435 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3436 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3437 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3438 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3439 int nbOfCells=getNumberOfCells();
3440 int nbComp=getMeshDimension()+1;
3441 array->alloc(nbOfCells,nbComp);
3442 double *vals=array->getPointer();
3443 const int *connI=_nodal_connec_index->getConstPointer();
3444 const int *conn=_nodal_connec->getConstPointer();
3445 const double *coords=_coords->getConstPointer();
3446 if(getMeshDimension()==2)
3448 if(getSpaceDimension()==3)
3450 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3451 const double *locPtr=loc->getConstPointer();
3452 for(int i=0;i<nbOfCells;i++,vals+=3)
3454 int offset=connI[i];
3455 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3456 double n=INTERP_KERNEL::norm<3>(vals);
3457 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3462 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3463 const double *isAbsPtr=isAbs->getArray()->begin();
3464 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3465 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3468 else//meshdimension==1
3471 for(int i=0;i<nbOfCells;i++)
3473 int offset=connI[i];
3474 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3475 double n=INTERP_KERNEL::norm<2>(tmp);
3476 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3481 ret->setArray(array);
3483 ret->synchronizeTimeWithSupport();
3488 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3489 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3490 * and are normalized.
3491 * <br> \a this can be either
3492 * - a 2D mesh in 2D or 3D space or
3493 * - an 1D mesh in 2D space.
3495 * This method avoids building explicitly a part of \a this mesh to perform the work.
3496 * \param [in] begin - an array of cell ids of interest.
3497 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3498 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3499 * cells and one time. The caller is to delete this field using decrRef() as
3500 * it is no more needed.
3501 * \throw If the nodal connectivity of cells is not defined.
3502 * \throw If the coordinates array is not set.
3503 * \throw If the mesh dimension is not set.
3504 * \throw If the mesh and space dimension is not as specified above.
3505 * \sa buildOrthogonalField()
3507 * \if ENABLE_EXAMPLES
3508 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3509 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3512 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3514 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3515 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3516 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3517 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3518 std::size_t nbelems=std::distance(begin,end);
3519 int nbComp=getMeshDimension()+1;
3520 array->alloc((int)nbelems,nbComp);
3521 double *vals=array->getPointer();
3522 const int *connI=_nodal_connec_index->getConstPointer();
3523 const int *conn=_nodal_connec->getConstPointer();
3524 const double *coords=_coords->getConstPointer();
3525 if(getMeshDimension()==2)
3527 if(getSpaceDimension()==3)
3529 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3530 const double *locPtr=loc->getConstPointer();
3531 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3533 int offset=connI[*i];
3534 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3535 double n=INTERP_KERNEL::norm<3>(vals);
3536 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3541 for(std::size_t i=0;i<nbelems;i++)
3542 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3545 else//meshdimension==1
3548 for(const int *i=begin;i!=end;i++)
3550 int offset=connI[*i];
3551 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3552 double n=INTERP_KERNEL::norm<2>(tmp);
3553 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3558 ret->setArray(array);
3560 ret->synchronizeTimeWithSupport();
3565 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3566 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3567 * and are \b not normalized.
3568 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3569 * cells and one time. The caller is to delete this field using decrRef() as
3570 * it is no more needed.
3571 * \throw If the nodal connectivity of cells is not defined.
3572 * \throw If the coordinates array is not set.
3573 * \throw If \a this->getMeshDimension() != 1.
3574 * \throw If \a this mesh includes cells of type other than SEG2.
3576 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3578 if(getMeshDimension()!=1)
3579 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3580 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3581 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3582 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3583 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3584 int nbOfCells=getNumberOfCells();
3585 int spaceDim=getSpaceDimension();
3586 array->alloc(nbOfCells,spaceDim);
3587 double *pt=array->getPointer();
3588 const double *coo=getCoords()->getConstPointer();
3589 std::vector<int> conn;
3591 for(int i=0;i<nbOfCells;i++)
3594 getNodeIdsOfCell(i,conn);
3595 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3597 ret->setArray(array);
3599 ret->synchronizeTimeWithSupport();
3604 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3605 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3606 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3607 * from. If a result face is shared by two 3D cells, then the face in included twice in
3609 * \param [in] origin - 3 components of a point defining location of the plane.
3610 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3611 * must be greater than 1e-6.
3612 * \param [in] eps - half-thickness of the plane.
3613 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3614 * producing correspondent 2D cells. The caller is to delete this array
3615 * using decrRef() as it is no more needed.
3616 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3617 * not share the node coordinates array with \a this mesh. The caller is to
3618 * delete this mesh using decrRef() as it is no more needed.
3619 * \throw If the coordinates array is not set.
3620 * \throw If the nodal connectivity of cells is not defined.
3621 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3622 * \throw If magnitude of \a vec is less than 1e-6.
3623 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3624 * \throw If \a this includes quadratic cells.
3626 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3628 checkFullyDefined();
3629 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3630 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3631 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3632 if(candidates->empty())
3633 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3634 std::vector<int> nodes;
3635 DataArrayInt *cellIds1D=0;
3636 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3637 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3638 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3639 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3640 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3641 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3642 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3643 revDesc2=0; revDescIndx2=0;
3644 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3645 revDesc1=0; revDescIndx1=0;
3646 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3647 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3649 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3650 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3652 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3653 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3654 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3655 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3656 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3657 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3658 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3659 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3660 if(cellIds2->empty())
3661 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3662 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3663 ret->setCoords(mDesc1->getCoords());
3664 ret->setConnectivity(conn,connI,true);
3665 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3670 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3671 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
3672 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3674 * \param [in] origin - 3 components of a point defining location of the plane.
3675 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3676 * must be greater than 1e-6.
3677 * \param [in] eps - half-thickness of the plane.
3678 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3679 * producing correspondent segments. The caller is to delete this array
3680 * using decrRef() as it is no more needed.
3681 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3682 * mesh in 3D space. This mesh does not share the node coordinates array with
3683 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3685 * \throw If the coordinates array is not set.
3686 * \throw If the nodal connectivity of cells is not defined.
3687 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3688 * \throw If magnitude of \a vec is less than 1e-6.
3689 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3690 * \throw If \a this includes quadratic cells.
3692 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const
3694 checkFullyDefined();
3695 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3696 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3697 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3698 if(candidates->empty())
3699 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3700 std::vector<int> nodes;
3701 DataArrayInt *cellIds1D=0;
3702 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3703 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3704 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3705 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3706 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3707 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3708 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3709 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3710 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3712 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3713 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3715 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3716 int ncellsSub=subMesh->getNumberOfCells();
3717 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3718 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3719 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3720 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3721 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3723 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3724 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3725 for(int i=0;i<ncellsSub;i++)
3727 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3729 if(cut3DSurf[i].first!=-2)
3731 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3732 connI->pushBackSilent(conn->getNumberOfTuples());
3733 cellIds2->pushBackSilent(i);
3737 int cellId3DSurf=cut3DSurf[i].second;
3738 int offset=nodalI[cellId3DSurf]+1;
3739 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3740 for(int j=0;j<nbOfEdges;j++)
3742 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3743 connI->pushBackSilent(conn->getNumberOfTuples());
3744 cellIds2->pushBackSilent(cellId3DSurf);
3749 if(cellIds2->empty())
3750 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3751 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3752 ret->setCoords(mDesc1->getCoords());
3753 ret->setConnectivity(conn,connI,true);
3754 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3759 * Finds cells whose bounding boxes intersect a given plane.
3760 * \param [in] origin - 3 components of a point defining location of the plane.
3761 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3762 * must be greater than 1e-6.
3763 * \param [in] eps - half-thickness of the plane.
3764 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3765 * cells. The caller is to delete this array using decrRef() as it is no more
3767 * \throw If the coordinates array is not set.
3768 * \throw If the nodal connectivity of cells is not defined.
3769 * \throw If \a this->getSpaceDimension() != 3.
3770 * \throw If magnitude of \a vec is less than 1e-6.
3771 * \sa buildSlice3D()
3773 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const
3775 checkFullyDefined();
3776 if(getSpaceDimension()!=3)
3777 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3778 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3780 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3782 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3783 double angle=acos(vec[2]/normm);
3784 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3788 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3789 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3790 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3792 mw->getBoundingBox(bbox);
3793 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3794 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3798 getBoundingBox(bbox);
3799 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3800 cellIds=getCellsInBoundingBox(bbox,eps);
3802 return cellIds.retn();
3806 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3807 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3808 * No consideration of coordinate is done by this method.
3809 * 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)
3810 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3812 bool MEDCouplingUMesh::isContiguous1D() const
3814 if(getMeshDimension()!=1)
3815 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3816 int nbCells=getNumberOfCells();
3818 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3819 const int *connI=_nodal_connec_index->getConstPointer();
3820 const int *conn=_nodal_connec->getConstPointer();
3821 int ref=conn[connI[0]+2];
3822 for(int i=1;i<nbCells;i++)
3824 if(conn[connI[i]+1]!=ref)
3826 ref=conn[connI[i]+2];
3832 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3833 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3834 * \param pt reference point of the line
3835 * \param v normalized director vector of the line
3836 * \param eps max precision before throwing an exception
3837 * \param res output of size this->getNumberOfCells
3839 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3841 if(getMeshDimension()!=1)
3842 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3843 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3844 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3845 if(getSpaceDimension()!=3)
3846 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3847 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3848 const double *fPtr=f->getArray()->getConstPointer();
3850 for(int i=0;i<getNumberOfCells();i++)
3852 const double *tmp1=fPtr+3*i;
3853 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3854 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3855 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3856 double n1=INTERP_KERNEL::norm<3>(tmp);
3857 n1/=INTERP_KERNEL::norm<3>(tmp1);
3859 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3861 const double *coo=getCoords()->getConstPointer();
3862 for(int i=0;i<getNumberOfNodes();i++)
3864 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3865 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3866 res[i]=std::accumulate(tmp,tmp+3,0.);
3871 * 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.
3872 * \a this is expected to be a mesh so that its space dimension is equal to its
3873 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3874 * 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).
3876 * 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
3877 * 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).
3878 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3880 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3881 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3883 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3884 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3885 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3886 * \return the positive value of the distance.
3887 * \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
3889 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3891 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const
3893 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3894 if(meshDim!=spaceDim-1)
3895 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3896 if(meshDim!=2 && meshDim!=1)
3897 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3898 checkFullyDefined();
3899 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3900 { 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()); }
3901 DataArrayInt *ret1=0;
3902 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3903 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3904 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3905 cellId=*ret1Safe->begin();
3906 return *ret0->begin();
3910 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3911 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
3912 * 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
3913 * 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).
3914 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3916 * \a this is expected to be a mesh so that its space dimension is equal to its
3917 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3918 * 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).
3920 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3921 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3923 * \param [in] pts the list of points in which each tuple represents a point
3924 * \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.
3925 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3926 * \throw if number of components of \a pts is not equal to the space dimension.
3927 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3928 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3930 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const
3933 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3934 pts->checkAllocated();
3935 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3936 if(meshDim!=spaceDim-1)
3937 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3938 if(meshDim!=2 && meshDim!=1)
3939 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3940 if(pts->getNumberOfComponents()!=spaceDim)
3942 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3943 throw INTERP_KERNEL::Exception(oss.str().c_str());
3945 checkFullyDefined();
3946 int nbCells=getNumberOfCells();
3948 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3949 int nbOfPts=pts->getNumberOfTuples();
3950 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3951 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3952 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3953 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3954 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3955 const double *bbox(bboxArr->begin());
3960 BBTreeDst<3> myTree(bbox,0,0,nbCells);
3961 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3963 double x=std::numeric_limits<double>::max();
3964 std::vector<int> elems;
3965 myTree.getMinDistanceOfMax(ptsPtr,x);
3966 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3967 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3973 BBTreeDst<2> myTree(bbox,0,0,nbCells);
3974 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3976 double x=std::numeric_limits<double>::max();
3977 std::vector<int> elems;
3978 myTree.getMinDistanceOfMax(ptsPtr,x);
3979 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3980 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3985 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3987 cellIds=ret1.retn();
3992 * \param [in] pt the start pointer (included) of the coordinates of the point
3993 * \param [in] cellIdsBg the start pointer (included) of cellIds
3994 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3995 * \param [in] nc nodal connectivity
3996 * \param [in] ncI nodal connectivity index
3997 * \param [in,out] ret0 the min distance between \a this and the external input point
3998 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3999 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4001 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)
4004 ret0=std::numeric_limits<double>::max();
4005 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4007 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4009 case INTERP_KERNEL::NORM_TRI3:
4011 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
4013 { ret0=tmp; cellId=*zeCell; }
4016 case INTERP_KERNEL::NORM_QUAD4:
4017 case INTERP_KERNEL::NORM_POLYGON:
4019 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4021 { ret0=tmp; cellId=*zeCell; }
4025 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4031 * \param [in] pt the start pointer (included) of the coordinates of the point
4032 * \param [in] cellIdsBg the start pointer (included) of cellIds
4033 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4034 * \param [in] nc nodal connectivity
4035 * \param [in] ncI nodal connectivity index
4036 * \param [in,out] ret0 the min distance between \a this and the external input point
4037 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4038 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4040 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)
4043 ret0=std::numeric_limits<double>::max();
4044 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4046 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4048 case INTERP_KERNEL::NORM_SEG2:
4050 std::size_t uselessEntry=0;
4051 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4054 { ret0=tmp; cellId=*zeCell; }
4058 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4064 * Finds cells in contact with a ball (i.e. a point with precision).
4065 * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4066 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4068 * \warning This method is suitable if the caller intends to evaluate only one
4069 * point, for more points getCellsContainingPoints() is recommended as it is
4071 * \param [in] pos - array of coordinates of the ball central point.
4072 * \param [in] eps - ball radius.
4073 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4074 * if there are no such cells.
4075 * \throw If the coordinates array is not set.
4076 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4078 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4080 std::vector<int> elts;
4081 getCellsContainingPoint(pos,eps,elts);
4084 return elts.front();
4088 * Finds cells in contact with a ball (i.e. a point with precision).
4089 * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4090 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4091 * \warning This method is suitable if the caller intends to evaluate only one
4092 * point, for more points getCellsContainingPoints() is recommended as it is
4094 * \param [in] pos - array of coordinates of the ball central point.
4095 * \param [in] eps - ball radius.
4096 * \param [out] elts - vector returning ids of the found cells. It is cleared
4097 * before inserting ids.
4098 * \throw If the coordinates array is not set.
4099 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4101 * \if ENABLE_EXAMPLES
4102 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4103 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4106 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4108 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> eltsUg,eltsIndexUg;
4109 getCellsContainingPoints(pos,1,eps,eltsUg,eltsIndexUg);
4110 elts.clear(); elts.insert(elts.end(),eltsUg->begin(),eltsUg->end());
4115 namespace ParaMEDMEM
4117 template<const int SPACEDIMM>
4121 static const int MY_SPACEDIM=SPACEDIMM;
4122 static const int MY_MESHDIM=8;
4123 typedef int MyConnType;
4124 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4126 // useless, but for windows compilation ...
4127 const double* getCoordinatesPtr() const { return 0; }
4128 const int* getConnectivityPtr() const { return 0; }
4129 const int* getConnectivityIndexPtr() const { return 0; }
4130 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4135 * Warning the nodes in \a m should be decrRefed ! To avoid that Node * pointer be replaced by another instance.
4137 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge2(INTERP_KERNEL::NormalizedCellType typ, const int *bg, const double *coords2D, std::map<INTERP_KERNEL::Node *,int>& m)
4139 INTERP_KERNEL::Edge *ret=0;
4140 INTERP_KERNEL::Node *n0(new INTERP_KERNEL::Node(coords2D[2*bg[0]],coords2D[2*bg[0]+1])),*n1(new INTERP_KERNEL::Node(coords2D[2*bg[1]],coords2D[2*bg[1]+1]));
4141 m[n0]=bg[0]; m[n1]=bg[1];
4144 case INTERP_KERNEL::NORM_SEG2:
4146 ret=new INTERP_KERNEL::EdgeLin(n0,n1);
4149 case INTERP_KERNEL::NORM_SEG3:
4151 INTERP_KERNEL::Node *n2(new INTERP_KERNEL::Node(coords2D[2*bg[2]],coords2D[2*bg[2]+1])); m[n2]=bg[2];
4152 INTERP_KERNEL::EdgeLin *e1(new INTERP_KERNEL::EdgeLin(n0,n2)),*e2(new INTERP_KERNEL::EdgeLin(n2,n1));
4153 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4154 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4155 bool colinearity(inters.areColinears());
4156 delete e1; delete e2;
4158 { ret=new INTERP_KERNEL::EdgeLin(n0,n1); }
4160 { ret=new INTERP_KERNEL::EdgeArcCircle(n0,n2,n1); }
4164 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge2 : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4169 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4171 INTERP_KERNEL::Edge *ret=0;
4174 case INTERP_KERNEL::NORM_SEG2:
4176 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4179 case INTERP_KERNEL::NORM_SEG3:
4181 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4182 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4183 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4184 // is the SEG3 degenerated, and thus can be reduced to a SEG2?
4185 bool colinearity=inters.areColinears();
4186 delete e1; delete e2;
4188 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4190 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4191 mapp2[bg[2]].second=false;
4195 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4201 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed by the sub set of cells in 'candidates' taken from
4202 * the global mesh 'mDesc'.
4203 * The input mesh 'mDesc' must be so that mDim==1 and spaceDim==2.
4204 * 'mapp' returns a mapping between local numbering in submesh (represented by a Node*) and the global node numbering in 'mDesc'.
4206 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates,
4207 std::map<INTERP_KERNEL::Node *,int>& mapp)
4208 throw(INTERP_KERNEL::Exception)
4211 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.
4212 const double *coo=mDesc->getCoords()->getConstPointer();
4213 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4214 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4216 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4217 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4218 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4220 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4221 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4223 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4224 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4226 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4227 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4229 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4231 if((*it2).second.second)
4232 mapp[(*it2).second.first]=(*it2).first;
4233 ((*it2).second.first)->decrRef();
4238 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4242 int locId=nodeId-offset2;
4243 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4247 int locId=nodeId-offset1;
4248 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4250 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4254 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4256 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4257 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4258 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4260 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4262 int eltId1=abs(*desc1)-1;
4263 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4265 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4266 if(it==mappRev.end())
4268 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4279 template<int SPACEDIM>
4280 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4281 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4283 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4284 int *eltsIndexPtr(eltsIndex->getPointer());
4285 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4286 const double *bbox(bboxArr->begin());
4287 int nbOfCells=getNumberOfCells();
4288 const int *conn=_nodal_connec->getConstPointer();
4289 const int *connI=_nodal_connec_index->getConstPointer();
4290 double bb[2*SPACEDIM];
4291 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4292 for(int i=0;i<nbOfPoints;i++)
4294 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4295 for(int j=0;j<SPACEDIM;j++)
4297 bb[2*j]=pos[SPACEDIM*i+j];
4298 bb[2*j+1]=pos[SPACEDIM*i+j];
4300 std::vector<int> candidates;
4301 myTree.getIntersectingElems(bb,candidates);
4302 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4304 int sz(connI[(*iter)+1]-connI[*iter]-1);
4305 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4307 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4308 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4312 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4313 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4314 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4315 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4316 INTERP_KERNEL::QuadraticPolygon *pol(0);
4317 for(int j=0;j<sz;j++)
4319 int nodeId(conn[connI[*iter]+1+j]);
4320 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4322 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4323 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4325 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4326 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4327 double a(0.),b(0.),c(0.);
4328 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4329 status=pol->isInOrOut2(n);
4330 delete pol; n->decrRef();
4334 eltsIndexPtr[i+1]++;
4335 elts->pushBackSilent(*iter);
4341 * Finds cells in contact with several balls (i.e. points with precision).
4342 * This method is an extension of getCellContainingPoint() and
4343 * getCellsContainingPoint() for the case of multiple points.
4344 * For speed reasons, the INTERP_KERNEL::NORM_QUAD4, INTERP_KERNEL::NORM_TRI6 and INTERP_KERNEL::NORM_QUAD8 cells are considered as convex cells to detect if a point is IN or OUT.
4345 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4346 * \param [in] pos - an array of coordinates of points in full interlace mode :
4347 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4348 * this->getSpaceDimension() * \a nbOfPoints
4349 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4350 * \param [in] eps - radius of balls (i.e. the precision).
4351 * \param [out] elts - vector returning ids of found cells.
4352 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4353 * dividing cell ids in \a elts into groups each referring to one
4354 * point. Its every element (except the last one) is an index pointing to the
4355 * first id of a group of cells. For example cells in contact with the *i*-th
4356 * point are described by following range of indices:
4357 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4358 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4359 * Number of cells in contact with the *i*-th point is
4360 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4361 * \throw If the coordinates array is not set.
4362 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4364 * \if ENABLE_EXAMPLES
4365 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4366 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4369 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4370 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4372 int spaceDim=getSpaceDimension();
4373 int mDim=getMeshDimension();
4378 const double *coords=_coords->getConstPointer();
4379 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4386 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4388 else if(spaceDim==2)
4392 const double *coords=_coords->getConstPointer();
4393 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4396 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4398 else if(spaceDim==1)
4402 const double *coords=_coords->getConstPointer();
4403 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4406 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4409 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4413 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4414 * least two its edges intersect each other anywhere except their extremities. An
4415 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4416 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4417 * cleared before filling in.
4418 * \param [in] eps - precision.
4419 * \throw If \a this->getMeshDimension() != 2.
4420 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4422 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4424 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4425 if(getMeshDimension()!=2)
4426 throw INTERP_KERNEL::Exception(msg);
4427 int spaceDim=getSpaceDimension();
4428 if(spaceDim!=2 && spaceDim!=3)
4429 throw INTERP_KERNEL::Exception(msg);
4430 const int *conn=_nodal_connec->getConstPointer();
4431 const int *connI=_nodal_connec_index->getConstPointer();
4432 int nbOfCells=getNumberOfCells();
4433 std::vector<double> cell2DinS2;
4434 for(int i=0;i<nbOfCells;i++)
4436 int offset=connI[i];
4437 int nbOfNodesForCell=connI[i+1]-offset-1;
4438 if(nbOfNodesForCell<=3)
4440 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4441 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4442 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4449 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4451 * 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.
4452 * 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.
4454 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4455 * This convex envelop is computed using Jarvis march algorithm.
4456 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4457 * 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)
4458 * 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.
4460 * \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.
4462 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D()
4464 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4465 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4466 checkFullyDefined();
4467 const double *coords=getCoords()->getConstPointer();
4468 int nbOfCells=getNumberOfCells();
4469 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4470 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4471 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4472 int *workIndexOut=nodalConnecIndexOut->getPointer();
4474 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4475 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4476 std::set<INTERP_KERNEL::NormalizedCellType> types;
4477 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4478 isChanged->alloc(0,1);
4479 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4481 int pos=nodalConnecOut->getNumberOfTuples();
4482 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4483 isChanged->pushBackSilent(i);
4484 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4485 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4487 if(isChanged->empty())
4489 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4491 return isChanged.retn();
4495 * This method is \b NOT const because it can modify \a this.
4496 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4497 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4498 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4499 * \b 1 for translation and rotation around point of 'mesh1D'.
4500 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4502 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4504 checkFullyDefined();
4505 mesh1D->checkFullyDefined();
4506 if(!mesh1D->isContiguous1D())
4507 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4508 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4509 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4510 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4511 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4512 if(mesh1D->getMeshDimension()!=1)
4513 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4515 if(isPresenceOfQuadratic())
4517 if(mesh1D->isFullyQuadratic())
4520 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4523 int oldNbOfNodes=getNumberOfNodes();
4524 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4529 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4534 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4538 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4540 setCoords(newCoords);
4541 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4547 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4548 * If it is not the case an exception will be thrown.
4549 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4550 * intersection of plane defined by ('origin','vec').
4551 * This method has one in/out parameter : 'cut3DCurve'.
4552 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4553 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4554 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4555 * This method will throw an exception if \a this contains a non linear segment.
4557 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve)
4559 checkFullyDefined();
4560 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4561 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4562 int ncells=getNumberOfCells();
4563 int nnodes=getNumberOfNodes();
4564 double vec2[3],vec3[3],vec4[3];
4565 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4567 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4568 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4569 const int *conn=_nodal_connec->getConstPointer();
4570 const int *connI=_nodal_connec_index->getConstPointer();
4571 const double *coo=_coords->getConstPointer();
4572 std::vector<double> addCoo;
4573 for(int i=0;i<ncells;i++)
4575 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4577 if(cut3DCurve[i]==-2)
4579 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4580 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];
4581 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4582 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4583 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4585 const double *st2=coo+3*st;
4586 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4587 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]));
4588 if(pos>eps && pos<1-eps)
4590 int nNode=((int)addCoo.size())/3;
4591 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4592 addCoo.insert(addCoo.end(),vec4,vec4+3);
4593 cut3DCurve[i]=nnodes+nNode;
4599 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4603 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4604 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4605 coo2->alloc(newNbOfNodes,3);
4606 double *tmp=coo2->getPointer();
4607 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4608 std::copy(addCoo.begin(),addCoo.end(),tmp);
4609 DataArrayDouble::SetArrayIn(coo2,_coords);
4614 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4615 * \param mesh1D is the input 1D mesh used for translation computation.
4616 * \return newCoords new coords filled by this method.
4618 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4620 int oldNbOfNodes=getNumberOfNodes();
4621 int nbOf1DCells=mesh1D->getNumberOfCells();
4622 int spaceDim=getSpaceDimension();
4623 DataArrayDouble *ret=DataArrayDouble::New();
4624 std::vector<bool> isQuads;
4625 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4626 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4627 double *retPtr=ret->getPointer();
4628 const double *coords=getCoords()->getConstPointer();
4629 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4631 std::vector<double> c;
4635 for(int i=0;i<nbOf1DCells;i++)
4638 mesh1D->getNodeIdsOfCell(i,v);
4640 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4641 mesh1D->getCoordinatesOfNode(v[0],c);
4642 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4643 for(int j=0;j<oldNbOfNodes;j++)
4644 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4648 mesh1D->getCoordinatesOfNode(v[1],c);
4649 mesh1D->getCoordinatesOfNode(v[0],c);
4650 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4651 for(int j=0;j<oldNbOfNodes;j++)
4652 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4655 ret->copyStringInfoFrom(*getCoords());
4660 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4661 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4662 * \return newCoords new coords filled by this method.
4664 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4666 if(mesh1D->getSpaceDimension()==2)
4667 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4668 if(mesh1D->getSpaceDimension()==3)
4669 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4670 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4674 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4675 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4676 * \return newCoords new coords filled by this method.
4678 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4681 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4682 int oldNbOfNodes=getNumberOfNodes();
4683 int nbOf1DCells=mesh1D->getNumberOfCells();
4685 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4686 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4687 int nbOfLevsInVec=nbOf1DCells+1;
4688 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4689 double *retPtr=ret->getPointer();
4690 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4691 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4692 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4693 tmp->setCoords(tmp2);
4694 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4695 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4696 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4697 for(int i=1;i<nbOfLevsInVec;i++)
4699 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4700 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4701 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4702 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4703 tmp->translate(vec);
4704 double tmp3[2],radius,alpha,alpha0;
4705 const double *p0=i+1<nbOfLevsInVec?begin:third;
4706 const double *p1=i+1<nbOfLevsInVec?end:begin;
4707 const double *p2=i+1<nbOfLevsInVec?third:end;
4708 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4709 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]);
4710 double angle=acos(cosangle/(radius*radius));
4711 tmp->rotate(end,0,angle);
4712 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4718 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4719 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4720 * \return newCoords new coords filled by this method.
4722 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4725 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4726 int oldNbOfNodes=getNumberOfNodes();
4727 int nbOf1DCells=mesh1D->getNumberOfCells();
4729 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4730 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4731 int nbOfLevsInVec=nbOf1DCells+1;
4732 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4733 double *retPtr=ret->getPointer();
4734 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4735 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4736 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4737 tmp->setCoords(tmp2);
4738 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4739 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4740 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4741 for(int i=1;i<nbOfLevsInVec;i++)
4743 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4744 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4745 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4746 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4747 tmp->translate(vec);
4748 double tmp3[2],radius,alpha,alpha0;
4749 const double *p0=i+1<nbOfLevsInVec?begin:third;
4750 const double *p1=i+1<nbOfLevsInVec?end:begin;
4751 const double *p2=i+1<nbOfLevsInVec?third:end;
4752 double vecPlane[3]={
4753 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4754 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4755 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4757 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4760 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4761 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4762 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4764 double c2=cos(asin(s2));
4766 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4767 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4768 {-vec2[1]*s2, vec2[0]*s2, c2}
4770 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]};
4771 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]};
4772 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]};
4773 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4774 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]);
4775 double angle=acos(cosangle/(radius*radius));
4776 tmp->rotate(end,vecPlane,angle);
4779 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4785 * This method is private because not easy to use for end user. This method is const contrary to
4786 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4787 * the coords sorted slice by slice.
4788 * \param isQuad specifies presence of quadratic cells.
4790 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4792 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4793 int nbOf2DCells=getNumberOfCells();
4794 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4795 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4796 const int *conn=_nodal_connec->getConstPointer();
4797 const int *connI=_nodal_connec_index->getConstPointer();
4798 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4799 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4800 newConnI->alloc(nbOf3DCells+1,1);
4801 int *newConnIPtr=newConnI->getPointer();
4803 std::vector<int> newc;
4804 for(int j=0;j<nbOf2DCells;j++)
4806 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4807 *newConnIPtr++=(int)newc.size();
4809 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4810 int *newConnPtr=newConn->getPointer();
4811 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4812 newConnIPtr=newConnI->getPointer();
4813 for(int iz=0;iz<nbOf1DCells;iz++)
4816 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4817 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4819 int icell=(int)(iter-newc.begin());
4820 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4823 *newConnPtr=(*iter)+iz*deltaPerLev;
4828 *newConnPtr=(*iter);
4831 ret->setConnectivity(newConn,newConnI,true);
4832 ret->setCoords(getCoords());
4837 * Checks if \a this mesh is constituted by only quadratic cells.
4838 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4839 * \throw If the coordinates array is not set.
4840 * \throw If the nodal connectivity of cells is not defined.
4842 bool MEDCouplingUMesh::isFullyQuadratic() const
4844 checkFullyDefined();
4846 int nbOfCells=getNumberOfCells();
4847 for(int i=0;i<nbOfCells && ret;i++)
4849 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4850 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4851 ret=cm.isQuadratic();
4857 * Checks if \a this mesh includes any quadratic cell.
4858 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4859 * \throw If the coordinates array is not set.
4860 * \throw If the nodal connectivity of cells is not defined.
4862 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4864 checkFullyDefined();
4866 int nbOfCells=getNumberOfCells();
4867 for(int i=0;i<nbOfCells && !ret;i++)
4869 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4870 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4871 ret=cm.isQuadratic();
4877 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4878 * this mesh, it remains unchanged.
4879 * \throw If the coordinates array is not set.
4880 * \throw If the nodal connectivity of cells is not defined.
4882 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4884 checkFullyDefined();
4885 int nbOfCells=getNumberOfCells();
4887 const int *iciptr=_nodal_connec_index->getConstPointer();
4888 for(int i=0;i<nbOfCells;i++)
4890 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4891 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4892 if(cm.isQuadratic())
4894 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4895 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4896 if(!cml.isDynamic())
4897 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4899 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4904 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4905 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4906 const int *icptr=_nodal_connec->getConstPointer();
4907 newConn->alloc(getMeshLength()-delta,1);
4908 newConnI->alloc(nbOfCells+1,1);
4909 int *ocptr=newConn->getPointer();
4910 int *ociptr=newConnI->getPointer();
4913 for(int i=0;i<nbOfCells;i++,ociptr++)
4915 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4916 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4917 if(!cm.isQuadratic())
4919 _types.insert(type);
4920 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4921 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4925 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4926 _types.insert(typel);
4927 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4928 int newNbOfNodes=cml.getNumberOfNodes();
4930 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4931 *ocptr++=(int)typel;
4932 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4933 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4936 setConnectivity(newConn,newConnI,false);
4940 * This method converts all linear cell in \a this to quadratic one.
4941 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4942 * 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)
4943 * 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.
4944 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4945 * end of the existing coordinates.
4947 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4948 * corresponding quadratic cells. 1 is those creating the 'most' complex.
4949 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4951 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4953 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4955 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4957 DataArrayInt *conn=0,*connI=0;
4958 DataArrayDouble *coords=0;
4959 std::set<INTERP_KERNEL::NormalizedCellType> types;
4960 checkFullyDefined();
4961 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4962 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4963 int meshDim=getMeshDimension();
4964 switch(conversionType)
4970 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4971 connSafe=conn; connISafe=connI; coordsSafe=coords;
4974 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4975 connSafe=conn; connISafe=connI; coordsSafe=coords;
4978 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4979 connSafe=conn; connISafe=connI; coordsSafe=coords;
4982 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4990 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4991 connSafe=conn; connISafe=connI; coordsSafe=coords;
4994 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4995 connSafe=conn; connISafe=connI; coordsSafe=coords;
4998 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4999 connSafe=conn; connISafe=connI; coordsSafe=coords;
5002 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5007 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5009 setConnectivity(connSafe,connISafe,false);
5011 setCoords(coordsSafe);
5016 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5017 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5018 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5020 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5022 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5023 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5024 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5025 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5026 int nbOfCells=getNumberOfCells();
5027 int nbOfNodes=getNumberOfNodes();
5028 const int *cPtr=_nodal_connec->getConstPointer();
5029 const int *icPtr=_nodal_connec_index->getConstPointer();
5030 int lastVal=0,offset=nbOfNodes;
5031 for(int i=0;i<nbOfCells;i++,icPtr++)
5033 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5034 if(type==INTERP_KERNEL::NORM_SEG2)
5036 types.insert(INTERP_KERNEL::NORM_SEG3);
5037 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5038 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5039 newConn->pushBackSilent(offset++);
5041 newConnI->pushBackSilent(lastVal);
5042 ret->pushBackSilent(i);
5047 lastVal+=(icPtr[1]-icPtr[0]);
5048 newConnI->pushBackSilent(lastVal);
5049 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5052 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5053 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5057 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
5059 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5060 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5061 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5063 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5064 DataArrayInt *conn1D=0,*conn1DI=0;
5065 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5066 DataArrayDouble *coordsTmp=0;
5067 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5068 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5069 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5070 const int *c1DPtr=conn1D->begin();
5071 const int *c1DIPtr=conn1DI->begin();
5072 int nbOfCells=getNumberOfCells();
5073 const int *cPtr=_nodal_connec->getConstPointer();
5074 const int *icPtr=_nodal_connec_index->getConstPointer();
5076 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5078 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5079 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5080 if(!cm.isQuadratic())
5082 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5083 types.insert(typ2); newConn->pushBackSilent(typ2);
5084 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5085 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5086 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5087 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5088 newConnI->pushBackSilent(lastVal);
5089 ret->pushBackSilent(i);
5094 lastVal+=(icPtr[1]-icPtr[0]);
5095 newConnI->pushBackSilent(lastVal);
5096 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5099 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5104 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5105 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5106 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5108 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5111 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5112 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5113 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5116 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5118 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5119 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5121 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5122 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5123 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5125 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5126 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5127 DataArrayInt *conn1D=0,*conn1DI=0;
5128 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5129 DataArrayDouble *coordsTmp=0;
5130 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5131 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5132 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5133 const int *c1DPtr=conn1D->begin();
5134 const int *c1DIPtr=conn1DI->begin();
5135 int nbOfCells=getNumberOfCells();
5136 const int *cPtr=_nodal_connec->getConstPointer();
5137 const int *icPtr=_nodal_connec_index->getConstPointer();
5138 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5139 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5141 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5142 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5143 if(!cm.isQuadratic())
5145 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5146 types.insert(typ2); newConn->pushBackSilent(typ2);
5147 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5148 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5149 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5150 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5151 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5152 newConnI->pushBackSilent(lastVal);
5153 ret->pushBackSilent(i);
5158 lastVal+=(icPtr[1]-icPtr[0]);
5159 newConnI->pushBackSilent(lastVal);
5160 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5163 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5164 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5169 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5170 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5171 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5173 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5175 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5176 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5177 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5180 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5182 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5183 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5184 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5185 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5187 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5188 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5189 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5191 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5192 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5193 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5194 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5195 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5196 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5197 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5198 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5199 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5200 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5201 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5202 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5203 int nbOfCells=getNumberOfCells();
5204 const int *cPtr=_nodal_connec->getConstPointer();
5205 const int *icPtr=_nodal_connec_index->getConstPointer();
5206 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5207 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5209 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5210 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5211 if(!cm.isQuadratic())
5213 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5214 if(typ2==INTERP_KERNEL::NORM_ERROR)
5216 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5217 throw INTERP_KERNEL::Exception(oss.str().c_str());
5219 types.insert(typ2); newConn->pushBackSilent(typ2);
5220 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5221 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5222 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5223 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5225 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5226 int tmpPos=newConn->getNumberOfTuples();
5227 newConn->pushBackSilent(nodeId2);
5228 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5230 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5231 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5232 newConnI->pushBackSilent(lastVal);
5233 ret->pushBackSilent(i);
5238 lastVal+=(icPtr[1]-icPtr[0]);
5239 newConnI->pushBackSilent(lastVal);
5240 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5243 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5244 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5245 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5246 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5247 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5248 int *c=newConn->getPointer();
5249 const int *cI(newConnI->begin());
5250 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5251 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5252 offset=coordsTmp2Safe->getNumberOfTuples();
5253 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5254 c[cI[(*elt)+1]-1]+=offset;
5255 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5260 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5261 * so that the number of cells remains the same. Quadratic faces are converted to
5262 * polygons. This method works only for 2D meshes in
5263 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5264 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5265 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5266 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5267 * a polylinized edge constituting the input polygon.
5268 * \throw If the coordinates array is not set.
5269 * \throw If the nodal connectivity of cells is not defined.
5270 * \throw If \a this->getMeshDimension() != 2.
5271 * \throw If \a this->getSpaceDimension() != 2.
5273 void MEDCouplingUMesh::tessellate2D(double eps)
5275 checkFullyDefined();
5276 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5277 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5278 double epsa=fabs(eps);
5279 if(epsa<std::numeric_limits<double>::min())
5280 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 !");
5281 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5282 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5283 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5284 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5285 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5286 revDesc1=0; revDescIndx1=0;
5287 mDesc->tessellate2DCurve(eps);
5288 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5289 setCoords(mDesc->getCoords());
5293 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5294 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5295 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5296 * a sub-divided edge.
5297 * \throw If the coordinates array is not set.
5298 * \throw If the nodal connectivity of cells is not defined.
5299 * \throw If \a this->getMeshDimension() != 1.
5300 * \throw If \a this->getSpaceDimension() != 2.
5302 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5304 checkFullyDefined();
5305 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5306 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5307 double epsa=fabs(eps);
5308 if(epsa<std::numeric_limits<double>::min())
5309 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 !");
5310 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5311 int nbCells=getNumberOfCells();
5312 int nbNodes=getNumberOfNodes();
5313 const int *conn=_nodal_connec->getConstPointer();
5314 const int *connI=_nodal_connec_index->getConstPointer();
5315 const double *coords=_coords->getConstPointer();
5316 std::vector<double> addCoo;
5317 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5318 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5319 newConnI->alloc(nbCells+1,1);
5320 int *newConnIPtr=newConnI->getPointer();
5323 INTERP_KERNEL::Node *tmp2[3];
5324 std::set<INTERP_KERNEL::NormalizedCellType> types;
5325 for(int i=0;i<nbCells;i++,newConnIPtr++)
5327 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5328 if(cm.isQuadratic())
5329 {//assert(connI[i+1]-connI[i]-1==3)
5330 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5331 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5332 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5333 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5334 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5337 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5338 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5340 newConnIPtr[1]=(int)newConn.size();
5344 types.insert(INTERP_KERNEL::NORM_SEG2);
5345 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5346 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5347 newConnIPtr[1]=newConnIPtr[0]+3;
5352 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5353 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5354 newConnIPtr[1]=newConnIPtr[0]+3;
5357 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5360 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5361 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5362 newConnArr->alloc((int)newConn.size(),1);
5363 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5364 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5365 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5366 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5367 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5368 std::copy(addCoo.begin(),addCoo.end(),work);
5369 DataArrayDouble::SetArrayIn(newCoords,_coords);
5374 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5375 * In addition, returns an array mapping new cells to old ones. <br>
5376 * This method typically increases the number of cells in \a this mesh
5377 * but the number of nodes remains \b unchanged.
5378 * That's why the 3D splitting policies
5379 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5380 * \param [in] policy - specifies a pattern used for splitting.
5381 * The semantic of \a policy is:
5382 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5383 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5384 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5385 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5386 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5387 * an id of old cell producing it. The caller is to delete this array using
5388 * decrRef() as it is no more needed.
5389 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5390 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5391 * and \a this->getMeshDimension() != 3.
5392 * \throw If \a policy is not one of the four discussed above.
5393 * \throw If the nodal connectivity of cells is not defined.
5394 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5396 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5401 return simplexizePol0();
5403 return simplexizePol1();
5404 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5405 return simplexizePlanarFace5();
5406 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5407 return simplexizePlanarFace6();
5409 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)");
5414 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5415 * - 1D: INTERP_KERNEL::NORM_SEG2
5416 * - 2D: INTERP_KERNEL::NORM_TRI3
5417 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5419 * This method is useful for users that need to use P1 field services as
5420 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5421 * All these methods need mesh support containing only simplex cells.
5422 * \return bool - \c true if there are only simplex cells in \a this mesh.
5423 * \throw If the coordinates array is not set.
5424 * \throw If the nodal connectivity of cells is not defined.
5425 * \throw If \a this->getMeshDimension() < 1.
5427 bool MEDCouplingUMesh::areOnlySimplexCells() const
5429 checkFullyDefined();
5430 int mdim=getMeshDimension();
5431 if(mdim<1 || mdim>3)
5432 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5433 int nbCells=getNumberOfCells();
5434 const int *conn=_nodal_connec->getConstPointer();
5435 const int *connI=_nodal_connec_index->getConstPointer();
5436 for(int i=0;i<nbCells;i++)
5438 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5446 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5448 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5450 checkConnectivityFullyDefined();
5451 if(getMeshDimension()!=2)
5452 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5453 int nbOfCells=getNumberOfCells();
5454 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5455 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5456 ret->alloc(nbOfCells+nbOfCutCells,1);
5457 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5458 int *retPt=ret->getPointer();
5459 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5461 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5462 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5463 int *pt=newConn->getPointer();
5464 int *ptI=newConnI->getPointer();
5466 const int *oldc=_nodal_connec->getConstPointer();
5467 const int *ci=_nodal_connec_index->getConstPointer();
5468 for(int i=0;i<nbOfCells;i++,ci++)
5470 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5472 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5473 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5474 pt=std::copy(tmp,tmp+8,pt);
5483 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5484 ptI[1]=ptI[0]+ci[1]-ci[0];
5489 _nodal_connec->decrRef();
5490 _nodal_connec=newConn.retn();
5491 _nodal_connec_index->decrRef();
5492 _nodal_connec_index=newConnI.retn();
5499 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5501 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5503 checkConnectivityFullyDefined();
5504 if(getMeshDimension()!=2)
5505 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5506 int nbOfCells=getNumberOfCells();
5507 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5508 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5509 ret->alloc(nbOfCells+nbOfCutCells,1);
5510 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5511 int *retPt=ret->getPointer();
5512 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5513 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5514 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5515 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5516 int *pt=newConn->getPointer();
5517 int *ptI=newConnI->getPointer();
5519 const int *oldc=_nodal_connec->getConstPointer();
5520 const int *ci=_nodal_connec_index->getConstPointer();
5521 for(int i=0;i<nbOfCells;i++,ci++)
5523 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5525 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5526 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5527 pt=std::copy(tmp,tmp+8,pt);
5536 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5537 ptI[1]=ptI[0]+ci[1]-ci[0];
5542 _nodal_connec->decrRef();
5543 _nodal_connec=newConn.retn();
5544 _nodal_connec_index->decrRef();
5545 _nodal_connec_index=newConnI.retn();
5552 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5554 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5556 checkConnectivityFullyDefined();
5557 if(getMeshDimension()!=3)
5558 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5559 int nbOfCells=getNumberOfCells();
5560 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5561 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5562 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5563 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5564 int *retPt=ret->getPointer();
5565 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5566 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5567 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5568 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5569 int *pt=newConn->getPointer();
5570 int *ptI=newConnI->getPointer();
5572 const int *oldc=_nodal_connec->getConstPointer();
5573 const int *ci=_nodal_connec_index->getConstPointer();
5574 for(int i=0;i<nbOfCells;i++,ci++)
5576 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5578 for(int j=0;j<5;j++,pt+=5,ptI++)
5580 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5581 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];
5588 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5589 ptI[1]=ptI[0]+ci[1]-ci[0];
5594 _nodal_connec->decrRef();
5595 _nodal_connec=newConn.retn();
5596 _nodal_connec_index->decrRef();
5597 _nodal_connec_index=newConnI.retn();
5604 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5606 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5608 checkConnectivityFullyDefined();
5609 if(getMeshDimension()!=3)
5610 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5611 int nbOfCells=getNumberOfCells();
5612 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5613 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5614 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5615 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5616 int *retPt=ret->getPointer();
5617 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5618 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5619 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5620 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5621 int *pt=newConn->getPointer();
5622 int *ptI=newConnI->getPointer();
5624 const int *oldc=_nodal_connec->getConstPointer();
5625 const int *ci=_nodal_connec_index->getConstPointer();
5626 for(int i=0;i<nbOfCells;i++,ci++)
5628 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5630 for(int j=0;j<6;j++,pt+=5,ptI++)
5632 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5633 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];
5640 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5641 ptI[1]=ptI[0]+ci[1]-ci[0];
5646 _nodal_connec->decrRef();
5647 _nodal_connec=newConn.retn();
5648 _nodal_connec_index->decrRef();
5649 _nodal_connec_index=newConnI.retn();
5656 * 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.
5657 * This method completly ignore coordinates.
5658 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5659 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5660 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5661 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5663 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5665 checkFullyDefined();
5666 if(getMeshDimension()!=2)
5667 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5668 int nbOfCells=getNumberOfCells();
5669 int *connI=_nodal_connec_index->getPointer();
5671 for(int i=0;i<nbOfCells;i++,connI++)
5673 int offset=descIndex[i];
5674 int nbOfEdges=descIndex[i+1]-offset;
5676 bool ddirect=desc[offset+nbOfEdges-1]>0;
5677 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5678 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5679 for(int j=0;j<nbOfEdges;j++)
5681 bool direct=desc[offset+j]>0;
5682 int edgeId=std::abs(desc[offset+j])-1;
5683 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5685 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5686 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5687 int ref2=direct?id1:id2;
5690 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5691 newConnLgth+=nbOfSubNodes-1;
5696 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5697 throw INTERP_KERNEL::Exception(oss.str().c_str());
5702 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5705 newConnLgth++;//+1 is for cell type
5706 connI[1]=newConnLgth;
5709 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5710 newConn->alloc(newConnLgth,1);
5711 int *work=newConn->getPointer();
5712 for(int i=0;i<nbOfCells;i++)
5714 *work++=INTERP_KERNEL::NORM_POLYGON;
5715 int offset=descIndex[i];
5716 int nbOfEdges=descIndex[i+1]-offset;
5717 for(int j=0;j<nbOfEdges;j++)
5719 bool direct=desc[offset+j]>0;
5720 int edgeId=std::abs(desc[offset+j])-1;
5722 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5725 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5726 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5727 work=std::copy(it,it+nbOfSubNodes-1,work);
5731 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5734 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5738 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5739 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5740 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5741 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5742 * so it can be useful to call mergeNodes() before calling this method.
5743 * \throw If \a this->getMeshDimension() <= 1.
5744 * \throw If the coordinates array is not set.
5745 * \throw If the nodal connectivity of cells is not defined.
5747 void MEDCouplingUMesh::convertDegeneratedCells()
5749 checkFullyDefined();
5750 if(getMeshDimension()<=1)
5751 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5752 int nbOfCells=getNumberOfCells();
5755 int initMeshLgth=getMeshLength();
5756 int *conn=_nodal_connec->getPointer();
5757 int *index=_nodal_connec_index->getPointer();
5761 for(int i=0;i<nbOfCells;i++)
5763 lgthOfCurCell=index[i+1]-posOfCurCell;
5764 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5766 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5767 conn+newPos+1,newLgth);
5768 conn[newPos]=newType;
5770 posOfCurCell=index[i+1];
5773 if(newPos!=initMeshLgth)
5774 _nodal_connec->reAlloc(newPos);
5779 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5780 * A cell is considered to be oriented correctly if an angle between its
5781 * normal vector and a given vector is less than \c PI / \c 2.
5782 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5784 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5786 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5787 * is not cleared before filling in.
5788 * \throw If \a this->getMeshDimension() != 2.
5789 * \throw If \a this->getSpaceDimension() != 3.
5791 * \if ENABLE_EXAMPLES
5792 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5793 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5796 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5798 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5799 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5800 int nbOfCells=getNumberOfCells();
5801 const int *conn=_nodal_connec->getConstPointer();
5802 const int *connI=_nodal_connec_index->getConstPointer();
5803 const double *coordsPtr=_coords->getConstPointer();
5804 for(int i=0;i<nbOfCells;i++)
5806 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5807 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5809 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5810 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5817 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5818 * considered to be oriented correctly if an angle between its normal vector and a
5819 * given vector is less than \c PI / \c 2.
5820 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5822 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5824 * \throw If \a this->getMeshDimension() != 2.
5825 * \throw If \a this->getSpaceDimension() != 3.
5827 * \if ENABLE_EXAMPLES
5828 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5829 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5832 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5834 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5835 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5836 int nbOfCells=getNumberOfCells();
5837 int *conn=_nodal_connec->getPointer();
5838 const int *connI=_nodal_connec_index->getConstPointer();
5839 const double *coordsPtr=_coords->getConstPointer();
5840 bool isModified=false;
5841 for(int i=0;i<nbOfCells;i++)
5843 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5844 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5846 bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5847 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5852 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5853 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5854 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5858 int sz(((int)(connI[i+1]-connI[i]-1))/2);
5859 std::vector<int> tmp0(sz-1),tmp1(sz);
5860 std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5861 std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5862 std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5863 std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5869 _nodal_connec->declareAsNew();
5874 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5875 * oriented facets. The normal vector of the facet should point out of the cell.
5876 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5877 * is not cleared before filling in.
5878 * \throw If \a this->getMeshDimension() != 3.
5879 * \throw If \a this->getSpaceDimension() != 3.
5880 * \throw If the coordinates array is not set.
5881 * \throw If the nodal connectivity of cells is not defined.
5883 * \if ENABLE_EXAMPLES
5884 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5885 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5888 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5890 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5891 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5892 int nbOfCells=getNumberOfCells();
5893 const int *conn=_nodal_connec->getConstPointer();
5894 const int *connI=_nodal_connec_index->getConstPointer();
5895 const double *coordsPtr=_coords->getConstPointer();
5896 for(int i=0;i<nbOfCells;i++)
5898 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5899 if(type==INTERP_KERNEL::NORM_POLYHED)
5901 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5908 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5910 * \throw If \a this->getMeshDimension() != 3.
5911 * \throw If \a this->getSpaceDimension() != 3.
5912 * \throw If the coordinates array is not set.
5913 * \throw If the nodal connectivity of cells is not defined.
5914 * \throw If the reparation fails.
5916 * \if ENABLE_EXAMPLES
5917 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5918 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5920 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5922 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
5924 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5925 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5926 int nbOfCells=getNumberOfCells();
5927 int *conn=_nodal_connec->getPointer();
5928 const int *connI=_nodal_connec_index->getConstPointer();
5929 const double *coordsPtr=_coords->getConstPointer();
5930 for(int i=0;i<nbOfCells;i++)
5932 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5933 if(type==INTERP_KERNEL::NORM_POLYHED)
5937 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5938 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5940 catch(INTERP_KERNEL::Exception& e)
5942 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5943 throw INTERP_KERNEL::Exception(oss.str().c_str());
5951 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5952 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5953 * according to which the first facet of the cell should be oriented to have the normal vector
5954 * pointing out of cell.
5955 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5956 * cells. The caller is to delete this array using decrRef() as it is no more
5958 * \throw If \a this->getMeshDimension() != 3.
5959 * \throw If \a this->getSpaceDimension() != 3.
5960 * \throw If the coordinates array is not set.
5961 * \throw If the nodal connectivity of cells is not defined.
5963 * \if ENABLE_EXAMPLES
5964 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5965 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5967 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5969 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
5971 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5972 if(getMeshDimension()!=3)
5973 throw INTERP_KERNEL::Exception(msg);
5974 int spaceDim=getSpaceDimension();
5976 throw INTERP_KERNEL::Exception(msg);
5978 int nbOfCells=getNumberOfCells();
5979 int *conn=_nodal_connec->getPointer();
5980 const int *connI=_nodal_connec_index->getConstPointer();
5981 const double *coo=getCoords()->getConstPointer();
5982 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5983 for(int i=0;i<nbOfCells;i++)
5985 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5986 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5988 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5990 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5991 cells->pushBackSilent(i);
5995 return cells.retn();
5999 * This method is a faster method to correct orientation of all 3D cells in \a this.
6000 * 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.
6001 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6003 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6004 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6006 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6008 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6009 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6010 int nbOfCells=getNumberOfCells();
6011 int *conn=_nodal_connec->getPointer();
6012 const int *connI=_nodal_connec_index->getConstPointer();
6013 const double *coordsPtr=_coords->getConstPointer();
6014 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6015 for(int i=0;i<nbOfCells;i++)
6017 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6020 case INTERP_KERNEL::NORM_TETRA4:
6022 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6024 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6025 ret->pushBackSilent(i);
6029 case INTERP_KERNEL::NORM_PYRA5:
6031 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6033 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6034 ret->pushBackSilent(i);
6038 case INTERP_KERNEL::NORM_PENTA6:
6039 case INTERP_KERNEL::NORM_HEXA8:
6040 case INTERP_KERNEL::NORM_HEXGP12:
6042 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6044 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6045 ret->pushBackSilent(i);
6049 case INTERP_KERNEL::NORM_POLYHED:
6051 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6053 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6054 ret->pushBackSilent(i);
6059 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 !");
6067 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6068 * If it is not the case an exception will be thrown.
6069 * This method is fast because the first cell of \a this is used to compute the plane.
6070 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6071 * \param pos output of size at least 3 used to store a point owned of searched plane.
6073 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6075 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6076 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6077 const int *conn=_nodal_connec->getConstPointer();
6078 const int *connI=_nodal_connec_index->getConstPointer();
6079 const double *coordsPtr=_coords->getConstPointer();
6080 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6081 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6085 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6086 * cells. Currently cells of the following types are treated:
6087 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6088 * For a cell of other type an exception is thrown.
6089 * Space dimension of a 2D mesh can be either 2 or 3.
6090 * The Edge Ratio of a cell \f$t\f$ is:
6091 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6092 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6093 * the smallest edge lengths of \f$t\f$.
6094 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6095 * cells and one time, lying on \a this mesh. The caller is to delete this
6096 * field using decrRef() as it is no more needed.
6097 * \throw If the coordinates array is not set.
6098 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6099 * \throw If the connectivity data array has more than one component.
6100 * \throw If the connectivity data array has a named component.
6101 * \throw If the connectivity index data array has more than one component.
6102 * \throw If the connectivity index data array has a named component.
6103 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6104 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6105 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6107 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6110 int spaceDim=getSpaceDimension();
6111 int meshDim=getMeshDimension();
6112 if(spaceDim!=2 && spaceDim!=3)
6113 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6114 if(meshDim!=2 && meshDim!=3)
6115 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6116 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6118 int nbOfCells=getNumberOfCells();
6119 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6120 arr->alloc(nbOfCells,1);
6121 double *pt=arr->getPointer();
6122 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6123 const int *conn=_nodal_connec->getConstPointer();
6124 const int *connI=_nodal_connec_index->getConstPointer();
6125 const double *coo=_coords->getConstPointer();
6127 for(int i=0;i<nbOfCells;i++,pt++)
6129 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6132 case INTERP_KERNEL::NORM_TRI3:
6134 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6135 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6138 case INTERP_KERNEL::NORM_QUAD4:
6140 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6141 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6144 case INTERP_KERNEL::NORM_TETRA4:
6146 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6147 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6151 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6153 conn+=connI[i+1]-connI[i];
6155 ret->setName("EdgeRatio");
6156 ret->synchronizeTimeWithSupport();
6161 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6162 * cells. Currently cells of the following types are treated:
6163 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6164 * For a cell of other type an exception is thrown.
6165 * Space dimension of a 2D mesh can be either 2 or 3.
6166 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6167 * cells and one time, lying on \a this mesh. The caller is to delete this
6168 * field using decrRef() as it is no more needed.
6169 * \throw If the coordinates array is not set.
6170 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6171 * \throw If the connectivity data array has more than one component.
6172 * \throw If the connectivity data array has a named component.
6173 * \throw If the connectivity index data array has more than one component.
6174 * \throw If the connectivity index data array has a named component.
6175 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6176 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6177 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6179 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6182 int spaceDim=getSpaceDimension();
6183 int meshDim=getMeshDimension();
6184 if(spaceDim!=2 && spaceDim!=3)
6185 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6186 if(meshDim!=2 && meshDim!=3)
6187 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6188 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6190 int nbOfCells=getNumberOfCells();
6191 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6192 arr->alloc(nbOfCells,1);
6193 double *pt=arr->getPointer();
6194 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6195 const int *conn=_nodal_connec->getConstPointer();
6196 const int *connI=_nodal_connec_index->getConstPointer();
6197 const double *coo=_coords->getConstPointer();
6199 for(int i=0;i<nbOfCells;i++,pt++)
6201 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6204 case INTERP_KERNEL::NORM_TRI3:
6206 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6207 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6210 case INTERP_KERNEL::NORM_QUAD4:
6212 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6213 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6216 case INTERP_KERNEL::NORM_TETRA4:
6218 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6219 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6223 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6225 conn+=connI[i+1]-connI[i];
6227 ret->setName("AspectRatio");
6228 ret->synchronizeTimeWithSupport();
6233 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6234 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6235 * treated: INTERP_KERNEL::NORM_QUAD4.
6236 * For a cell of other type an exception is thrown.
6237 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6238 * cells and one time, lying on \a this mesh. The caller is to delete this
6239 * field using decrRef() as it is no more needed.
6240 * \throw If the coordinates array is not set.
6241 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6242 * \throw If the connectivity data array has more than one component.
6243 * \throw If the connectivity data array has a named component.
6244 * \throw If the connectivity index data array has more than one component.
6245 * \throw If the connectivity index data array has a named component.
6246 * \throw If \a this->getMeshDimension() != 2.
6247 * \throw If \a this->getSpaceDimension() != 3.
6248 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6250 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6253 int spaceDim=getSpaceDimension();
6254 int meshDim=getMeshDimension();
6256 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6258 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6259 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6261 int nbOfCells=getNumberOfCells();
6262 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6263 arr->alloc(nbOfCells,1);
6264 double *pt=arr->getPointer();
6265 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6266 const int *conn=_nodal_connec->getConstPointer();
6267 const int *connI=_nodal_connec_index->getConstPointer();
6268 const double *coo=_coords->getConstPointer();
6270 for(int i=0;i<nbOfCells;i++,pt++)
6272 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6275 case INTERP_KERNEL::NORM_QUAD4:
6277 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6278 *pt=INTERP_KERNEL::quadWarp(tmp);
6282 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6284 conn+=connI[i+1]-connI[i];
6286 ret->setName("Warp");
6287 ret->synchronizeTimeWithSupport();
6293 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6294 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6295 * treated: INTERP_KERNEL::NORM_QUAD4.
6296 * For a cell of other type an exception is thrown.
6297 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6298 * cells and one time, lying on \a this mesh. The caller is to delete this
6299 * field using decrRef() as it is no more needed.
6300 * \throw If the coordinates array is not set.
6301 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6302 * \throw If the connectivity data array has more than one component.
6303 * \throw If the connectivity data array has a named component.
6304 * \throw If the connectivity index data array has more than one component.
6305 * \throw If the connectivity index data array has a named component.
6306 * \throw If \a this->getMeshDimension() != 2.
6307 * \throw If \a this->getSpaceDimension() != 3.
6308 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6310 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6313 int spaceDim=getSpaceDimension();
6314 int meshDim=getMeshDimension();
6316 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6318 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6319 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6321 int nbOfCells=getNumberOfCells();
6322 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6323 arr->alloc(nbOfCells,1);
6324 double *pt=arr->getPointer();
6325 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6326 const int *conn=_nodal_connec->getConstPointer();
6327 const int *connI=_nodal_connec_index->getConstPointer();
6328 const double *coo=_coords->getConstPointer();
6330 for(int i=0;i<nbOfCells;i++,pt++)
6332 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6335 case INTERP_KERNEL::NORM_QUAD4:
6337 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6338 *pt=INTERP_KERNEL::quadSkew(tmp);
6342 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6344 conn+=connI[i+1]-connI[i];
6346 ret->setName("Skew");
6347 ret->synchronizeTimeWithSupport();
6352 * This method aggregate the bbox of each cell and put it into bbox parameter.
6354 * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6355 * For all other cases this input parameter is ignored.
6356 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6358 * \throw If \a this is not fully set (coordinates and connectivity).
6359 * \throw If a cell in \a this has no valid nodeId.
6360 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6362 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6364 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6365 if((mDim==3 && sDim==3) || (mDim==2 && sDim==3) || (mDim==1 && sDim==1) || ( mDim==1 && sDim==3)) // Compute refined boundary box for quadratic elements only in 2D.
6366 return getBoundingBoxForBBTreeFast();
6367 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6369 bool presenceOfQuadratic(false);
6370 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6372 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6373 if(cm.isQuadratic())
6374 presenceOfQuadratic=true;
6376 if(!presenceOfQuadratic)
6377 return getBoundingBoxForBBTreeFast();
6378 if(mDim==2 && sDim==2)
6379 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6381 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6383 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree : Managed dimensions are (mDim=1,sDim=1), (mDim=1,sDim=2), (mDim=1,sDim=3), (mDim=2,sDim=2), (mDim=2,sDim=3) and (mDim=3,sDim=3) !");
6387 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6388 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6390 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6392 * \throw If \a this is not fully set (coordinates and connectivity).
6393 * \throw If a cell in \a this has no valid nodeId.
6395 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6397 checkFullyDefined();
6398 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6399 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6400 double *bbox(ret->getPointer());
6401 for(int i=0;i<nbOfCells*spaceDim;i++)
6403 bbox[2*i]=std::numeric_limits<double>::max();
6404 bbox[2*i+1]=-std::numeric_limits<double>::max();
6406 const double *coordsPtr(_coords->getConstPointer());
6407 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6408 for(int i=0;i<nbOfCells;i++)
6410 int offset=connI[i]+1;
6411 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6412 for(int j=0;j<nbOfNodesForCell;j++)
6414 int nodeId=conn[offset+j];
6415 if(nodeId>=0 && nodeId<nbOfNodes)
6417 for(int k=0;k<spaceDim;k++)
6419 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6420 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6427 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6428 throw INTERP_KERNEL::Exception(oss.str().c_str());
6435 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6436 * useful for 2D meshes having quadratic cells
6437 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6438 * the two extremities of the arc of circle).
6440 * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6441 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6442 * \throw If \a this is not fully defined.
6443 * \throw If \a this is not a mesh with meshDimension equal to 2.
6444 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6445 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6447 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6449 checkFullyDefined();
6450 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6451 if(spaceDim!=2 || mDim!=2)
6452 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic : This method should be applied on mesh with mesh dimension equal to 2 and space dimension also equal to 2!");
6453 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6454 double *bbox(ret->getPointer());
6455 const double *coords(_coords->getConstPointer());
6456 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6457 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6459 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6460 int sz(connI[1]-connI[0]-1);
6461 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6462 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6463 INTERP_KERNEL::QuadraticPolygon *pol(0);
6464 for(int j=0;j<sz;j++)
6466 int nodeId(conn[*connI+1+j]);
6467 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6469 if(!cm.isQuadratic())
6470 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6472 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6473 INTERP_KERNEL::Bounds b; pol->fillBounds(b); delete pol;
6474 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6480 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6481 * useful for 2D meshes having quadratic cells
6482 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6483 * the two extremities of the arc of circle).
6485 * \param [in] arcDetEps - a parameter specifying in case of 2D quadratic polygon cell the detection limit between linear and arc circle. (By default 1e-12)
6486 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6487 * \throw If \a this is not fully defined.
6488 * \throw If \a this is not a mesh with meshDimension equal to 1.
6489 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6490 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6492 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6494 checkFullyDefined();
6495 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6496 if(spaceDim!=2 || mDim!=1)
6497 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic : This method should be applied on mesh with mesh dimension equal to 1 and space dimension also equal to 2!");
6498 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6499 double *bbox(ret->getPointer());
6500 const double *coords(_coords->getConstPointer());
6501 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6502 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6504 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6505 int sz(connI[1]-connI[0]-1);
6506 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6507 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6508 INTERP_KERNEL::Edge *edge(0);
6509 for(int j=0;j<sz;j++)
6511 int nodeId(conn[*connI+1+j]);
6512 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6514 if(!cm.isQuadratic())
6515 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6517 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6518 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6519 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6526 namespace ParaMEDMEMImpl
6531 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6532 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6541 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6542 bool operator() (const int& pos) { return _conn[pos]==_val; }
6552 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6553 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6554 * \a this is composed in cell types.
6555 * The returned array is of size 3*n where n is the number of different types present in \a this.
6556 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6557 * This parameter is kept only for compatibility with other methode listed above.
6559 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6561 checkConnectivityFullyDefined();
6562 const int *conn=_nodal_connec->getConstPointer();
6563 const int *connI=_nodal_connec_index->getConstPointer();
6564 const int *work=connI;
6565 int nbOfCells=getNumberOfCells();
6566 std::size_t n=getAllGeoTypes().size();
6567 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6568 std::set<INTERP_KERNEL::NormalizedCellType> types;
6569 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6571 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6572 if(types.find(typ)!=types.end())
6574 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6575 oss << " is not contiguous !";
6576 throw INTERP_KERNEL::Exception(oss.str().c_str());
6580 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6581 ret[3*i+1]=(int)std::distance(work,work2);
6588 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6589 * only for types cell, type node is not managed.
6590 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6591 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6592 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6593 * If 2 or more same geometric type is in \a code and exception is thrown too.
6595 * This method firstly checks
6596 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6597 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6598 * an exception is thrown too.
6600 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6601 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6602 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6604 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6607 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6608 std::size_t sz=code.size();
6611 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6612 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6614 bool isNoPflUsed=true;
6615 for(std::size_t i=0;i<n;i++)
6616 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6618 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6620 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6621 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6622 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6625 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6628 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6629 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6630 if(types.size()==_types.size())
6633 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6635 int *retPtr=ret->getPointer();
6636 const int *connI=_nodal_connec_index->getConstPointer();
6637 const int *conn=_nodal_connec->getConstPointer();
6638 int nbOfCells=getNumberOfCells();
6641 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6643 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6644 int offset=(int)std::distance(connI,i);
6645 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6646 int nbOfCellsOfCurType=(int)std::distance(i,j);
6647 if(code[3*kk+2]==-1)
6648 for(int k=0;k<nbOfCellsOfCurType;k++)
6652 int idInIdsPerType=code[3*kk+2];
6653 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6655 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6658 zePfl->checkAllocated();
6659 if(zePfl->getNumberOfComponents()==1)
6661 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6663 if(*k>=0 && *k<nbOfCellsOfCurType)
6664 *retPtr=(*k)+offset;
6667 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6668 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6669 throw INTERP_KERNEL::Exception(oss.str().c_str());
6674 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6677 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6681 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6682 oss << " should be in [0," << idsPerType.size() << ") !";
6683 throw INTERP_KERNEL::Exception(oss.str().c_str());
6692 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6693 * 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.
6694 * 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.
6695 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6697 * \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.
6698 * \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,
6699 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6700 * \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.
6701 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6702 * \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
6704 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6707 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6708 if(profile->getNumberOfComponents()!=1)
6709 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6710 checkConnectivityFullyDefined();
6711 const int *conn=_nodal_connec->getConstPointer();
6712 const int *connI=_nodal_connec_index->getConstPointer();
6713 int nbOfCells=getNumberOfCells();
6714 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6715 std::vector<int> typeRangeVals(1);
6716 for(const int *i=connI;i!=connI+nbOfCells;)
6718 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6719 if(std::find(types.begin(),types.end(),curType)!=types.end())
6721 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6723 types.push_back(curType);
6724 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6725 typeRangeVals.push_back((int)std::distance(connI,i));
6728 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6729 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6730 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6731 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6732 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6734 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6735 code.resize(3*nbOfCastsFinal);
6736 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6737 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6738 for(int i=0;i<nbOfCastsFinal;i++)
6740 int castId=castsPresent->getIJ(i,0);
6741 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6742 idsInPflPerType2.push_back(tmp3);
6743 code[3*i]=(int)types[castId];
6744 code[3*i+1]=tmp3->getNumberOfTuples();
6745 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6746 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6748 tmp4->copyStringInfoFrom(*profile);
6749 idsPerType2.push_back(tmp4);
6750 code[3*i+2]=(int)idsPerType2.size()-1;
6757 std::size_t sz2=idsInPflPerType2.size();
6758 idsInPflPerType.resize(sz2);
6759 for(std::size_t i=0;i<sz2;i++)
6761 DataArrayInt *locDa=idsInPflPerType2[i];
6763 idsInPflPerType[i]=locDa;
6765 std::size_t sz=idsPerType2.size();
6766 idsPerType.resize(sz);
6767 for(std::size_t i=0;i<sz;i++)
6769 DataArrayInt *locDa=idsPerType2[i];
6771 idsPerType[i]=locDa;
6776 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6777 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6778 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6779 * 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.
6781 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6783 checkFullyDefined();
6784 nM1LevMesh->checkFullyDefined();
6785 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6786 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6787 if(_coords!=nM1LevMesh->getCoords())
6788 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6789 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6790 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6791 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6792 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6793 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6794 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6795 tmp->setConnectivity(tmp0,tmp1);
6796 tmp->renumberCells(ret0->getConstPointer(),false);
6797 revDesc=tmp->getNodalConnectivity();
6798 revDescIndx=tmp->getNodalConnectivityIndex();
6799 DataArrayInt *ret=0;
6800 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6803 ret->getMaxValue(tmp2);
6805 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6806 throw INTERP_KERNEL::Exception(oss.str().c_str());
6811 revDescIndx->incrRef();
6814 meshnM1Old2New=ret0;
6819 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6820 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6821 * in "Old to New" mode.
6822 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6823 * this array using decrRef() as it is no more needed.
6824 * \throw If the nodal connectivity of cells is not defined.
6826 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6828 checkConnectivityFullyDefined();
6829 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6830 renumberCells(ret->getConstPointer(),false);
6835 * This methods checks that cells are sorted by their types.
6836 * This method makes asumption (no check) that connectivity is correctly set before calling.
6838 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6840 checkFullyDefined();
6841 const int *conn=_nodal_connec->getConstPointer();
6842 const int *connI=_nodal_connec_index->getConstPointer();
6843 int nbOfCells=getNumberOfCells();
6844 std::set<INTERP_KERNEL::NormalizedCellType> types;
6845 for(const int *i=connI;i!=connI+nbOfCells;)
6847 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6848 if(types.find(curType)!=types.end())
6850 types.insert(curType);
6851 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6857 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6858 * The geometric type order is specified by MED file.
6860 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6862 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6864 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6868 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6869 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6870 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6871 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6873 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6875 checkFullyDefined();
6876 const int *conn=_nodal_connec->getConstPointer();
6877 const int *connI=_nodal_connec_index->getConstPointer();
6878 int nbOfCells=getNumberOfCells();
6882 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6883 for(const int *i=connI;i!=connI+nbOfCells;)
6885 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6886 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6887 if(isTypeExists!=orderEnd)
6889 int pos=(int)std::distance(orderBg,isTypeExists);
6893 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6897 if(sg.find(curType)==sg.end())
6899 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6910 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6911 * 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
6912 * 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'.
6914 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
6916 checkConnectivityFullyDefined();
6917 int nbOfCells=getNumberOfCells();
6918 const int *conn=_nodal_connec->getConstPointer();
6919 const int *connI=_nodal_connec_index->getConstPointer();
6920 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6921 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6922 tmpa->alloc(nbOfCells,1);
6923 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6924 tmpb->fillWithZero();
6925 int *tmp=tmpa->getPointer();
6926 int *tmp2=tmpb->getPointer();
6927 for(const int *i=connI;i!=connI+nbOfCells;i++)
6929 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6932 int pos=(int)std::distance(orderBg,where);
6934 tmp[std::distance(connI,i)]=pos;
6938 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6939 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6940 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6941 throw INTERP_KERNEL::Exception(oss.str().c_str());
6944 nbPerType=tmpb.retn();
6949 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6951 * \return a new object containing the old to new correspondance.
6953 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6955 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
6957 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6961 * 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.
6962 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6963 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6964 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6966 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6968 DataArrayInt *nbPerType=0;
6969 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6970 nbPerType->decrRef();
6971 return tmpa->buildPermArrPerLevel();
6975 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6976 * The number of cells remains unchanged after the call of this method.
6977 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6978 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6980 * \return the array giving the correspondance old to new.
6982 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6984 checkFullyDefined();
6986 const int *conn=_nodal_connec->getConstPointer();
6987 const int *connI=_nodal_connec_index->getConstPointer();
6988 int nbOfCells=getNumberOfCells();
6989 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6990 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6991 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6993 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6994 types.push_back(curType);
6995 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6997 DataArrayInt *ret=DataArrayInt::New();
6998 ret->alloc(nbOfCells,1);
6999 int *retPtr=ret->getPointer();
7000 std::fill(retPtr,retPtr+nbOfCells,-1);
7002 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7004 for(const int *i=connI;i!=connI+nbOfCells;i++)
7005 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7006 retPtr[std::distance(connI,i)]=newCellId++;
7008 renumberCells(retPtr,false);
7013 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7014 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7015 * This method makes asumption that connectivity is correctly set before calling.
7017 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7019 checkConnectivityFullyDefined();
7020 const int *conn=_nodal_connec->getConstPointer();
7021 const int *connI=_nodal_connec_index->getConstPointer();
7022 int nbOfCells=getNumberOfCells();
7023 std::vector<MEDCouplingUMesh *> ret;
7024 for(const int *i=connI;i!=connI+nbOfCells;)
7026 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7027 int beginCellId=(int)std::distance(connI,i);
7028 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7029 int endCellId=(int)std::distance(connI,i);
7030 int sz=endCellId-beginCellId;
7031 int *cells=new int[sz];
7032 for(int j=0;j<sz;j++)
7033 cells[j]=beginCellId+j;
7034 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7042 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7043 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7044 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7046 * \return a newly allocated instance, that the caller must manage.
7047 * \throw If \a this contains more than one geometric type.
7048 * \throw If the nodal connectivity of \a this is not fully defined.
7049 * \throw If the internal data is not coherent.
7051 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7053 checkConnectivityFullyDefined();
7054 if(_types.size()!=1)
7055 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7056 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7057 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7058 ret->setCoords(getCoords());
7059 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7062 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7063 retC->setNodalConnectivity(c);
7067 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7069 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7070 DataArrayInt *c=0,*ci=0;
7071 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7072 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7073 retD->setNodalConnectivity(cs,cis);
7078 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7080 checkConnectivityFullyDefined();
7081 if(_types.size()!=1)
7082 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7083 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7084 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7087 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7088 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7089 throw INTERP_KERNEL::Exception(oss.str().c_str());
7091 int nbCells=getNumberOfCells();
7093 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7094 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7095 int *outPtr=connOut->getPointer();
7096 const int *conn=_nodal_connec->begin();
7097 const int *connI=_nodal_connec_index->begin();
7099 for(int i=0;i<nbCells;i++,connI++)
7101 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7102 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7105 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 << ") !";
7106 throw INTERP_KERNEL::Exception(oss.str().c_str());
7109 return connOut.retn();
7112 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7114 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7115 checkConnectivityFullyDefined();
7116 if(_types.size()!=1)
7117 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7118 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7120 throw INTERP_KERNEL::Exception(msg0);
7121 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7122 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7123 int *cp(c->getPointer()),*cip(ci->getPointer());
7124 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7126 for(int i=0;i<nbCells;i++,cip++,incip++)
7128 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7129 int delta(stop-strt);
7132 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7133 cp=std::copy(incp+strt,incp+stop,cp);
7135 throw INTERP_KERNEL::Exception(msg0);
7138 throw INTERP_KERNEL::Exception(msg0);
7139 cip[1]=cip[0]+delta;
7141 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7145 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7146 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7147 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7148 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7149 * are not used here to avoid the build of big permutation array.
7151 * \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
7152 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7153 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7154 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7155 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7156 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7157 * \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
7158 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7160 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7161 DataArrayInt *&szOfCellGrpOfSameType,
7162 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
7164 std::vector<const MEDCouplingUMesh *> ms2;
7165 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7168 (*it)->checkConnectivityFullyDefined();
7172 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7173 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7174 int meshDim=ms2[0]->getMeshDimension();
7175 std::vector<const MEDCouplingUMesh *> m1ssm;
7176 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7178 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7179 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7181 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7182 ret1->alloc(0,1); ret2->alloc(0,1);
7183 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7185 if(meshDim!=(*it)->getMeshDimension())
7186 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7187 if(refCoo!=(*it)->getCoords())
7188 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7189 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7190 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7191 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7192 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7194 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7195 m1ssmSingleAuto.push_back(singleCell);
7196 m1ssmSingle.push_back(singleCell);
7197 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7200 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7201 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7202 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7203 for(std::size_t i=0;i<m1ssm.size();i++)
7204 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7205 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7206 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7207 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7212 * This method returns a newly created DataArrayInt instance.
7213 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7215 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7217 checkFullyDefined();
7218 const int *conn=_nodal_connec->getConstPointer();
7219 const int *connIndex=_nodal_connec_index->getConstPointer();
7220 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7221 for(const int *w=begin;w!=end;w++)
7222 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7223 ret->pushBackSilent(*w);
7228 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7229 * are in [0:getNumberOfCells())
7231 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7233 checkFullyDefined();
7234 const int *conn=_nodal_connec->getConstPointer();
7235 const int *connI=_nodal_connec_index->getConstPointer();
7236 int nbOfCells=getNumberOfCells();
7237 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7238 int *tmp=new int[nbOfCells];
7239 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7242 for(const int *i=connI;i!=connI+nbOfCells;i++)
7243 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7244 tmp[std::distance(connI,i)]=j++;
7246 DataArrayInt *ret=DataArrayInt::New();
7247 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7248 ret->copyStringInfoFrom(*da);
7249 int *retPtr=ret->getPointer();
7250 const int *daPtr=da->getConstPointer();
7251 int nbOfElems=da->getNbOfElems();
7252 for(int k=0;k<nbOfElems;k++)
7253 retPtr[k]=tmp[daPtr[k]];
7259 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7260 * This method \b works \b for mesh sorted by type.
7261 * cells whose ids is in 'idsPerGeoType' array.
7262 * This method conserves coords and name of mesh.
7264 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7266 std::vector<int> code=getDistributionOfTypes();
7267 std::size_t nOfTypesInThis=code.size()/3;
7268 int sz=0,szOfType=0;
7269 for(std::size_t i=0;i<nOfTypesInThis;i++)
7274 szOfType=code[3*i+1];
7276 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7277 if(*work<0 || *work>=szOfType)
7279 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7280 oss << ". It should be in [0," << szOfType << ") !";
7281 throw INTERP_KERNEL::Exception(oss.str().c_str());
7283 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7284 int *idsPtr=idsTokeep->getPointer();
7286 for(std::size_t i=0;i<nOfTypesInThis;i++)
7289 for(int j=0;j<code[3*i+1];j++)
7292 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7293 offset+=code[3*i+1];
7295 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7296 ret->copyTinyInfoFrom(this);
7301 * This method returns a vector of size 'this->getNumberOfCells()'.
7302 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7304 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7306 int ncell=getNumberOfCells();
7307 std::vector<bool> ret(ncell);
7308 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7309 const int *c=getNodalConnectivity()->getConstPointer();
7310 for(int i=0;i<ncell;i++)
7312 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7313 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7314 ret[i]=cm.isQuadratic();
7320 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7322 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7324 if(other->getType()!=UNSTRUCTURED)
7325 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7326 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7327 return MergeUMeshes(this,otherC);
7331 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7332 * computed by averaging coordinates of cell nodes, so this method is not a right
7333 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7334 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7335 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7336 * components. The caller is to delete this array using decrRef() as it is
7338 * \throw If the coordinates array is not set.
7339 * \throw If the nodal connectivity of cells is not defined.
7340 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7342 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7344 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7345 int spaceDim=getSpaceDimension();
7346 int nbOfCells=getNumberOfCells();
7347 ret->alloc(nbOfCells,spaceDim);
7348 ret->copyStringInfoFrom(*getCoords());
7349 double *ptToFill=ret->getPointer();
7350 const int *nodal=_nodal_connec->getConstPointer();
7351 const int *nodalI=_nodal_connec_index->getConstPointer();
7352 const double *coor=_coords->getConstPointer();
7353 for(int i=0;i<nbOfCells;i++)
7355 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7356 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7363 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7364 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7366 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7367 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7369 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7370 * \throw If \a this is not fully defined (coordinates and connectivity)
7371 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7373 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7375 checkFullyDefined();
7376 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7377 int spaceDim=getSpaceDimension();
7378 int nbOfCells=getNumberOfCells();
7379 int nbOfNodes=getNumberOfNodes();
7380 ret->alloc(nbOfCells,spaceDim);
7381 double *ptToFill=ret->getPointer();
7382 const int *nodal=_nodal_connec->getConstPointer();
7383 const int *nodalI=_nodal_connec_index->getConstPointer();
7384 const double *coor=_coords->getConstPointer();
7385 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7387 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7388 std::fill(ptToFill,ptToFill+spaceDim,0.);
7389 if(type!=INTERP_KERNEL::NORM_POLYHED)
7391 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7393 if(*conn>=0 && *conn<nbOfNodes)
7394 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7397 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7398 throw INTERP_KERNEL::Exception(oss.str().c_str());
7401 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7402 if(nbOfNodesInCell>0)
7403 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7406 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7407 throw INTERP_KERNEL::Exception(oss.str().c_str());
7412 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7414 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7416 if(*it>=0 && *it<nbOfNodes)
7417 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7420 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7421 throw INTERP_KERNEL::Exception(oss.str().c_str());
7425 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7428 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7429 throw INTERP_KERNEL::Exception(oss.str().c_str());
7437 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7438 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7439 * are specified via an array of cell ids.
7440 * \warning Validity of the specified cell ids is not checked!
7441 * Valid range is [ 0, \a this->getNumberOfCells() ).
7442 * \param [in] begin - an array of cell ids of interest.
7443 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7444 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7445 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7446 * caller is to delete this array using decrRef() as it is no more needed.
7447 * \throw If the coordinates array is not set.
7448 * \throw If the nodal connectivity of cells is not defined.
7450 * \if ENABLE_EXAMPLES
7451 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7452 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7455 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7457 DataArrayDouble *ret=DataArrayDouble::New();
7458 int spaceDim=getSpaceDimension();
7459 int nbOfTuple=(int)std::distance(begin,end);
7460 ret->alloc(nbOfTuple,spaceDim);
7461 double *ptToFill=ret->getPointer();
7462 double *tmp=new double[spaceDim];
7463 const int *nodal=_nodal_connec->getConstPointer();
7464 const int *nodalI=_nodal_connec_index->getConstPointer();
7465 const double *coor=_coords->getConstPointer();
7466 for(const int *w=begin;w!=end;w++)
7468 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7469 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7477 * Returns a DataArrayDouble instance giving for each cell in \a this the equation of plane given by "a*X+b*Y+c*Z+d=0".
7478 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7479 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7480 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7481 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7483 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7484 * \throw If spaceDim!=3 or meshDim!=2.
7485 * \throw If connectivity of \a this is invalid.
7486 * \throw If connectivity of a cell in \a this points to an invalid node.
7488 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7490 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7491 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7492 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7493 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7494 ret->alloc(nbOfCells,4);
7495 double *retPtr(ret->getPointer());
7496 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7497 const double *coor(_coords->begin());
7498 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7500 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7501 if(nodalI[1]-nodalI[0]>=3)
7503 for(int j=0;j<3;j++)
7505 int nodeId(nodal[nodalI[0]+1+j]);
7506 if(nodeId>=0 && nodeId<nbOfNodes)
7507 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7510 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7511 throw INTERP_KERNEL::Exception(oss.str().c_str());
7517 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7518 throw INTERP_KERNEL::Exception(oss.str().c_str());
7520 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7521 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7527 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7530 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7533 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7534 da->checkAllocated();
7535 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7537 int nbOfTuples=da->getNumberOfTuples();
7538 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7539 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7540 c->alloc(2*nbOfTuples,1);
7541 cI->alloc(nbOfTuples+1,1);
7542 int *cp=c->getPointer();
7543 int *cip=cI->getPointer();
7545 for(int i=0;i<nbOfTuples;i++)
7547 *cp++=INTERP_KERNEL::NORM_POINT1;
7551 ret->setConnectivity(c,cI,true);
7555 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7556 * Cells and nodes of
7557 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7558 * \param [in] mesh1 - the first mesh.
7559 * \param [in] mesh2 - the second mesh.
7560 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7561 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7562 * is no more needed.
7563 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7564 * \throw If the coordinates array is not set in none of the meshes.
7565 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7566 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7568 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7570 std::vector<const MEDCouplingUMesh *> tmp(2);
7571 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7572 return MergeUMeshes(tmp);
7576 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7577 * Cells and nodes of
7578 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7579 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7580 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7581 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7582 * is no more needed.
7583 * \throw If \a a.size() == 0.
7584 * \throw If \a a[ *i* ] == NULL.
7585 * \throw If the coordinates array is not set in none of the meshes.
7586 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7587 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7589 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7591 std::size_t sz=a.size();
7593 return MergeUMeshesLL(a);
7594 for(std::size_t ii=0;ii<sz;ii++)
7597 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7598 throw INTERP_KERNEL::Exception(oss.str().c_str());
7600 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7601 std::vector< const MEDCouplingUMesh * > aa(sz);
7603 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7605 const MEDCouplingUMesh *cur=a[i];
7606 const DataArrayDouble *coo=cur->getCoords();
7608 spaceDim=coo->getNumberOfComponents();
7611 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7612 for(std::size_t i=0;i<sz;i++)
7614 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7617 return MergeUMeshesLL(aa);
7622 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7625 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7626 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7627 int meshDim=(*it)->getMeshDimension();
7628 int nbOfCells=(*it)->getNumberOfCells();
7629 int meshLgth=(*it++)->getMeshLength();
7630 for(;it!=a.end();it++)
7632 if(meshDim!=(*it)->getMeshDimension())
7633 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7634 nbOfCells+=(*it)->getNumberOfCells();
7635 meshLgth+=(*it)->getMeshLength();
7637 std::vector<const MEDCouplingPointSet *> aps(a.size());
7638 std::copy(a.begin(),a.end(),aps.begin());
7639 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7640 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7641 ret->setCoords(pts);
7642 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7643 c->alloc(meshLgth,1);
7644 int *cPtr=c->getPointer();
7645 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7646 cI->alloc(nbOfCells+1,1);
7647 int *cIPtr=cI->getPointer();
7651 for(it=a.begin();it!=a.end();it++)
7653 int curNbOfCell=(*it)->getNumberOfCells();
7654 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7655 const int *curC=(*it)->_nodal_connec->getConstPointer();
7656 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7657 for(int j=0;j<curNbOfCell;j++)
7659 const int *src=curC+curCI[j];
7661 for(;src!=curC+curCI[j+1];src++,cPtr++)
7669 offset+=curCI[curNbOfCell];
7670 offset2+=(*it)->getNumberOfNodes();
7673 ret->setConnectivity(c,cI,true);
7680 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7681 * dimension and sharing the node coordinates array.
7682 * All cells of the first mesh precede all cells of the second mesh
7683 * within the result mesh.
7684 * \param [in] mesh1 - the first mesh.
7685 * \param [in] mesh2 - the second mesh.
7686 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7687 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7688 * is no more needed.
7689 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7690 * \throw If the meshes do not share the node coordinates array.
7691 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7692 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7694 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7696 std::vector<const MEDCouplingUMesh *> tmp(2);
7697 tmp[0]=mesh1; tmp[1]=mesh2;
7698 return MergeUMeshesOnSameCoords(tmp);
7702 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7703 * dimension and sharing the node coordinates array.
7704 * All cells of the *i*-th mesh precede all cells of the
7705 * (*i*+1)-th mesh within the result mesh.
7706 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7707 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7708 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7709 * is no more needed.
7710 * \throw If \a a.size() == 0.
7711 * \throw If \a a[ *i* ] == NULL.
7712 * \throw If the meshes do not share the node coordinates array.
7713 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7714 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7716 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7719 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7720 for(std::size_t ii=0;ii<meshes.size();ii++)
7723 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7724 throw INTERP_KERNEL::Exception(oss.str().c_str());
7726 const DataArrayDouble *coords=meshes.front()->getCoords();
7727 int meshDim=meshes.front()->getMeshDimension();
7728 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7730 int meshIndexLgth=0;
7731 for(;iter!=meshes.end();iter++)
7733 if(coords!=(*iter)->getCoords())
7734 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7735 if(meshDim!=(*iter)->getMeshDimension())
7736 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7737 meshLgth+=(*iter)->getMeshLength();
7738 meshIndexLgth+=(*iter)->getNumberOfCells();
7740 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7741 nodal->alloc(meshLgth,1);
7742 int *nodalPtr=nodal->getPointer();
7743 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7744 nodalIndex->alloc(meshIndexLgth+1,1);
7745 int *nodalIndexPtr=nodalIndex->getPointer();
7747 for(iter=meshes.begin();iter!=meshes.end();iter++)
7749 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7750 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7751 int nbOfCells=(*iter)->getNumberOfCells();
7752 int meshLgth2=(*iter)->getMeshLength();
7753 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7754 if(iter!=meshes.begin())
7755 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7757 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7760 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7761 ret->setName("merge");
7762 ret->setMeshDimension(meshDim);
7763 ret->setConnectivity(nodal,nodalIndex,true);
7764 ret->setCoords(coords);
7769 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7770 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7771 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7772 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7773 * New" mode are returned for each input mesh.
7774 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7775 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7776 * valid values [0,1,2], see zipConnectivityTraducer().
7777 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7778 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7779 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7781 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7782 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7783 * is no more needed.
7784 * \throw If \a meshes.size() == 0.
7785 * \throw If \a meshes[ *i* ] == NULL.
7786 * \throw If the meshes do not share the node coordinates array.
7787 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7788 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7789 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7790 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7792 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7794 //All checks are delegated to MergeUMeshesOnSameCoords
7795 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7796 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7797 corr.resize(meshes.size());
7798 std::size_t nbOfMeshes=meshes.size();
7800 const int *o2nPtr=o2n->getConstPointer();
7801 for(std::size_t i=0;i<nbOfMeshes;i++)
7803 DataArrayInt *tmp=DataArrayInt::New();
7804 int curNbOfCells=meshes[i]->getNumberOfCells();
7805 tmp->alloc(curNbOfCells,1);
7806 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7807 offset+=curNbOfCells;
7808 tmp->setName(meshes[i]->getName());
7815 * Makes all given meshes share the nodal connectivity array. The common connectivity
7816 * array is created by concatenating the connectivity arrays of all given meshes. All
7817 * the given meshes must be of the same space dimension but dimension of cells **can
7818 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7819 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7820 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7821 * \param [in,out] meshes - a vector of meshes to update.
7822 * \throw If any of \a meshes is NULL.
7823 * \throw If the coordinates array is not set in any of \a meshes.
7824 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7825 * \throw If \a meshes are of different space dimension.
7827 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7829 std::size_t sz=meshes.size();
7832 std::vector< const DataArrayDouble * > coords(meshes.size());
7833 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7834 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7838 (*it)->checkConnectivityFullyDefined();
7839 const DataArrayDouble *coo=(*it)->getCoords();
7844 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7845 oss << " has no coordinate array defined !";
7846 throw INTERP_KERNEL::Exception(oss.str().c_str());
7851 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7852 oss << " is null !";
7853 throw INTERP_KERNEL::Exception(oss.str().c_str());
7856 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7857 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7858 int offset=(*it)->getNumberOfNodes();
7859 (*it++)->setCoords(res);
7860 for(;it!=meshes.end();it++)
7862 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7863 (*it)->setCoords(res);
7864 (*it)->shiftNodeNumbersInConn(offset);
7865 offset+=oldNumberOfNodes;
7870 * Merges nodes coincident with a given precision within all given meshes that share
7871 * the nodal connectivity array. The given meshes **can be of different** mesh
7872 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7873 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7874 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7875 * \param [in,out] meshes - a vector of meshes to update.
7876 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7877 * \throw If any of \a meshes is NULL.
7878 * \throw If the \a meshes do not share the same node coordinates array.
7879 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7881 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7885 std::set<const DataArrayDouble *> s;
7886 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7889 s.insert((*it)->getCoords());
7892 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 !";
7893 throw INTERP_KERNEL::Exception(oss.str().c_str());
7898 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 !";
7899 throw INTERP_KERNEL::Exception(oss.str().c_str());
7901 const DataArrayDouble *coo=*(s.begin());
7905 DataArrayInt *comm,*commI;
7906 coo->findCommonTuples(eps,-1,comm,commI);
7907 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7908 int oldNbOfNodes=coo->getNumberOfTuples();
7910 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7911 if(oldNbOfNodes==newNbOfNodes)
7913 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7914 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7916 (*it)->renumberNodesInConn(o2n->getConstPointer());
7917 (*it)->setCoords(newCoords);
7922 * 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.
7923 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7924 * \param isQuad specifies the policy of connectivity.
7925 * @ret in/out parameter in which the result will be append
7927 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7929 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7930 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7931 ret.push_back(cm.getExtrudedType());
7932 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7935 case INTERP_KERNEL::NORM_POINT1:
7937 ret.push_back(connBg[1]);
7938 ret.push_back(connBg[1]+nbOfNodesPerLev);
7941 case INTERP_KERNEL::NORM_SEG2:
7943 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7944 ret.insert(ret.end(),conn,conn+4);
7947 case INTERP_KERNEL::NORM_SEG3:
7949 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7950 ret.insert(ret.end(),conn,conn+8);
7953 case INTERP_KERNEL::NORM_QUAD4:
7955 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7956 ret.insert(ret.end(),conn,conn+8);
7959 case INTERP_KERNEL::NORM_TRI3:
7961 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7962 ret.insert(ret.end(),conn,conn+6);
7965 case INTERP_KERNEL::NORM_TRI6:
7967 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,
7968 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7969 ret.insert(ret.end(),conn,conn+15);
7972 case INTERP_KERNEL::NORM_QUAD8:
7975 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7976 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7977 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7979 ret.insert(ret.end(),conn,conn+20);
7982 case INTERP_KERNEL::NORM_POLYGON:
7984 std::back_insert_iterator< std::vector<int> > ii(ret);
7985 std::copy(connBg+1,connEnd,ii);
7987 std::reverse_iterator<const int *> rConnBg(connEnd);
7988 std::reverse_iterator<const int *> rConnEnd(connBg+1);
7989 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7990 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7991 for(std::size_t i=0;i<nbOfRadFaces;i++)
7994 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7995 std::copy(conn,conn+4,ii);
8000 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8005 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8007 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8010 double v[3]={0.,0.,0.};
8011 std::size_t sz=std::distance(begin,end);
8016 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];
8017 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8018 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8020 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8022 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8023 // SEG3 forming a circle):
8024 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8026 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8027 for(std::size_t j=0;j<sz;j++)
8029 if (j%2) // current point i is quadratic, next point i+1 is standard
8032 ip1 = (j+1)%sz; // ip1 = "i+1"
8034 else // current point i is standard, next point i+1 is quadratic
8039 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8040 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8041 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8043 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8049 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8051 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8053 std::vector<std::pair<int,int> > edges;
8054 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8055 const int *bgFace=begin;
8056 for(std::size_t i=0;i<nbOfFaces;i++)
8058 const int *endFace=std::find(bgFace+1,end,-1);
8059 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8060 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8062 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8063 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8065 edges.push_back(p1);
8069 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8073 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8075 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8077 double vec0[3],vec1[3];
8078 std::size_t sz=std::distance(begin,end);
8080 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8081 int nbOfNodes=(int)sz/2;
8082 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8083 const double *pt0=coords+3*begin[0];
8084 const double *pt1=coords+3*begin[nbOfNodes];
8085 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8086 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8089 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8091 std::size_t sz=std::distance(begin,end);
8092 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8093 std::size_t nbOfNodes(sz/2);
8094 std::copy(begin,end,(int *)tmp);
8095 for(std::size_t j=1;j<nbOfNodes;j++)
8097 begin[j]=tmp[nbOfNodes-j];
8098 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8102 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8104 std::size_t sz=std::distance(begin,end);
8106 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8107 double vec0[3],vec1[3];
8108 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8109 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];
8110 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;
8113 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8115 std::size_t sz=std::distance(begin,end);
8117 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8119 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8120 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8121 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8125 * 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 )
8126 * 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
8129 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8130 * \param [in] coords the coordinates with nb of components exactly equal to 3
8131 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8132 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8133 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8135 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8137 int nbFaces=std::count(begin+1,end,-1)+1;
8138 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8139 double *vPtr=v->getPointer();
8140 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8141 double *pPtr=p->getPointer();
8142 const int *stFaceConn=begin+1;
8143 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8145 const int *endFaceConn=std::find(stFaceConn,end,-1);
8146 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8147 stFaceConn=endFaceConn+1;
8149 pPtr=p->getPointer(); vPtr=v->getPointer();
8150 DataArrayInt *comm1=0,*commI1=0;
8151 v->findCommonTuples(eps,-1,comm1,commI1);
8152 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8153 const int *comm1Ptr=comm1->getConstPointer();
8154 const int *commI1Ptr=commI1->getConstPointer();
8155 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8156 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8158 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8159 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8160 mm->finishInsertingCells();
8162 for(int i=0;i<nbOfGrps1;i++)
8164 int vecId=comm1Ptr[commI1Ptr[i]];
8165 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8166 DataArrayInt *comm2=0,*commI2=0;
8167 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8168 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8169 const int *comm2Ptr=comm2->getConstPointer();
8170 const int *commI2Ptr=commI2->getConstPointer();
8171 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8172 for(int j=0;j<nbOfGrps2;j++)
8174 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8176 res->insertAtTheEnd(begin,end);
8177 res->pushBackSilent(-1);
8181 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8182 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8183 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8184 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8185 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8186 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8187 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8188 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8189 const int *idsNodePtr=idsNode->getConstPointer();
8190 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];
8191 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8192 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8193 if(std::abs(norm)>eps)
8195 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8196 mm3->rotate(center,vec,angle);
8198 mm3->changeSpaceDimension(2);
8199 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8200 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8201 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8202 int nbOfCells=mm4->getNumberOfCells();
8203 for(int k=0;k<nbOfCells;k++)
8206 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8207 res->pushBackSilent(idsNodePtr[*work]);
8208 res->pushBackSilent(-1);
8213 res->popBackSilent();
8217 * 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
8218 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8220 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8221 * \param [in] coords coordinates expected to have 3 components.
8222 * \param [in] begin start of the nodal connectivity of the face.
8223 * \param [in] end end of the nodal connectivity (excluded) of the face.
8224 * \param [out] v the normalized vector of size 3
8225 * \param [out] p the pos of plane
8227 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8229 std::size_t nbPoints=std::distance(begin,end);
8231 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8232 double vec[3]={0.,0.,0.};
8234 bool refFound=false;
8235 for(;j<nbPoints-1 && !refFound;j++)
8237 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8238 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8239 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8240 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8244 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8247 for(std::size_t i=j;i<nbPoints-1;i++)
8250 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8251 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8252 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8253 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8256 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8257 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];
8258 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8261 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8262 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8266 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8270 * This method tries to obtain a well oriented polyhedron.
8271 * If the algorithm fails, an exception will be thrown.
8273 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8275 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8276 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8277 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8279 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8280 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8281 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8283 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8286 std::size_t smthChanged=0;
8287 for(std::size_t i=0;i<nbOfFaces;i++)
8289 endFace=std::find(bgFace+1,end,-1);
8290 nbOfEdgesInFace=std::distance(bgFace,endFace);
8294 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8296 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8297 std::pair<int,int> p2(p1.second,p1.first);
8298 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8299 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8300 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8305 std::reverse(bgFace+1,endFace);
8306 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8308 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8309 std::pair<int,int> p2(p1.second,p1.first);
8310 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8311 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8312 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8313 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8314 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8315 if(it!=edgesOK.end())
8318 edgesFinished.push_back(p1);
8321 edgesOK.push_back(p1);
8328 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8330 if(!edgesOK.empty())
8331 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8332 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8333 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8335 for(std::size_t i=0;i<nbOfFaces;i++)
8337 endFace=std::find(bgFace+1,end,-1);
8338 std::reverse(bgFace+1,endFace);
8344 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8346 int nbOfNodesExpected(skin->getNumberOfNodes());
8347 const int *n2oPtr(n2o->getConstPointer());
8348 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8349 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8350 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8351 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8352 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8353 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8354 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8355 if(nbOfNodesExpected<1)
8357 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8358 *work++=n2oPtr[prevNode];
8359 for(int i=1;i<nbOfNodesExpected;i++)
8361 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8363 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8364 conn.erase(prevNode);
8367 int curNode(*(conn.begin()));
8368 *work++=n2oPtr[curNode];
8369 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8370 shar.erase(prevCell);
8373 prevCell=*(shar.begin());
8377 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8380 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8383 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8388 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8390 int nbOfNodesExpected(skin->getNumberOfNodes());
8391 int nbOfTurn(nbOfNodesExpected/2);
8392 const int *n2oPtr(n2o->getConstPointer());
8393 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8394 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8395 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8396 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8397 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8398 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8399 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8400 if(nbOfNodesExpected<1)
8402 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8403 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8404 for(int i=1;i<nbOfTurn;i++)
8406 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8408 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8409 conn.erase(prevNode);
8412 int curNode(*(conn.begin()));
8413 *work=n2oPtr[curNode];
8414 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8415 shar.erase(prevCell);
8418 int curCell(*(shar.begin()));
8419 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8425 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8428 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8431 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8437 * This method makes the assumption spacedimension == meshdimension == 2.
8438 * This method works only for linear cells.
8440 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8442 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8444 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8445 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8446 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8447 int oldNbOfNodes(skin->getNumberOfNodes());
8448 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8449 int nbOfNodesExpected(skin->getNumberOfNodes());
8450 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8451 int nbCells(skin->getNumberOfCells());
8452 if(nbCells==nbOfNodesExpected)
8453 return buildUnionOf2DMeshLinear(skin,n2o);
8454 else if(2*nbCells==nbOfNodesExpected)
8455 return buildUnionOf2DMeshQuadratic(skin,n2o);
8457 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8461 * This method makes the assumption spacedimension == meshdimension == 3.
8462 * This method works only for linear cells.
8464 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8466 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8468 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8469 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8470 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8471 const int *conn=m->getNodalConnectivity()->getConstPointer();
8472 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8473 int nbOfCells=m->getNumberOfCells();
8474 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8475 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8478 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8479 for(int i=1;i<nbOfCells;i++)
8482 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8488 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8489 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8491 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8495 for(int i=0;i<nbOfNodesInCell;i++)
8496 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8497 else if(spaceDim==2)
8499 for(int i=0;i<nbOfNodesInCell;i++)
8501 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8506 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8509 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8511 int nbOfCells=getNumberOfCells();
8513 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8514 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,36,4};
8515 ofs << " <" << getVTKDataSetType() << ">\n";
8516 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8517 ofs << " <PointData>\n" << pointData << std::endl;
8518 ofs << " </PointData>\n";
8519 ofs << " <CellData>\n" << cellData << std::endl;
8520 ofs << " </CellData>\n";
8521 ofs << " <Points>\n";
8522 if(getSpaceDimension()==3)
8523 _coords->writeVTK(ofs,8,"Points",byteData);
8526 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8527 coo->writeVTK(ofs,8,"Points",byteData);
8529 ofs << " </Points>\n";
8530 ofs << " <Cells>\n";
8531 const int *cPtr=_nodal_connec->getConstPointer();
8532 const int *cIPtr=_nodal_connec_index->getConstPointer();
8533 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8534 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8535 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8536 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8537 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8538 int szFaceOffsets=0,szConn=0;
8539 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8542 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8545 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8546 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8550 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8551 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8552 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8553 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8554 w4=std::copy(c.begin(),c.end(),w4);
8557 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8558 types->writeVTK(ofs,8,"UInt8","types",byteData);
8559 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8560 if(szFaceOffsets!=0)
8561 {//presence of Polyhedra
8562 connectivity->reAlloc(szConn);
8563 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8564 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8565 w1=faces->getPointer();
8566 for(int i=0;i<nbOfCells;i++)
8567 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8569 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8571 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8572 for(int j=0;j<nbFaces;j++)
8574 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8575 *w1++=(int)std::distance(w6,w5);
8576 w1=std::copy(w6,w5,w1);
8580 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8582 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8583 ofs << " </Cells>\n";
8584 ofs << " </Piece>\n";
8585 ofs << " </" << getVTKDataSetType() << ">\n";
8588 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8590 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8592 { stream << " Not set !"; return ; }
8593 stream << " Mesh dimension : " << _mesh_dim << ".";
8597 { stream << " No coordinates set !"; return ; }
8598 if(!_coords->isAllocated())
8599 { stream << " Coordinates set but not allocated !"; return ; }
8600 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8601 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8602 if(!_nodal_connec_index)
8603 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8604 if(!_nodal_connec_index->isAllocated())
8605 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8606 int lgth=_nodal_connec_index->getNumberOfTuples();
8607 int cpt=_nodal_connec_index->getNumberOfComponents();
8608 if(cpt!=1 || lgth<1)
8610 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8613 std::string MEDCouplingUMesh::getVTKDataSetType() const
8615 return std::string("UnstructuredGrid");
8619 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8620 * returns a result mesh constituted by polygons.
8621 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8622 * all nodes from m2.
8623 * The meshes should be in 2D space. In
8624 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8626 * \param [in] m1 - the first input mesh which is a partitioned object.
8627 * \param [in] m2 - the second input mesh which is a partition tool.
8628 * \param [in] eps - precision used to detect coincident mesh entities.
8629 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8630 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8631 * this array using decrRef() as it is no more needed.
8632 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8633 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8634 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8635 * any cell of \a m2. The caller is to delete this array using decrRef() as
8636 * it is no more needed.
8637 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8638 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8639 * is no more needed.
8640 * \throw If the coordinates array is not set in any of the meshes.
8641 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8642 * \throw If any of the meshes is not a 2D mesh in 2D space.
8644 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8645 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8647 m1->checkFullyDefined();
8648 m2->checkFullyDefined();
8649 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8650 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8652 // Step 1: compute all edge intersections (new nodes)
8653 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8654 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8655 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8656 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8657 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8658 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8659 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8660 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8661 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8662 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8663 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8664 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8666 // Step 2: re-order newly created nodes according to the ordering found in m2
8667 std::vector< std::vector<int> > intersectEdge2;
8668 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8669 subDiv2.clear(); dd5=0; dd6=0;
8672 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8673 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8674 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8675 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8677 // Step 4: Prepare final result:
8678 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8679 addCooDa->alloc((int)(addCoo.size())/2,2);
8680 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8681 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8682 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8683 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8684 std::vector<const DataArrayDouble *> coordss(4);
8685 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8686 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8687 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8688 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8689 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8690 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8691 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8692 ret->setConnectivity(conn,connI,true);
8693 ret->setCoords(coo);
8694 cellNb1=c1.retn(); cellNb2=c2.retn();
8700 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
8701 * (newly created) nodes corresponding to the edge intersections.
8703 * @param[out] cr, crI connectivity of the resulting mesh
8704 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
8705 * TODO: describe input parameters
8707 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8708 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8709 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8710 const std::vector<double>& addCoords,
8711 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8713 static const int SPACEDIM=2;
8714 const double *coo1=m1->getCoords()->getConstPointer();
8715 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8716 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8717 int offset1=m1->getNumberOfNodes();
8718 const double *coo2=m2->getCoords()->getConstPointer();
8719 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8720 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8721 int offset2=offset1+m2->getNumberOfNodes();
8722 int offset3=offset2+((int)addCoords.size())/2;
8723 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8724 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8725 // Here a BBTree on 2D-cells, not on segments:
8726 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8727 int ncell1=m1->getNumberOfCells();
8729 for(int i=0;i<ncell1;i++)
8731 std::vector<int> candidates2;
8732 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8733 std::map<INTERP_KERNEL::Node *,int> mapp;
8734 std::map<int,INTERP_KERNEL::Node *> mappRev;
8735 INTERP_KERNEL::QuadraticPolygon pol1;
8736 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8737 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8738 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
8739 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8740 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
8741 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8742 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8744 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
8745 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8746 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8747 for(it1.first();!it1.finished();it1.next())
8748 edges1.insert(it1.current()->getPtr());
8750 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
8751 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8753 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8755 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8756 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8757 // Complete mapping with elements coming from the current cell it2 in mesh2:
8758 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8759 // pol2 is the new QP in the final merged result.
8760 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8761 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
8764 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8766 pol1.initLocationsWithOther(pol2s[ii]);
8767 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8768 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8769 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8771 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
8772 // by m2 but that we still want to keep in the final result.
8777 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8779 catch(INTERP_KERNEL::Exception& e)
8781 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();
8782 throw INTERP_KERNEL::Exception(oss.str().c_str());
8785 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8786 (*it).second->decrRef();
8790 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<INTERP_KERNEL::Node *,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
8792 std::map<INTERP_KERNEL::Node *,int>::const_iterator it(m.find(n));
8794 throw INTERP_KERNEL::Exception("Internal error in remapping !");
8795 int v((*it).second);
8796 if(v==forbVal0 || v==forbVal1)
8798 if(std::find(isect.begin(),isect.end(),v)==isect.end())
8802 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<INTERP_KERNEL::Node *,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
8807 bool presenceOfOn(false);
8808 for(int i=0;i<sz;i++)
8810 INTERP_KERNEL::ElementaryEdge *e(c[i]);
8811 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
8813 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
8814 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
8816 return presenceOfOn;
8820 * This method split some of edges of 2D cells in \a this. The edges to be split are specified in \a subNodesInSeg and in \a subNodesInSegI using index storage mode.
8821 * To do the work this method can optionnaly needs information about middle of subedges for quadratic cases if a minimal creation of new nodes is wanted.
8822 * So this method try to reduce at most the number of new nodes. The only case that can lead this method to add nodes if a SEG3 is split without information of middle.
8823 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
8825 * \return int - the number of new nodes created (in most of cases 0).
8827 * \throw If \a this is not coherent.
8828 * \throw If \a this has not spaceDim equal to 2.
8829 * \throw If \a this has not meshDim equal to 2.
8830 * \throw If some subcells needed to be split are orphan.
8831 * \sa MEDCouplingUMesh::conformize2D
8833 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
8835 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
8836 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
8837 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
8838 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
8839 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
8840 if(midOpt==0 && midOptI==0)
8842 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
8845 else if(midOpt!=0 && midOptI!=0)
8846 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
8848 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
8852 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
8853 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
8854 * This method performs a conformization of \b this. So if a edge in \a this can be split into entire edges in \a this this method
8855 * will suppress such edges to use sub edges in \a this. So this method does not add nodes in \a this if merged edges have same nature each other (Linear,Quadratic).
8856 * Whatever the returned value, this method does not alter the order of cells in \a this neither the orientation of cells.
8857 * The modified cells if any are systematically declared as NORM_POLYGON or NORM_QPOLYG depending on the
8859 * This method expects that \b this has a meshDim equal 2 and spaceDim equal to 2 too.
8860 * This method expects that all nodes in \a this are not closer than \a eps.
8861 * If it is not the case you can invoke MEDCouplingUMesh::mergeNodes before calling this method.
8863 * \param [in] eps the relative error to detect merged edges.
8864 * \return DataArrayInt * - The list of cellIds in \a this that have been subdivided. If empty, nothing changed in \a this (as if it were a const method). The array is a newly allocated array
8865 * that the user is expected to deal with.
8867 * \throw If \a this is not coherent.
8868 * \throw If \a this has not spaceDim equal to 2.
8869 * \throw If \a this has not meshDim equal to 2.
8870 * \sa MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::split2DCells
8872 DataArrayInt *MEDCouplingUMesh::conformize2D(double eps)
8874 static const int SPACEDIM=2;
8876 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
8877 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
8878 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),descIndx1(DataArrayInt::New()),revDesc1(DataArrayInt::New()),revDescIndx1(DataArrayInt::New());
8879 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc(buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1));
8880 const int *c(mDesc->getNodalConnectivity()->getConstPointer()),*ci(mDesc->getNodalConnectivityIndex()->getConstPointer()),*rd(revDesc1->getConstPointer()),*rdi(revDescIndx1->getConstPointer());
8881 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(mDesc->getBoundingBoxForBBTree());
8882 const double *bbox(bboxArr->begin()),*coords(getCoords()->begin());
8883 int nCell(getNumberOfCells()),nDescCell(mDesc->getNumberOfCells());
8884 std::vector< std::vector<int> > intersectEdge(nDescCell),overlapEdge(nDescCell);
8885 std::vector<double> addCoo;
8886 BBTree<SPACEDIM,int> myTree(bbox,0,0,nDescCell,-eps);
8887 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8888 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8889 for(int i=0;i<nDescCell;i++)
8891 std::vector<int> candidates;
8892 myTree.getIntersectingElems(bbox+i*2*SPACEDIM,candidates);
8893 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
8896 std::map<INTERP_KERNEL::Node *,int> m;
8897 INTERP_KERNEL::Edge *e1(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m)),
8898 *e2(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[*it]],c+ci[*it]+1,coords,m));
8899 INTERP_KERNEL::MergePoints merge;
8900 INTERP_KERNEL::QuadraticPolygon c1,c2;
8901 e1->intersectWith(e2,merge,c1,c2);
8902 e1->decrRef(); e2->decrRef();
8903 if(IKGeo2DInternalMapper(c1,m,c[ci[i]+1],c[ci[i]+2],intersectEdge[i]))
8904 overlapEdge[i].push_back(*it);
8905 if(IKGeo2DInternalMapper(c2,m,c[ci[*it]+1],c[ci[*it]+2],intersectEdge[*it]))
8906 overlapEdge[*it].push_back(i);
8907 for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it2=m.begin();it2!=m.end();it2++)
8908 (*it2).first->decrRef();
8911 // splitting done. sort intersect point in intersectEdge.
8912 std::vector< std::vector<int> > middle(nDescCell);
8913 int nbOf2DCellsToBeSplit(0);
8914 bool middleNeedsToBeUsed(false);
8915 std::vector<bool> cells2DToTreat(nDescCell,false);
8916 for(int i=0;i<nDescCell;i++)
8918 std::vector<int>& isect(intersectEdge[i]);
8919 int sz((int)isect.size());
8922 std::map<INTERP_KERNEL::Node *,int> m;
8923 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2((INTERP_KERNEL::NormalizedCellType)c[ci[i]],c+ci[i]+1,coords,m));
8924 e->sortSubNodesAbs(coords,isect);
8926 for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it2=m.begin();it2!=m.end();it2++)
8927 (*it2).first->decrRef();
8931 int idx0(rdi[i]),idx1(rdi[i+1]);
8933 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::conformize2D : internal error #0 !");
8934 if(!cells2DToTreat[rd[idx0]])
8936 cells2DToTreat[rd[idx0]]=true;
8937 nbOf2DCellsToBeSplit++;
8939 // try to reuse at most eventual 'middle' of SEG3
8940 std::vector<int>& mid(middle[i]);
8941 mid.resize(sz+1,-1);
8942 if((INTERP_KERNEL::NormalizedCellType)c[ci[i]]==INTERP_KERNEL::NORM_SEG3)
8944 middleNeedsToBeUsed=true;
8945 const std::vector<int>& candidates(overlapEdge[i]);
8946 std::vector<int> trueCandidates;
8947 for(std::vector<int>::const_iterator itc=candidates.begin();itc!=candidates.end();itc++)
8948 if((INTERP_KERNEL::NormalizedCellType)c[ci[*itc]]==INTERP_KERNEL::NORM_SEG3)
8949 trueCandidates.push_back(*itc);
8950 int stNode(c[ci[i]+1]),endNode(isect[0]);
8951 for(int j=0;j<sz+1;j++)
8953 for(std::vector<int>::const_iterator itc=trueCandidates.begin();itc!=trueCandidates.end();itc++)
8955 int tmpSt(c[ci[*itc]+1]),tmpEnd(c[ci[*itc]+2]);
8956 if((tmpSt==stNode && tmpEnd==endNode) || (tmpSt==endNode && tmpEnd==stNode))
8957 { mid[j]=*itc; break; }
8960 endNode=j<sz-1?isect[j+1]:c[ci[i]+2];
8965 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()),notRet(DataArrayInt::New()); ret->alloc(nbOf2DCellsToBeSplit,1);
8966 if(nbOf2DCellsToBeSplit==0)
8969 int *retPtr(ret->getPointer());
8970 for(int i=0;i<nCell;i++)
8971 if(cells2DToTreat[i])
8974 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> mSafe,nSafe,oSafe,pSafe,qSafe,rSafe;
8975 DataArrayInt *m(0),*n(0),*o(0),*p(0),*q(0),*r(0);
8976 MEDCouplingUMesh::ExtractFromIndexedArrays(ret->begin(),ret->end(),desc1,descIndx1,m,n); mSafe=m; nSafe=n;
8977 DataArrayInt::PutIntoToSkylineFrmt(intersectEdge,o,p); oSafe=o; pSafe=p;
8978 if(middleNeedsToBeUsed)
8979 { DataArrayInt::PutIntoToSkylineFrmt(middle,q,r); qSafe=q; rSafe=r; }
8980 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> modif(static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(ret->begin(),ret->end(),true)));
8981 int nbOfNodesCreated(modif->split2DCells(mSafe,nSafe,oSafe,pSafe,qSafe,rSafe));
8982 setCoords(modif->getCoords());//if nbOfNodesCreated==0 modif and this have the same coordinates pointer so this line has no effect. But for quadratic cases this line is important.
8983 setPartOfMySelf(ret->begin(),ret->end(),*modif);
8985 bool areNodesMerged; int newNbOfNodes;
8986 if(nbOfNodesCreated!=0)
8987 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp(mergeNodes(eps,areNodesMerged,newNbOfNodes));
8993 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8994 * It builds the descending connectivity of the two meshes, and then using a binary tree
8995 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
8996 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
8998 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8999 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
9000 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
9001 std::vector<double>& addCoo,
9002 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
9003 throw(INTERP_KERNEL::Exception)
9005 static const int SPACEDIM=2;
9006 // Build desc connectivity
9007 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
9008 desc2=DataArrayInt::New();
9009 descIndx2=DataArrayInt::New();
9010 revDesc2=DataArrayInt::New();
9011 revDescIndx2=DataArrayInt::New();
9012 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9013 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
9014 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
9015 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
9016 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
9017 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
9018 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
9020 // Build BB tree of all edges in the tool mesh (second mesh)
9021 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
9022 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9023 int nDescCell1=m1Desc->getNumberOfCells();
9024 int nDescCell2=m2Desc->getNumberOfCells();
9025 intersectEdge1.resize(nDescCell1);
9026 colinear2.resize(nDescCell2);
9027 subDiv2.resize(nDescCell2);
9028 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
9030 std::vector<int> candidates1(1);
9031 int offset1=m1->getNumberOfNodes();
9032 int offset2=offset1+m2->getNumberOfNodes();
9033 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
9035 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
9036 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9037 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
9039 std::map<INTERP_KERNEL::Node *,int> map1,map2;
9040 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
9041 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
9043 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
9044 // This following part is to avoid that some removed nodes (for example due to a merge between pol1 and pol2) are replaced by a newly created one
9045 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
9046 std::set<INTERP_KERNEL::Node *> nodes;
9047 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
9048 std::size_t szz(nodes.size());
9049 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
9050 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
9051 for(std::size_t iii=0;iii<szz;iii++,itt++)
9052 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
9053 // end of protection
9054 // Performs egde cutting:
9055 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
9060 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
9062 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
9063 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
9067 * This method performs the 2nd step of Partition of 2D mesh.
9068 * This method has 4 inputs :
9069 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
9070 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
9071 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
9072 * The aim of this method is to sort the splitting nodes, if any, and to put them in 'intersectEdge' output parameter based on edges of mesh 'm2'
9073 * Nodes end up lying consecutively on a cutted edge.
9074 * \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.
9075 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
9076 * \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.
9077 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
9078 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
9080 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9081 const std::vector<double>& addCoo,
9082 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
9084 int offset1=m1->getNumberOfNodes();
9085 int ncell=m2->getNumberOfCells();
9086 const int *c=m2->getNodalConnectivity()->getConstPointer();
9087 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
9088 const double *coo=m2->getCoords()->getConstPointer();
9089 const double *cooBis=m1->getCoords()->getConstPointer();
9090 int offset2=offset1+m2->getNumberOfNodes();
9091 intersectEdge.resize(ncell);
9092 for(int i=0;i<ncell;i++,cI++)
9094 const std::vector<int>& divs=subDiv[i];
9095 int nnode=cI[1]-cI[0]-1;
9096 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
9097 std::map<INTERP_KERNEL::Node *, int> mapp22;
9098 for(int j=0;j<nnode;j++)
9100 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
9101 int nnid=c[(*cI)+j+1];
9102 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
9103 mapp22[nn]=nnid+offset1;
9105 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
9106 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
9107 ((*it).second.first)->decrRef();
9108 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
9109 std::map<INTERP_KERNEL::Node *,int> mapp3;
9110 for(std::size_t j=0;j<divs.size();j++)
9113 INTERP_KERNEL::Node *tmp=0;
9115 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
9117 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
9119 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
9123 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
9124 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
9131 * 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).
9132 * 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
9133 * with a plane. The result will be put in 'cut3DSuf' out parameter.
9134 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
9135 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
9136 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
9137 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
9138 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
9139 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
9140 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
9141 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
9142 * \param [out] cut3DSuf input/output param.
9144 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
9145 const int *nodal3DCurve, const int *nodalIndx3DCurve,
9146 const int *desc, const int *descIndx,
9147 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
9149 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
9150 int nbOf3DSurfCell=(int)cut3DSurf.size();
9151 for(int i=0;i<nbOf3DSurfCell;i++)
9153 std::vector<int> res;
9154 int offset=descIndx[i];
9155 int nbOfSeg=descIndx[i+1]-offset;
9156 for(int j=0;j<nbOfSeg;j++)
9158 int edgeId=desc[offset+j];
9159 int status=cut3DCurve[edgeId];
9163 res.push_back(status);
9166 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
9167 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
9175 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9181 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
9182 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
9185 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9189 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
9194 {// case when plane is on a multi colinear edge of a polyhedron
9195 if((int)res.size()==2*nbOfSeg)
9197 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
9200 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
9207 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
9208 * 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).
9209 * 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
9210 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
9211 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
9212 * \param desc is the descending connectivity 3D->3DSurf
9213 * \param descIndx is the descending connectivity index 3D->3DSurf
9215 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
9216 const int *desc, const int *descIndx,
9217 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
9219 checkFullyDefined();
9220 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9221 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
9222 const int *nodal3D=_nodal_connec->getConstPointer();
9223 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
9224 int nbOfCells=getNumberOfCells();
9225 for(int i=0;i<nbOfCells;i++)
9227 std::map<int, std::set<int> > m;
9228 int offset=descIndx[i];
9229 int nbOfFaces=descIndx[i+1]-offset;
9232 for(int j=0;j<nbOfFaces;j++)
9234 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
9235 if(p.first!=-1 && p.second!=-1)
9239 start=p.first; end=p.second;
9240 m[p.first].insert(p.second);
9241 m[p.second].insert(p.first);
9245 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
9246 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
9247 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
9248 INTERP_KERNEL::NormalizedCellType cmsId;
9249 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
9250 start=tmp[0]; end=tmp[nbOfNodesSon-1];
9251 for(unsigned k=0;k<nbOfNodesSon;k++)
9253 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
9254 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
9261 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
9265 std::map<int, std::set<int> >::const_iterator it=m.find(start);
9266 const std::set<int>& s=(*it).second;
9267 std::set<int> s2; s2.insert(prev);
9269 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
9272 int val=*s3.begin();
9273 conn.push_back(start);
9280 conn.push_back(end);
9283 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
9284 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
9285 cellIds->pushBackSilent(i);
9291 * 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
9292 * 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
9293 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
9294 * 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
9295 * 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.
9297 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
9299 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
9301 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
9304 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
9305 if(cm.getDimension()==2)
9307 const int *node=nodalConnBg+1;
9308 int startNode=*node++;
9309 double refX=coords[2*startNode];
9310 for(;node!=nodalConnEnd;node++)
9312 if(coords[2*(*node)]<refX)
9315 refX=coords[2*startNode];
9318 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
9322 double angle0=-M_PI/2;
9327 double angleNext=0.;
9328 while(nextNode!=startNode)
9332 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
9334 if(*node!=tmpOut.back() && *node!=prevNode)
9336 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
9337 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
9342 res=angle0-angleM+2.*M_PI;
9351 if(nextNode!=startNode)
9353 angle0=angleNext-M_PI;
9356 prevNode=tmpOut.back();
9357 tmpOut.push_back(nextNode);
9360 std::vector<int> tmp3(2*(sz-1));
9361 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
9362 std::copy(nodalConnBg+1,nodalConnEnd,it);
9363 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
9365 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9368 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
9370 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9375 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
9376 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
9381 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9384 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9388 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
9389 * 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.
9391 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
9392 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
9393 * \param [in,out] arr array in which the remove operation will be done.
9394 * \param [in,out] arrIndx array in the remove operation will modify
9395 * \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])
9396 * \return true if \b arr and \b arrIndx have been modified, false if not.
9398 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
9400 if(!arrIndx || !arr)
9401 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
9402 if(offsetForRemoval<0)
9403 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
9404 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
9405 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
9406 int *arrIPtr=arrIndx->getPointer();
9409 const int *arrPtr=arr->getConstPointer();
9410 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
9411 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
9413 if(*arrIPtr-previousArrI>offsetForRemoval)
9415 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
9417 if(s.find(*work)==s.end())
9418 arrOut.push_back(*work);
9421 previousArrI=*arrIPtr;
9422 *arrIPtr=(int)arrOut.size();
9424 if(arr->getNumberOfTuples()==(int)arrOut.size())
9426 arr->alloc((int)arrOut.size(),1);
9427 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
9432 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9433 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
9434 * The selection of extraction is done standardly in new2old format.
9435 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9437 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9438 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9439 * \param [in] arrIn arr origin array from which the extraction will be done.
9440 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9441 * \param [out] arrOut the resulting array
9442 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9443 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
9445 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9446 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9448 if(!arrIn || !arrIndxIn)
9449 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
9450 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9451 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9452 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
9453 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
9454 const int *arrInPtr=arrIn->getConstPointer();
9455 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9456 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9458 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9459 int maxSizeOfArr=arrIn->getNumberOfTuples();
9460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9461 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9462 arrIo->alloc((int)(sz+1),1);
9463 const int *idsIt=idsOfSelectBg;
9464 int *work=arrIo->getPointer();
9467 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
9469 if(*idsIt>=0 && *idsIt<nbOfGrps)
9470 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
9473 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9474 throw INTERP_KERNEL::Exception(oss.str().c_str());
9480 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
9481 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
9482 throw INTERP_KERNEL::Exception(oss.str().c_str());
9485 arro->alloc(lgth,1);
9486 work=arro->getPointer();
9487 idsIt=idsOfSelectBg;
9488 for(std::size_t i=0;i<sz;i++,idsIt++)
9490 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
9491 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
9494 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
9495 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9496 throw INTERP_KERNEL::Exception(oss.str().c_str());
9500 arrIndexOut=arrIo.retn();
9504 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9505 * 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 ).
9506 * The selection of extraction is done standardly in new2old format.
9507 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9509 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9510 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9511 * \param [in] arrIn arr origin array from which the extraction will be done.
9512 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9513 * \param [out] arrOut the resulting array
9514 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9515 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
9517 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9518 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9520 if(!arrIn || !arrIndxIn)
9521 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
9522 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9523 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9524 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
9525 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
9526 const int *arrInPtr=arrIn->getConstPointer();
9527 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9528 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9530 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9531 int maxSizeOfArr=arrIn->getNumberOfTuples();
9532 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9533 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9534 arrIo->alloc((int)(sz+1),1);
9535 int idsIt=idsOfSelectStart;
9536 int *work=arrIo->getPointer();
9539 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
9541 if(idsIt>=0 && idsIt<nbOfGrps)
9542 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
9545 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9546 throw INTERP_KERNEL::Exception(oss.str().c_str());
9552 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
9553 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
9554 throw INTERP_KERNEL::Exception(oss.str().c_str());
9557 arro->alloc(lgth,1);
9558 work=arro->getPointer();
9559 idsIt=idsOfSelectStart;
9560 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
9562 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
9563 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
9566 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
9567 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9568 throw INTERP_KERNEL::Exception(oss.str().c_str());
9572 arrIndexOut=arrIo.retn();
9576 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9577 * 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
9578 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9579 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9581 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9582 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9583 * \param [in] arrIn arr origin array from which the extraction will be done.
9584 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9585 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
9586 * \param [in] srcArrIndex index array of \b srcArr
9587 * \param [out] arrOut the resulting array
9588 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9590 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9592 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9593 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9594 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9596 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9597 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9598 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9599 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9600 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9601 std::vector<bool> v(nbOfTuples,true);
9603 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9604 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9605 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9607 if(*it>=0 && *it<nbOfTuples)
9610 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9614 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9615 throw INTERP_KERNEL::Exception(oss.str().c_str());
9618 srcArrIndexPtr=srcArrIndex->getConstPointer();
9619 arrIo->alloc(nbOfTuples+1,1);
9620 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9621 const int *arrInPtr=arrIn->getConstPointer();
9622 const int *srcArrPtr=srcArr->getConstPointer();
9623 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9624 int *arroPtr=arro->getPointer();
9625 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9629 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9630 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9634 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9635 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9636 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9640 arrIndexOut=arrIo.retn();
9644 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9645 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9647 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9648 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9649 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9650 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9651 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
9652 * \param [in] srcArrIndex index array of \b srcArr
9654 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9656 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9657 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9659 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9660 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9661 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9662 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9663 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9664 int *arrInOutPtr=arrInOut->getPointer();
9665 const int *srcArrPtr=srcArr->getConstPointer();
9666 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9668 if(*it>=0 && *it<nbOfTuples)
9670 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9671 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9674 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] !";
9675 throw INTERP_KERNEL::Exception(oss.str().c_str());
9680 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9681 throw INTERP_KERNEL::Exception(oss.str().c_str());
9687 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9688 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9689 * 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]].
9690 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9691 * A negative value in \b arrIn means that it is ignored.
9692 * 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.
9694 * \param [in] arrIn arr origin array from which the extraction will be done.
9695 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9696 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9697 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9699 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
9701 int seed=0,nbOfDepthPeelingPerformed=0;
9702 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9706 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9707 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9708 * 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]].
9709 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9710 * A negative value in \b arrIn means that it is ignored.
9711 * 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.
9712 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9713 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9714 * \param [in] arrIn arr origin array from which the extraction will be done.
9715 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9716 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9717 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9718 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9719 * \sa MEDCouplingUMesh::partitionBySpreadZone
9721 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9723 nbOfDepthPeelingPerformed=0;
9725 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9726 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9729 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9733 std::vector<bool> fetched(nbOfTuples,false);
9734 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9737 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9739 nbOfDepthPeelingPerformed=0;
9740 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9741 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9742 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9743 std::vector<bool> fetched2(nbOfTuples,false);
9745 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9747 if(*seedElt>=0 && *seedElt<nbOfTuples)
9748 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9750 { 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()); }
9752 const int *arrInPtr=arrIn->getConstPointer();
9753 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9754 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9755 std::vector<int> idsToFetch1(seedBg,seedEnd);
9756 std::vector<int> idsToFetch2;
9757 std::vector<int> *idsToFetch=&idsToFetch1;
9758 std::vector<int> *idsToFetchOther=&idsToFetch2;
9759 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9761 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9762 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9764 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9765 std::swap(idsToFetch,idsToFetchOther);
9766 idsToFetchOther->clear();
9767 nbOfDepthPeelingPerformed++;
9769 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9771 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9772 int *retPtr=ret->getPointer();
9773 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9780 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9781 * 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
9782 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9783 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9785 * \param [in] start begin of set of ids of the input extraction (included)
9786 * \param [in] end end of set of ids of the input extraction (excluded)
9787 * \param [in] step step of the set of ids in range mode.
9788 * \param [in] arrIn arr origin array from which the extraction will be done.
9789 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9790 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9791 * \param [in] srcArrIndex index array of \b srcArr
9792 * \param [out] arrOut the resulting array
9793 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9795 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9797 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9798 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9799 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9801 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9802 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9803 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9804 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9805 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9807 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9808 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9809 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9811 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9813 if(it>=0 && it<nbOfTuples)
9814 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9817 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9818 throw INTERP_KERNEL::Exception(oss.str().c_str());
9821 srcArrIndexPtr=srcArrIndex->getConstPointer();
9822 arrIo->alloc(nbOfTuples+1,1);
9823 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9824 const int *arrInPtr=arrIn->getConstPointer();
9825 const int *srcArrPtr=srcArr->getConstPointer();
9826 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9827 int *arroPtr=arro->getPointer();
9828 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9830 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9833 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9834 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9838 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9839 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9843 arrIndexOut=arrIo.retn();
9847 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9848 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9850 * \param [in] start begin of set of ids of the input extraction (included)
9851 * \param [in] end end of set of ids of the input extraction (excluded)
9852 * \param [in] step step of the set of ids in range mode.
9853 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9854 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9855 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9856 * \param [in] srcArrIndex index array of \b srcArr
9858 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9860 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9861 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9863 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9864 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9865 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9866 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9867 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9868 int *arrInOutPtr=arrInOut->getPointer();
9869 const int *srcArrPtr=srcArr->getConstPointer();
9870 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9872 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9874 if(it>=0 && it<nbOfTuples)
9876 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9877 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9880 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9881 throw INTERP_KERNEL::Exception(oss.str().c_str());
9886 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9887 throw INTERP_KERNEL::Exception(oss.str().c_str());
9893 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9894 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9895 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9896 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9897 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9899 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9901 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
9903 checkFullyDefined();
9904 int mdim=getMeshDimension();
9905 int spaceDim=getSpaceDimension();
9907 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9908 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9909 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9910 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9911 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9912 ret->setCoords(getCoords());
9913 ret->allocateCells((int)partition.size());
9915 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9917 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9918 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9922 cell=tmp->buildUnionOf2DMesh();
9925 cell=tmp->buildUnionOf3DMesh();
9928 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9931 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9934 ret->finishInsertingCells();
9939 * This method partitions \b this into contiguous zone.
9940 * This method only needs a well defined connectivity. Coordinates are not considered here.
9941 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9943 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
9945 int nbOfCellsCur=getNumberOfCells();
9946 std::vector<DataArrayInt *> ret;
9949 DataArrayInt *neigh=0,*neighI=0;
9950 computeNeighborsOfCells(neigh,neighI);
9951 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9952 std::vector<bool> fetchedCells(nbOfCellsCur,false);
9953 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9955 while(seed<nbOfCellsCur)
9957 int nbOfPeelPerformed=0;
9958 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9959 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9961 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9962 ret.push_back((*it).retn());
9967 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9968 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9970 * \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.
9971 * \return a newly allocated DataArrayInt to be managed by the caller.
9972 * \throw In case of \a code has not the right format (typically of size 3*n)
9974 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
9976 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9977 std::size_t nb=code.size()/3;
9978 if(code.size()%3!=0)
9979 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9980 ret->alloc((int)nb,2);
9981 int *retPtr=ret->getPointer();
9982 for(std::size_t i=0;i<nb;i++,retPtr+=2)
9984 retPtr[0]=code[3*i+2];
9985 retPtr[1]=code[3*i+2]+code[3*i+1];
9991 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
9992 * All cells in \a this are expected to be linear 3D cells.
9993 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
9994 * It leads to an increase to number of cells.
9995 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
9996 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
9997 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
9999 * \param [in] policy - the policy of splitting that must be in (PLANAR_FACE_5, PLANAR_FACE_6, GENERAL_24, GENERAL_48). The policy will be used only for INTERP_KERNEL::NORM_HEXA8 cells.
10000 * For all other cells, the splitting policy will be ignored.
10001 * \param [out] nbOfAdditionalPoints - number of nodes added to \c this->_coords. If > 0 a new coordinates object will be constructed result of the aggregation of the old one and the new points added.
10002 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
10003 * an id of old cell producing it. The caller is to delete this array using
10004 * decrRef() as it is no more needed.
10005 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
10007 * \warning This method operates on each cells in this independantly ! So it can leads to non conform mesh in returned value ! If you expect to have a conform mesh in output
10008 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
10010 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
10011 * \throw If \a this is not fully constituted with linear 3D cells.
10012 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
10014 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
10016 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
10017 checkConnectivityFullyDefined();
10018 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10019 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
10020 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
10021 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
10022 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
10023 int *retPt(ret->getPointer());
10024 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
10025 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
10026 const int *oldc(_nodal_connec->begin());
10027 const int *oldci(_nodal_connec_index->begin());
10028 const double *coords(_coords->begin());
10029 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
10031 std::vector<int> a; std::vector<double> b;
10032 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
10033 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
10034 const int *aa(&a[0]);
10037 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
10039 *it=(-(*(it))-1+nbNodes);
10040 addPts->insertAtTheEnd(b.begin(),b.end());
10041 nbNodes+=(int)b.size()/3;
10043 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
10044 newConn->insertAtTheEnd(aa,aa+4);
10046 if(!addPts->empty())
10048 addPts->rearrange(3);
10049 nbOfAdditionalPoints=addPts->getNumberOfTuples();
10050 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
10051 ret0->setCoords(addPts);
10055 nbOfAdditionalPoints=0;
10056 ret0->setCoords(getCoords());
10058 ret0->setNodalConnectivity(newConn);
10060 ret->computeOffsets2();
10061 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
10062 return ret0.retn();
10066 * It is the linear part of MEDCouplingUMesh::split2DCells. Here no additionnal nodes will be added in \b this. So coordinates pointer remain unchanged (is not even touch).
10068 * \sa MEDCouplingUMesh::split2DCells
10070 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
10072 checkConnectivityFullyDefined();
10073 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
10074 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10075 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10076 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10077 int prevPosOfCi(ciPtr[0]);
10078 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10080 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
10081 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
10082 for(int j=0;j<sz;j++)
10084 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
10085 for(int k=0;k<sz2;k++)
10086 *cPtr++=subPtr[offset2+k];
10088 *cPtr++=oldConn[prevPosOfCi+j+2];
10091 prevPosOfCi=ciPtr[1];
10092 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10095 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
10096 _nodal_connec->decrRef();
10097 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
10100 int internalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
10106 int ret(nodesCnter++);
10108 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
10109 addCoo.insertAtTheEnd(newPt,newPt+2);
10115 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
10117 * \return int - the number of new nodes created.
10118 * \sa MEDCouplingUMesh::split2DCells
10120 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
10123 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
10124 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10125 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
10126 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10127 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
10128 const double *oldCoordsPtr(getCoords()->begin());
10129 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10130 int prevPosOfCi(ciPtr[0]);
10131 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10133 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
10134 for(int j=0;j<sz;j++)
10135 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
10136 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
10137 for(int j=0;j<sz;j++)//loop over subedges of oldConn
10139 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
10143 cPtr[1]=oldConn[prevPosOfCi+2+j];
10144 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
10147 std::vector<INTERP_KERNEL::Node *> ns(3);
10148 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
10149 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
10150 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
10151 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
10152 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
10154 cPtr[1]=subPtr[offset2+k];
10155 cPtr[deltaSz]=internalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
10157 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
10159 { cPtr[1]=tmpEnd; }
10160 cPtr[deltaSz]=internalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
10162 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
10163 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10166 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
10167 _nodal_connec->decrRef();
10168 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
10169 addCoo->rearrange(2);
10170 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
10172 return addCoo->getNumberOfTuples();
10175 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
10176 _own_cell(true),_cell_id(-1),_nb_cell(0)
10181 _nb_cell=mesh->getNumberOfCells();
10185 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
10193 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
10194 _own_cell(false),_cell_id(bg-1),
10201 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
10204 if(_cell_id<_nb_cell)
10213 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
10219 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
10221 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
10224 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
10230 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
10238 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
10244 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
10249 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
10254 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
10256 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
10259 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
10264 _nb_cell=mesh->getNumberOfCells();
10268 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
10275 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
10277 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
10278 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
10279 if(_cell_id<_nb_cell)
10281 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
10282 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
10283 int startId=_cell_id;
10284 _cell_id+=nbOfElems;
10285 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
10291 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
10295 _conn=mesh->getNodalConnectivity()->getPointer();
10296 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
10300 void MEDCouplingUMeshCell::next()
10302 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10307 _conn_lgth=_conn_indx[1]-_conn_indx[0];
10310 std::string MEDCouplingUMeshCell::repr() const
10312 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10314 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
10316 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
10320 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
10323 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
10325 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10326 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
10328 return INTERP_KERNEL::NORM_ERROR;
10331 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
10334 if(_conn_lgth!=NOTICABLE_FIRST_VAL)