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)
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)
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
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)
4210 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.
4211 const double *coo=mDesc->getCoords()->getConstPointer();
4212 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4213 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4215 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4216 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4217 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4219 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4220 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4222 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4223 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4225 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4226 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4228 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4230 if((*it2).second.second)
4231 mapp[(*it2).second.first]=(*it2).first;
4232 ((*it2).second.first)->decrRef();
4237 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4241 int locId=nodeId-offset2;
4242 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4246 int locId=nodeId-offset1;
4247 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4249 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4253 * Construct a mapping between set of Nodes and the standart MEDCoupling connectivity format (c, cI).
4255 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4256 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4257 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4259 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4261 int eltId1=abs(*desc1)-1;
4262 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4264 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4265 if(it==mappRev.end())
4267 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4278 template<int SPACEDIM>
4279 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4280 double eps, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4282 elts=DataArrayInt::New(); eltsIndex=DataArrayInt::New(); eltsIndex->alloc(nbOfPoints+1,1); eltsIndex->setIJ(0,0,0); elts->alloc(0,1);
4283 int *eltsIndexPtr(eltsIndex->getPointer());
4284 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree(eps));
4285 const double *bbox(bboxArr->begin());
4286 int nbOfCells=getNumberOfCells();
4287 const int *conn=_nodal_connec->getConstPointer();
4288 const int *connI=_nodal_connec_index->getConstPointer();
4289 double bb[2*SPACEDIM];
4290 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4291 for(int i=0;i<nbOfPoints;i++)
4293 eltsIndexPtr[i+1]=eltsIndexPtr[i];
4294 for(int j=0;j<SPACEDIM;j++)
4296 bb[2*j]=pos[SPACEDIM*i+j];
4297 bb[2*j+1]=pos[SPACEDIM*i+j];
4299 std::vector<int> candidates;
4300 myTree.getIntersectingElems(bb,candidates);
4301 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4303 int sz(connI[(*iter)+1]-connI[*iter]-1);
4304 INTERP_KERNEL::NormalizedCellType ct((INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]]);
4306 if(ct!=INTERP_KERNEL::NORM_POLYGON && ct!=INTERP_KERNEL::NORM_QPOLYG)
4307 status=INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,ct,coords,conn+connI[*iter]+1,sz,eps);
4311 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPointsAlg : not implemented yet for POLYGON and QPOLYGON in spaceDim 3 !");
4312 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
4313 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
4314 std::vector<INTERP_KERNEL::Node *> nodes(sz);
4315 INTERP_KERNEL::QuadraticPolygon *pol(0);
4316 for(int j=0;j<sz;j++)
4318 int nodeId(conn[connI[*iter]+1+j]);
4319 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*SPACEDIM],coords[nodeId*SPACEDIM+1]);
4321 if(!INTERP_KERNEL::CellModel::GetCellModel(ct).isQuadratic())
4322 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
4324 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
4325 INTERP_KERNEL::Node *n(new INTERP_KERNEL::Node(pos[i*SPACEDIM],pos[i*SPACEDIM+1]));
4326 double a(0.),b(0.),c(0.);
4327 a=pol->normalizeMe(b,c); n->applySimilarity(b,c,a);
4328 status=pol->isInOrOut2(n);
4329 delete pol; n->decrRef();
4333 eltsIndexPtr[i+1]++;
4334 elts->pushBackSilent(*iter);
4340 * Finds cells in contact with several balls (i.e. points with precision).
4341 * This method is an extension of getCellContainingPoint() and
4342 * getCellsContainingPoint() for the case of multiple points.
4343 * 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.
4344 * If it is not the case, please change their types to INTERP_KERNEL::NORM_POLYGON or INTERP_KERNEL::NORM_QPOLYG before invoking this method.
4345 * \param [in] pos - an array of coordinates of points in full interlace mode :
4346 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4347 * this->getSpaceDimension() * \a nbOfPoints
4348 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4349 * \param [in] eps - radius of balls (i.e. the precision).
4350 * \param [out] elts - vector returning ids of found cells.
4351 * \param [out] eltsIndex - an array, of length \a nbOfPoints + 1,
4352 * dividing cell ids in \a elts into groups each referring to one
4353 * point. Its every element (except the last one) is an index pointing to the
4354 * first id of a group of cells. For example cells in contact with the *i*-th
4355 * point are described by following range of indices:
4356 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4357 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4358 * Number of cells in contact with the *i*-th point is
4359 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4360 * \throw If the coordinates array is not set.
4361 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4363 * \if ENABLE_EXAMPLES
4364 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4365 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4368 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4369 MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& elts, MEDCouplingAutoRefCountObjectPtr<DataArrayInt>& eltsIndex) const
4371 int spaceDim=getSpaceDimension();
4372 int mDim=getMeshDimension();
4377 const double *coords=_coords->getConstPointer();
4378 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4385 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4387 else if(spaceDim==2)
4391 const double *coords=_coords->getConstPointer();
4392 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4395 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4397 else if(spaceDim==1)
4401 const double *coords=_coords->getConstPointer();
4402 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4405 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4408 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4412 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4413 * least two its edges intersect each other anywhere except their extremities. An
4414 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4415 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4416 * cleared before filling in.
4417 * \param [in] eps - precision.
4418 * \throw If \a this->getMeshDimension() != 2.
4419 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4421 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4423 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4424 if(getMeshDimension()!=2)
4425 throw INTERP_KERNEL::Exception(msg);
4426 int spaceDim=getSpaceDimension();
4427 if(spaceDim!=2 && spaceDim!=3)
4428 throw INTERP_KERNEL::Exception(msg);
4429 const int *conn=_nodal_connec->getConstPointer();
4430 const int *connI=_nodal_connec_index->getConstPointer();
4431 int nbOfCells=getNumberOfCells();
4432 std::vector<double> cell2DinS2;
4433 for(int i=0;i<nbOfCells;i++)
4435 int offset=connI[i];
4436 int nbOfNodesForCell=connI[i+1]-offset-1;
4437 if(nbOfNodesForCell<=3)
4439 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4440 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4441 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4448 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4450 * 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.
4451 * 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.
4453 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4454 * This convex envelop is computed using Jarvis march algorithm.
4455 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4456 * 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)
4457 * 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.
4459 * \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.
4460 * \sa MEDCouplingUMesh::colinearize2D
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);
4778 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4784 * This method is private because not easy to use for end user. This method is const contrary to
4785 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4786 * the coords sorted slice by slice.
4787 * \param isQuad specifies presence of quadratic cells.
4789 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4791 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4792 int nbOf2DCells=getNumberOfCells();
4793 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4794 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4795 const int *conn=_nodal_connec->getConstPointer();
4796 const int *connI=_nodal_connec_index->getConstPointer();
4797 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4798 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4799 newConnI->alloc(nbOf3DCells+1,1);
4800 int *newConnIPtr=newConnI->getPointer();
4802 std::vector<int> newc;
4803 for(int j=0;j<nbOf2DCells;j++)
4805 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4806 *newConnIPtr++=(int)newc.size();
4808 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4809 int *newConnPtr=newConn->getPointer();
4810 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4811 newConnIPtr=newConnI->getPointer();
4812 for(int iz=0;iz<nbOf1DCells;iz++)
4815 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4816 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4818 int icell=(int)(iter-newc.begin());
4819 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4822 *newConnPtr=(*iter)+iz*deltaPerLev;
4827 *newConnPtr=(*iter);
4830 ret->setConnectivity(newConn,newConnI,true);
4831 ret->setCoords(getCoords());
4836 * Checks if \a this mesh is constituted by only quadratic cells.
4837 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4838 * \throw If the coordinates array is not set.
4839 * \throw If the nodal connectivity of cells is not defined.
4841 bool MEDCouplingUMesh::isFullyQuadratic() const
4843 checkFullyDefined();
4845 int nbOfCells=getNumberOfCells();
4846 for(int i=0;i<nbOfCells && ret;i++)
4848 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4849 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4850 ret=cm.isQuadratic();
4856 * Checks if \a this mesh includes any quadratic cell.
4857 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4858 * \throw If the coordinates array is not set.
4859 * \throw If the nodal connectivity of cells is not defined.
4861 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4863 checkFullyDefined();
4865 int nbOfCells=getNumberOfCells();
4866 for(int i=0;i<nbOfCells && !ret;i++)
4868 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4869 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4870 ret=cm.isQuadratic();
4876 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4877 * this mesh, it remains unchanged.
4878 * \throw If the coordinates array is not set.
4879 * \throw If the nodal connectivity of cells is not defined.
4881 void MEDCouplingUMesh::convertQuadraticCellsToLinear()
4883 checkFullyDefined();
4884 int nbOfCells=getNumberOfCells();
4886 const int *iciptr=_nodal_connec_index->getConstPointer();
4887 for(int i=0;i<nbOfCells;i++)
4889 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4890 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4891 if(cm.isQuadratic())
4893 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4894 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4895 if(!cml.isDynamic())
4896 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4898 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4903 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4904 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4905 const int *icptr=_nodal_connec->getConstPointer();
4906 newConn->alloc(getMeshLength()-delta,1);
4907 newConnI->alloc(nbOfCells+1,1);
4908 int *ocptr=newConn->getPointer();
4909 int *ociptr=newConnI->getPointer();
4912 for(int i=0;i<nbOfCells;i++,ociptr++)
4914 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4915 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4916 if(!cm.isQuadratic())
4918 _types.insert(type);
4919 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4920 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4924 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4925 _types.insert(typel);
4926 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4927 int newNbOfNodes=cml.getNumberOfNodes();
4929 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4930 *ocptr++=(int)typel;
4931 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4932 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4935 setConnectivity(newConn,newConnI,false);
4939 * This method converts all linear cell in \a this to quadratic one.
4940 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4941 * 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)
4942 * 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.
4943 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4944 * end of the existing coordinates.
4946 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4947 * corresponding quadratic cells. 1 is those creating the 'most' complex.
4948 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4950 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4952 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4954 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType)
4956 DataArrayInt *conn=0,*connI=0;
4957 DataArrayDouble *coords=0;
4958 std::set<INTERP_KERNEL::NormalizedCellType> types;
4959 checkFullyDefined();
4960 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4961 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4962 int meshDim=getMeshDimension();
4963 switch(conversionType)
4969 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4970 connSafe=conn; connISafe=connI; coordsSafe=coords;
4973 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4974 connSafe=conn; connISafe=connI; coordsSafe=coords;
4977 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4978 connSafe=conn; connISafe=connI; coordsSafe=coords;
4981 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4989 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4990 connSafe=conn; connISafe=connI; coordsSafe=coords;
4993 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4994 connSafe=conn; connISafe=connI; coordsSafe=coords;
4997 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4998 connSafe=conn; connISafe=connI; coordsSafe=coords;
5001 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
5006 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
5008 setConnectivity(connSafe,connISafe,false);
5010 setCoords(coordsSafe);
5015 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5016 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5017 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5019 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5021 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5022 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5023 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5024 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5025 int nbOfCells=getNumberOfCells();
5026 int nbOfNodes=getNumberOfNodes();
5027 const int *cPtr=_nodal_connec->getConstPointer();
5028 const int *icPtr=_nodal_connec_index->getConstPointer();
5029 int lastVal=0,offset=nbOfNodes;
5030 for(int i=0;i<nbOfCells;i++,icPtr++)
5032 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5033 if(type==INTERP_KERNEL::NORM_SEG2)
5035 types.insert(INTERP_KERNEL::NORM_SEG3);
5036 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
5037 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
5038 newConn->pushBackSilent(offset++);
5040 newConnI->pushBackSilent(lastVal);
5041 ret->pushBackSilent(i);
5046 lastVal+=(icPtr[1]-icPtr[0]);
5047 newConnI->pushBackSilent(lastVal);
5048 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5051 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5052 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
5056 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
5058 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5059 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5060 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5062 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5063 DataArrayInt *conn1D=0,*conn1DI=0;
5064 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5065 DataArrayDouble *coordsTmp=0;
5066 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5067 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5068 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5069 const int *c1DPtr=conn1D->begin();
5070 const int *c1DIPtr=conn1DI->begin();
5071 int nbOfCells=getNumberOfCells();
5072 const int *cPtr=_nodal_connec->getConstPointer();
5073 const int *icPtr=_nodal_connec_index->getConstPointer();
5075 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5077 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5078 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5079 if(!cm.isQuadratic())
5081 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
5082 types.insert(typ2); newConn->pushBackSilent(typ2);
5083 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5084 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5085 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5086 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
5087 newConnI->pushBackSilent(lastVal);
5088 ret->pushBackSilent(i);
5093 lastVal+=(icPtr[1]-icPtr[0]);
5094 newConnI->pushBackSilent(lastVal);
5095 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5098 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5103 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5104 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5105 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5107 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5109 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5110 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5111 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5114 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5116 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5117 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5119 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5120 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5121 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5123 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5124 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5125 DataArrayInt *conn1D=0,*conn1DI=0;
5126 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5127 DataArrayDouble *coordsTmp=0;
5128 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5129 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5130 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5131 const int *c1DPtr=conn1D->begin();
5132 const int *c1DIPtr=conn1DI->begin();
5133 int nbOfCells=getNumberOfCells();
5134 const int *cPtr=_nodal_connec->getConstPointer();
5135 const int *icPtr=_nodal_connec_index->getConstPointer();
5136 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5137 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5139 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5140 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5141 if(!cm.isQuadratic())
5143 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5144 types.insert(typ2); newConn->pushBackSilent(typ2);
5145 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5146 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5147 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5148 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5149 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5150 newConnI->pushBackSilent(lastVal);
5151 ret->pushBackSilent(i);
5156 lastVal+=(icPtr[1]-icPtr[0]);
5157 newConnI->pushBackSilent(lastVal);
5158 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5161 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5162 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5167 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5168 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5169 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5171 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5173 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5174 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5175 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5178 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const
5180 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5181 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5182 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5183 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5185 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5186 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5187 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5189 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5190 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5191 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5192 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5193 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5194 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5195 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5196 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5197 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5198 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5199 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5200 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5201 int nbOfCells=getNumberOfCells();
5202 const int *cPtr=_nodal_connec->getConstPointer();
5203 const int *icPtr=_nodal_connec_index->getConstPointer();
5204 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5205 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5207 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5208 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5209 if(!cm.isQuadratic())
5211 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5212 if(typ2==INTERP_KERNEL::NORM_ERROR)
5214 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5215 throw INTERP_KERNEL::Exception(oss.str().c_str());
5217 types.insert(typ2); newConn->pushBackSilent(typ2);
5218 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5219 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5220 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5221 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5223 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5224 int tmpPos=newConn->getNumberOfTuples();
5225 newConn->pushBackSilent(nodeId2);
5226 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5228 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5229 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5230 newConnI->pushBackSilent(lastVal);
5231 ret->pushBackSilent(i);
5236 lastVal+=(icPtr[1]-icPtr[0]);
5237 newConnI->pushBackSilent(lastVal);
5238 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5241 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5242 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5243 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5244 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5245 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5246 int *c=newConn->getPointer();
5247 const int *cI(newConnI->begin());
5248 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5249 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5250 offset=coordsTmp2Safe->getNumberOfTuples();
5251 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5252 c[cI[(*elt)+1]-1]+=offset;
5253 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5258 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5259 * so that the number of cells remains the same. Quadratic faces are converted to
5260 * polygons. This method works only for 2D meshes in
5261 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5262 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5263 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5264 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5265 * a polylinized edge constituting the input polygon.
5266 * \throw If the coordinates array is not set.
5267 * \throw If the nodal connectivity of cells is not defined.
5268 * \throw If \a this->getMeshDimension() != 2.
5269 * \throw If \a this->getSpaceDimension() != 2.
5271 void MEDCouplingUMesh::tessellate2D(double eps)
5273 checkFullyDefined();
5274 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5275 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5276 double epsa=fabs(eps);
5277 if(epsa<std::numeric_limits<double>::min())
5278 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 !");
5279 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5280 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5281 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5282 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5283 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5284 revDesc1=0; revDescIndx1=0;
5285 mDesc->tessellate2DCurve(eps);
5286 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5287 setCoords(mDesc->getCoords());
5291 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5292 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5293 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5294 * a sub-divided edge.
5295 * \throw If the coordinates array is not set.
5296 * \throw If the nodal connectivity of cells is not defined.
5297 * \throw If \a this->getMeshDimension() != 1.
5298 * \throw If \a this->getSpaceDimension() != 2.
5300 void MEDCouplingUMesh::tessellate2DCurve(double eps)
5302 checkFullyDefined();
5303 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5304 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5305 double epsa=fabs(eps);
5306 if(epsa<std::numeric_limits<double>::min())
5307 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 !");
5308 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5309 int nbCells=getNumberOfCells();
5310 int nbNodes=getNumberOfNodes();
5311 const int *conn=_nodal_connec->getConstPointer();
5312 const int *connI=_nodal_connec_index->getConstPointer();
5313 const double *coords=_coords->getConstPointer();
5314 std::vector<double> addCoo;
5315 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5316 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5317 newConnI->alloc(nbCells+1,1);
5318 int *newConnIPtr=newConnI->getPointer();
5321 INTERP_KERNEL::Node *tmp2[3];
5322 std::set<INTERP_KERNEL::NormalizedCellType> types;
5323 for(int i=0;i<nbCells;i++,newConnIPtr++)
5325 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5326 if(cm.isQuadratic())
5327 {//assert(connI[i+1]-connI[i]-1==3)
5328 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5329 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5330 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5331 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5332 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5335 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5336 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5338 newConnIPtr[1]=(int)newConn.size();
5342 types.insert(INTERP_KERNEL::NORM_SEG2);
5343 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5344 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5345 newConnIPtr[1]=newConnIPtr[0]+3;
5350 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5351 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5352 newConnIPtr[1]=newConnIPtr[0]+3;
5355 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tessellation : no update needed
5358 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5359 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5360 newConnArr->alloc((int)newConn.size(),1);
5361 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5362 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5363 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5364 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5365 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5366 std::copy(addCoo.begin(),addCoo.end(),work);
5367 DataArrayDouble::SetArrayIn(newCoords,_coords);
5372 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5373 * In addition, returns an array mapping new cells to old ones. <br>
5374 * This method typically increases the number of cells in \a this mesh
5375 * but the number of nodes remains \b unchanged.
5376 * That's why the 3D splitting policies
5377 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5378 * \param [in] policy - specifies a pattern used for splitting.
5379 * The semantic of \a policy is:
5380 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5381 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5382 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5383 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5384 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5385 * an id of old cell producing it. The caller is to delete this array using
5386 * decrRef() as it is no more needed.
5387 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5388 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5389 * and \a this->getMeshDimension() != 3.
5390 * \throw If \a policy is not one of the four discussed above.
5391 * \throw If the nodal connectivity of cells is not defined.
5392 * \sa MEDCouplingUMesh::tetrahedrize, MEDCoupling1SGTUMesh::sortHexa8EachOther
5394 DataArrayInt *MEDCouplingUMesh::simplexize(int policy)
5399 return simplexizePol0();
5401 return simplexizePol1();
5402 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5403 return simplexizePlanarFace5();
5404 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5405 return simplexizePlanarFace6();
5407 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)");
5412 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5413 * - 1D: INTERP_KERNEL::NORM_SEG2
5414 * - 2D: INTERP_KERNEL::NORM_TRI3
5415 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5417 * This method is useful for users that need to use P1 field services as
5418 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5419 * All these methods need mesh support containing only simplex cells.
5420 * \return bool - \c true if there are only simplex cells in \a this mesh.
5421 * \throw If the coordinates array is not set.
5422 * \throw If the nodal connectivity of cells is not defined.
5423 * \throw If \a this->getMeshDimension() < 1.
5425 bool MEDCouplingUMesh::areOnlySimplexCells() const
5427 checkFullyDefined();
5428 int mdim=getMeshDimension();
5429 if(mdim<1 || mdim>3)
5430 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5431 int nbCells=getNumberOfCells();
5432 const int *conn=_nodal_connec->getConstPointer();
5433 const int *connI=_nodal_connec_index->getConstPointer();
5434 for(int i=0;i<nbCells;i++)
5436 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5444 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5446 DataArrayInt *MEDCouplingUMesh::simplexizePol0()
5448 checkConnectivityFullyDefined();
5449 if(getMeshDimension()!=2)
5450 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5451 int nbOfCells=getNumberOfCells();
5452 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5453 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5454 ret->alloc(nbOfCells+nbOfCutCells,1);
5455 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5456 int *retPt=ret->getPointer();
5457 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5458 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5459 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5460 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5461 int *pt=newConn->getPointer();
5462 int *ptI=newConnI->getPointer();
5464 const int *oldc=_nodal_connec->getConstPointer();
5465 const int *ci=_nodal_connec_index->getConstPointer();
5466 for(int i=0;i<nbOfCells;i++,ci++)
5468 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5470 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5471 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5472 pt=std::copy(tmp,tmp+8,pt);
5481 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5482 ptI[1]=ptI[0]+ci[1]-ci[0];
5487 _nodal_connec->decrRef();
5488 _nodal_connec=newConn.retn();
5489 _nodal_connec_index->decrRef();
5490 _nodal_connec_index=newConnI.retn();
5497 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5499 DataArrayInt *MEDCouplingUMesh::simplexizePol1()
5501 checkConnectivityFullyDefined();
5502 if(getMeshDimension()!=2)
5503 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5504 int nbOfCells=getNumberOfCells();
5505 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5506 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5507 ret->alloc(nbOfCells+nbOfCutCells,1);
5508 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5509 int *retPt=ret->getPointer();
5510 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5511 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5512 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5513 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5514 int *pt=newConn->getPointer();
5515 int *ptI=newConnI->getPointer();
5517 const int *oldc=_nodal_connec->getConstPointer();
5518 const int *ci=_nodal_connec_index->getConstPointer();
5519 for(int i=0;i<nbOfCells;i++,ci++)
5521 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5523 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5524 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5525 pt=std::copy(tmp,tmp+8,pt);
5534 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5535 ptI[1]=ptI[0]+ci[1]-ci[0];
5540 _nodal_connec->decrRef();
5541 _nodal_connec=newConn.retn();
5542 _nodal_connec_index->decrRef();
5543 _nodal_connec_index=newConnI.retn();
5550 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5552 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5()
5554 checkConnectivityFullyDefined();
5555 if(getMeshDimension()!=3)
5556 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5557 int nbOfCells=getNumberOfCells();
5558 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5559 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5560 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5561 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5562 int *retPt=ret->getPointer();
5563 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5564 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5565 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5566 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5567 int *pt=newConn->getPointer();
5568 int *ptI=newConnI->getPointer();
5570 const int *oldc=_nodal_connec->getConstPointer();
5571 const int *ci=_nodal_connec_index->getConstPointer();
5572 for(int i=0;i<nbOfCells;i++,ci++)
5574 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5576 for(int j=0;j<5;j++,pt+=5,ptI++)
5578 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5579 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];
5586 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5587 ptI[1]=ptI[0]+ci[1]-ci[0];
5592 _nodal_connec->decrRef();
5593 _nodal_connec=newConn.retn();
5594 _nodal_connec_index->decrRef();
5595 _nodal_connec_index=newConnI.retn();
5602 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5604 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6()
5606 checkConnectivityFullyDefined();
5607 if(getMeshDimension()!=3)
5608 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5609 int nbOfCells=getNumberOfCells();
5610 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5611 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5612 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5613 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5614 int *retPt=ret->getPointer();
5615 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5616 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5617 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5618 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5619 int *pt=newConn->getPointer();
5620 int *ptI=newConnI->getPointer();
5622 const int *oldc=_nodal_connec->getConstPointer();
5623 const int *ci=_nodal_connec_index->getConstPointer();
5624 for(int i=0;i<nbOfCells;i++,ci++)
5626 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5628 for(int j=0;j<6;j++,pt+=5,ptI++)
5630 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5631 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];
5638 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5639 ptI[1]=ptI[0]+ci[1]-ci[0];
5644 _nodal_connec->decrRef();
5645 _nodal_connec=newConn.retn();
5646 _nodal_connec_index->decrRef();
5647 _nodal_connec_index=newConnI.retn();
5654 * 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.
5655 * This method completly ignore coordinates.
5656 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5657 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5658 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5659 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5661 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex)
5663 checkFullyDefined();
5664 if(getMeshDimension()!=2)
5665 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5666 int nbOfCells=getNumberOfCells();
5667 int *connI=_nodal_connec_index->getPointer();
5669 for(int i=0;i<nbOfCells;i++,connI++)
5671 int offset=descIndex[i];
5672 int nbOfEdges=descIndex[i+1]-offset;
5674 bool ddirect=desc[offset+nbOfEdges-1]>0;
5675 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5676 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5677 for(int j=0;j<nbOfEdges;j++)
5679 bool direct=desc[offset+j]>0;
5680 int edgeId=std::abs(desc[offset+j])-1;
5681 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5683 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5684 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5685 int ref2=direct?id1:id2;
5688 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5689 newConnLgth+=nbOfSubNodes-1;
5694 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5695 throw INTERP_KERNEL::Exception(oss.str().c_str());
5700 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5703 newConnLgth++;//+1 is for cell type
5704 connI[1]=newConnLgth;
5707 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5708 newConn->alloc(newConnLgth,1);
5709 int *work=newConn->getPointer();
5710 for(int i=0;i<nbOfCells;i++)
5712 *work++=INTERP_KERNEL::NORM_POLYGON;
5713 int offset=descIndex[i];
5714 int nbOfEdges=descIndex[i+1]-offset;
5715 for(int j=0;j<nbOfEdges;j++)
5717 bool direct=desc[offset+j]>0;
5718 int edgeId=std::abs(desc[offset+j])-1;
5720 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5723 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5724 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5725 work=std::copy(it,it+nbOfSubNodes-1,work);
5729 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5732 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5736 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5737 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5738 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5739 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5740 * so it can be useful to call mergeNodes() before calling this method.
5741 * \throw If \a this->getMeshDimension() <= 1.
5742 * \throw If the coordinates array is not set.
5743 * \throw If the nodal connectivity of cells is not defined.
5745 void MEDCouplingUMesh::convertDegeneratedCells()
5747 checkFullyDefined();
5748 if(getMeshDimension()<=1)
5749 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5750 int nbOfCells=getNumberOfCells();
5753 int initMeshLgth=getMeshLength();
5754 int *conn=_nodal_connec->getPointer();
5755 int *index=_nodal_connec_index->getPointer();
5759 for(int i=0;i<nbOfCells;i++)
5761 lgthOfCurCell=index[i+1]-posOfCurCell;
5762 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5764 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5765 conn+newPos+1,newLgth);
5766 conn[newPos]=newType;
5768 posOfCurCell=index[i+1];
5771 if(newPos!=initMeshLgth)
5772 _nodal_connec->reAlloc(newPos);
5777 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5778 * A cell is considered to be oriented correctly if an angle between its
5779 * normal vector and a given vector is less than \c PI / \c 2.
5780 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5782 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5784 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5785 * is not cleared before filling in.
5786 * \throw If \a this->getMeshDimension() != 2.
5787 * \throw If \a this->getSpaceDimension() != 3.
5789 * \if ENABLE_EXAMPLES
5790 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5791 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5794 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const
5796 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5797 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5798 int nbOfCells=getNumberOfCells();
5799 const int *conn=_nodal_connec->getConstPointer();
5800 const int *connI=_nodal_connec_index->getConstPointer();
5801 const double *coordsPtr=_coords->getConstPointer();
5802 for(int i=0;i<nbOfCells;i++)
5804 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5805 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5807 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5808 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5815 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5816 * considered to be oriented correctly if an angle between its normal vector and a
5817 * given vector is less than \c PI / \c 2.
5818 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5820 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5822 * \throw If \a this->getMeshDimension() != 2.
5823 * \throw If \a this->getSpaceDimension() != 3.
5825 * \if ENABLE_EXAMPLES
5826 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5827 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5830 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly)
5832 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5833 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5834 int nbOfCells=getNumberOfCells();
5835 int *conn=_nodal_connec->getPointer();
5836 const int *connI=_nodal_connec_index->getConstPointer();
5837 const double *coordsPtr=_coords->getConstPointer();
5838 bool isModified=false;
5839 for(int i=0;i<nbOfCells;i++)
5841 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5842 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5844 bool isQuadratic(INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic());
5845 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5850 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5851 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5852 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5856 int sz(((int)(connI[i+1]-connI[i]-1))/2);
5857 std::vector<int> tmp0(sz-1),tmp1(sz);
5858 std::copy(conn+connI[i]+2,conn+connI[i]+1+sz,tmp0.rbegin());
5859 std::copy(conn+connI[i]+1+sz,conn+connI[i+1],tmp1.rbegin());
5860 std::copy(tmp0.begin(),tmp0.end(),conn+connI[i]+2);
5861 std::copy(tmp1.begin(),tmp1.end(),conn+connI[i]+1+sz);
5867 _nodal_connec->declareAsNew();
5872 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5873 * oriented facets. The normal vector of the facet should point out of the cell.
5874 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5875 * is not cleared before filling in.
5876 * \throw If \a this->getMeshDimension() != 3.
5877 * \throw If \a this->getSpaceDimension() != 3.
5878 * \throw If the coordinates array is not set.
5879 * \throw If the nodal connectivity of cells is not defined.
5881 * \if ENABLE_EXAMPLES
5882 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5883 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5886 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const
5888 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5889 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5890 int nbOfCells=getNumberOfCells();
5891 const int *conn=_nodal_connec->getConstPointer();
5892 const int *connI=_nodal_connec_index->getConstPointer();
5893 const double *coordsPtr=_coords->getConstPointer();
5894 for(int i=0;i<nbOfCells;i++)
5896 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5897 if(type==INTERP_KERNEL::NORM_POLYHED)
5899 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5906 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5908 * \throw If \a this->getMeshDimension() != 3.
5909 * \throw If \a this->getSpaceDimension() != 3.
5910 * \throw If the coordinates array is not set.
5911 * \throw If the nodal connectivity of cells is not defined.
5912 * \throw If the reparation fails.
5914 * \if ENABLE_EXAMPLES
5915 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5916 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5918 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5920 void MEDCouplingUMesh::orientCorrectlyPolyhedrons()
5922 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5923 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5924 int nbOfCells=getNumberOfCells();
5925 int *conn=_nodal_connec->getPointer();
5926 const int *connI=_nodal_connec_index->getConstPointer();
5927 const double *coordsPtr=_coords->getConstPointer();
5928 for(int i=0;i<nbOfCells;i++)
5930 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5931 if(type==INTERP_KERNEL::NORM_POLYHED)
5935 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5936 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5938 catch(INTERP_KERNEL::Exception& e)
5940 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5941 throw INTERP_KERNEL::Exception(oss.str().c_str());
5949 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5950 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5951 * according to which the first facet of the cell should be oriented to have the normal vector
5952 * pointing out of cell.
5953 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5954 * cells. The caller is to delete this array using decrRef() as it is no more
5956 * \throw If \a this->getMeshDimension() != 3.
5957 * \throw If \a this->getSpaceDimension() != 3.
5958 * \throw If the coordinates array is not set.
5959 * \throw If the nodal connectivity of cells is not defined.
5961 * \if ENABLE_EXAMPLES
5962 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5963 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5965 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5967 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells()
5969 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5970 if(getMeshDimension()!=3)
5971 throw INTERP_KERNEL::Exception(msg);
5972 int spaceDim=getSpaceDimension();
5974 throw INTERP_KERNEL::Exception(msg);
5976 int nbOfCells=getNumberOfCells();
5977 int *conn=_nodal_connec->getPointer();
5978 const int *connI=_nodal_connec_index->getConstPointer();
5979 const double *coo=getCoords()->getConstPointer();
5980 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5981 for(int i=0;i<nbOfCells;i++)
5983 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5984 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5986 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5988 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5989 cells->pushBackSilent(i);
5993 return cells.retn();
5997 * This method is a faster method to correct orientation of all 3D cells in \a this.
5998 * 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.
5999 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
6001 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
6002 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
6004 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells()
6006 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
6007 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
6008 int nbOfCells=getNumberOfCells();
6009 int *conn=_nodal_connec->getPointer();
6010 const int *connI=_nodal_connec_index->getConstPointer();
6011 const double *coordsPtr=_coords->getConstPointer();
6012 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
6013 for(int i=0;i<nbOfCells;i++)
6015 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
6018 case INTERP_KERNEL::NORM_TETRA4:
6020 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6022 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
6023 ret->pushBackSilent(i);
6027 case INTERP_KERNEL::NORM_PYRA5:
6029 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6031 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
6032 ret->pushBackSilent(i);
6036 case INTERP_KERNEL::NORM_PENTA6:
6037 case INTERP_KERNEL::NORM_HEXA8:
6038 case INTERP_KERNEL::NORM_HEXGP12:
6040 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6042 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
6043 ret->pushBackSilent(i);
6047 case INTERP_KERNEL::NORM_POLYHED:
6049 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
6051 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
6052 ret->pushBackSilent(i);
6057 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 !");
6065 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
6066 * If it is not the case an exception will be thrown.
6067 * This method is fast because the first cell of \a this is used to compute the plane.
6068 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
6069 * \param pos output of size at least 3 used to store a point owned of searched plane.
6071 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const
6073 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
6074 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
6075 const int *conn=_nodal_connec->getConstPointer();
6076 const int *connI=_nodal_connec_index->getConstPointer();
6077 const double *coordsPtr=_coords->getConstPointer();
6078 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
6079 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
6083 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
6084 * cells. Currently cells of the following types are treated:
6085 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6086 * For a cell of other type an exception is thrown.
6087 * Space dimension of a 2D mesh can be either 2 or 3.
6088 * The Edge Ratio of a cell \f$t\f$ is:
6089 * \f$\frac{|t|_\infty}{|t|_0}\f$,
6090 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
6091 * the smallest edge lengths of \f$t\f$.
6092 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6093 * cells and one time, lying on \a this mesh. The caller is to delete this
6094 * field using decrRef() as it is no more needed.
6095 * \throw If the coordinates array is not set.
6096 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6097 * \throw If the connectivity data array has more than one component.
6098 * \throw If the connectivity data array has a named component.
6099 * \throw If the connectivity index data array has more than one component.
6100 * \throw If the connectivity index data array has a named component.
6101 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6102 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6103 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6105 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const
6108 int spaceDim=getSpaceDimension();
6109 int meshDim=getMeshDimension();
6110 if(spaceDim!=2 && spaceDim!=3)
6111 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
6112 if(meshDim!=2 && meshDim!=3)
6113 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
6114 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6116 int nbOfCells=getNumberOfCells();
6117 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6118 arr->alloc(nbOfCells,1);
6119 double *pt=arr->getPointer();
6120 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6121 const int *conn=_nodal_connec->getConstPointer();
6122 const int *connI=_nodal_connec_index->getConstPointer();
6123 const double *coo=_coords->getConstPointer();
6125 for(int i=0;i<nbOfCells;i++,pt++)
6127 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6130 case INTERP_KERNEL::NORM_TRI3:
6132 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6133 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6136 case INTERP_KERNEL::NORM_QUAD4:
6138 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6139 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6142 case INTERP_KERNEL::NORM_TETRA4:
6144 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6145 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6149 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6151 conn+=connI[i+1]-connI[i];
6153 ret->setName("EdgeRatio");
6154 ret->synchronizeTimeWithSupport();
6159 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6160 * cells. Currently cells of the following types are treated:
6161 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6162 * For a cell of other type an exception is thrown.
6163 * Space dimension of a 2D mesh can be either 2 or 3.
6164 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6165 * cells and one time, lying on \a this mesh. The caller is to delete this
6166 * field using decrRef() as it is no more needed.
6167 * \throw If the coordinates array is not set.
6168 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6169 * \throw If the connectivity data array has more than one component.
6170 * \throw If the connectivity data array has a named component.
6171 * \throw If the connectivity index data array has more than one component.
6172 * \throw If the connectivity index data array has a named component.
6173 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6174 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6175 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6177 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const
6180 int spaceDim=getSpaceDimension();
6181 int meshDim=getMeshDimension();
6182 if(spaceDim!=2 && spaceDim!=3)
6183 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6184 if(meshDim!=2 && meshDim!=3)
6185 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6186 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6188 int nbOfCells=getNumberOfCells();
6189 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6190 arr->alloc(nbOfCells,1);
6191 double *pt=arr->getPointer();
6192 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6193 const int *conn=_nodal_connec->getConstPointer();
6194 const int *connI=_nodal_connec_index->getConstPointer();
6195 const double *coo=_coords->getConstPointer();
6197 for(int i=0;i<nbOfCells;i++,pt++)
6199 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6202 case INTERP_KERNEL::NORM_TRI3:
6204 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6205 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6208 case INTERP_KERNEL::NORM_QUAD4:
6210 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6211 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6214 case INTERP_KERNEL::NORM_TETRA4:
6216 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6217 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6221 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6223 conn+=connI[i+1]-connI[i];
6225 ret->setName("AspectRatio");
6226 ret->synchronizeTimeWithSupport();
6231 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6232 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6233 * treated: INTERP_KERNEL::NORM_QUAD4.
6234 * For a cell of other type an exception is thrown.
6235 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6236 * cells and one time, lying on \a this mesh. The caller is to delete this
6237 * field using decrRef() as it is no more needed.
6238 * \throw If the coordinates array is not set.
6239 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6240 * \throw If the connectivity data array has more than one component.
6241 * \throw If the connectivity data array has a named component.
6242 * \throw If the connectivity index data array has more than one component.
6243 * \throw If the connectivity index data array has a named component.
6244 * \throw If \a this->getMeshDimension() != 2.
6245 * \throw If \a this->getSpaceDimension() != 3.
6246 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6248 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const
6251 int spaceDim=getSpaceDimension();
6252 int meshDim=getMeshDimension();
6254 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6256 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6257 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6259 int nbOfCells=getNumberOfCells();
6260 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6261 arr->alloc(nbOfCells,1);
6262 double *pt=arr->getPointer();
6263 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6264 const int *conn=_nodal_connec->getConstPointer();
6265 const int *connI=_nodal_connec_index->getConstPointer();
6266 const double *coo=_coords->getConstPointer();
6268 for(int i=0;i<nbOfCells;i++,pt++)
6270 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6273 case INTERP_KERNEL::NORM_QUAD4:
6275 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6276 *pt=INTERP_KERNEL::quadWarp(tmp);
6280 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6282 conn+=connI[i+1]-connI[i];
6284 ret->setName("Warp");
6285 ret->synchronizeTimeWithSupport();
6291 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6292 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6293 * treated: INTERP_KERNEL::NORM_QUAD4.
6294 * For a cell of other type an exception is thrown.
6295 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6296 * cells and one time, lying on \a this mesh. The caller is to delete this
6297 * field using decrRef() as it is no more needed.
6298 * \throw If the coordinates array is not set.
6299 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6300 * \throw If the connectivity data array has more than one component.
6301 * \throw If the connectivity data array has a named component.
6302 * \throw If the connectivity index data array has more than one component.
6303 * \throw If the connectivity index data array has a named component.
6304 * \throw If \a this->getMeshDimension() != 2.
6305 * \throw If \a this->getSpaceDimension() != 3.
6306 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6308 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const
6311 int spaceDim=getSpaceDimension();
6312 int meshDim=getMeshDimension();
6314 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6316 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6317 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6319 int nbOfCells=getNumberOfCells();
6320 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6321 arr->alloc(nbOfCells,1);
6322 double *pt=arr->getPointer();
6323 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6324 const int *conn=_nodal_connec->getConstPointer();
6325 const int *connI=_nodal_connec_index->getConstPointer();
6326 const double *coo=_coords->getConstPointer();
6328 for(int i=0;i<nbOfCells;i++,pt++)
6330 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6333 case INTERP_KERNEL::NORM_QUAD4:
6335 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6336 *pt=INTERP_KERNEL::quadSkew(tmp);
6340 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6342 conn+=connI[i+1]-connI[i];
6344 ret->setName("Skew");
6345 ret->synchronizeTimeWithSupport();
6350 * This method aggregate the bbox of each cell and put it into bbox parameter.
6352 * \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)
6353 * For all other cases this input parameter is ignored.
6354 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6356 * \throw If \a this is not fully set (coordinates and connectivity).
6357 * \throw If a cell in \a this has no valid nodeId.
6358 * \sa MEDCouplingUMesh::getBoundingBoxForBBTreeFast, MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6360 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree(double arcDetEps) const
6362 int mDim(getMeshDimension()),sDim(getSpaceDimension());
6363 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.
6364 return getBoundingBoxForBBTreeFast();
6365 if((mDim==2 && sDim==2) || (mDim==1 && sDim==2))
6367 bool presenceOfQuadratic(false);
6368 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator it=_types.begin();it!=_types.end();it++)
6370 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel(*it));
6371 if(cm.isQuadratic())
6372 presenceOfQuadratic=true;
6374 if(!presenceOfQuadratic)
6375 return getBoundingBoxForBBTreeFast();
6376 if(mDim==2 && sDim==2)
6377 return getBoundingBoxForBBTree2DQuadratic(arcDetEps);
6379 return getBoundingBoxForBBTree1DQuadratic(arcDetEps);
6381 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) !");
6385 * This method aggregate the bbox of each cell only considering the nodes constituting each cell and put it into bbox parameter.
6386 * So meshes having quadratic cells the computed bounding boxes can be invalid !
6388 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6390 * \throw If \a this is not fully set (coordinates and connectivity).
6391 * \throw If a cell in \a this has no valid nodeId.
6393 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTreeFast() const
6395 checkFullyDefined();
6396 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6397 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6398 double *bbox(ret->getPointer());
6399 for(int i=0;i<nbOfCells*spaceDim;i++)
6401 bbox[2*i]=std::numeric_limits<double>::max();
6402 bbox[2*i+1]=-std::numeric_limits<double>::max();
6404 const double *coordsPtr(_coords->getConstPointer());
6405 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6406 for(int i=0;i<nbOfCells;i++)
6408 int offset=connI[i]+1;
6409 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6410 for(int j=0;j<nbOfNodesForCell;j++)
6412 int nodeId=conn[offset+j];
6413 if(nodeId>=0 && nodeId<nbOfNodes)
6415 for(int k=0;k<spaceDim;k++)
6417 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6418 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6425 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6426 throw INTERP_KERNEL::Exception(oss.str().c_str());
6433 * This method aggregates the bbox of each 2D cell in \a this considering the whole shape. This method is particularly
6434 * useful for 2D meshes having quadratic cells
6435 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6436 * the two extremities of the arc of circle).
6438 * \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)
6439 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6440 * \throw If \a this is not fully defined.
6441 * \throw If \a this is not a mesh with meshDimension equal to 2.
6442 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6443 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic
6445 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic(double arcDetEps) const
6447 checkFullyDefined();
6448 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6449 if(spaceDim!=2 || mDim!=2)
6450 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!");
6451 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6452 double *bbox(ret->getPointer());
6453 const double *coords(_coords->getConstPointer());
6454 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6455 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6457 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6458 int sz(connI[1]-connI[0]-1);
6459 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6460 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6461 INTERP_KERNEL::QuadraticPolygon *pol(0);
6462 for(int j=0;j<sz;j++)
6464 int nodeId(conn[*connI+1+j]);
6465 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6467 if(!cm.isQuadratic())
6468 pol=INTERP_KERNEL::QuadraticPolygon::BuildLinearPolygon(nodes);
6470 pol=INTERP_KERNEL::QuadraticPolygon::BuildArcCirclePolygon(nodes);
6471 INTERP_KERNEL::Bounds b; b.prepareForAggregation(); pol->fillBounds(b); delete pol;
6472 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax();
6478 * This method aggregates the bbox of each 1D cell in \a this considering the whole shape. This method is particularly
6479 * useful for 2D meshes having quadratic cells
6480 * because for this type of cells getBoundingBoxForBBTreeFast method may return invalid bounding boxes (since it just considers
6481 * the two extremities of the arc of circle).
6483 * \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)
6484 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6485 * \throw If \a this is not fully defined.
6486 * \throw If \a this is not a mesh with meshDimension equal to 1.
6487 * \throw If \a this is not a mesh with spaceDimension equal to 2.
6488 * \sa MEDCouplingUMesh::getBoundingBoxForBBTree2DQuadratic
6490 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree1DQuadratic(double arcDetEps) const
6492 checkFullyDefined();
6493 int spaceDim(getSpaceDimension()),mDim(getMeshDimension()),nbOfCells(getNumberOfCells());
6494 if(spaceDim!=2 || mDim!=1)
6495 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!");
6496 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6497 double *bbox(ret->getPointer());
6498 const double *coords(_coords->getConstPointer());
6499 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6500 for(int i=0;i<nbOfCells;i++,bbox+=4,connI++)
6502 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]));
6503 int sz(connI[1]-connI[0]-1);
6504 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=arcDetEps;
6505 std::vector<INTERP_KERNEL::Node *> nodes(sz);
6506 INTERP_KERNEL::Edge *edge(0);
6507 for(int j=0;j<sz;j++)
6509 int nodeId(conn[*connI+1+j]);
6510 nodes[j]=new INTERP_KERNEL::Node(coords[nodeId*2],coords[nodeId*2+1]);
6512 if(!cm.isQuadratic())
6513 edge=INTERP_KERNEL::QuadraticPolygon::BuildLinearEdge(nodes);
6515 edge=INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(nodes);
6516 const INTERP_KERNEL::Bounds& b(edge->getBounds());
6517 bbox[0]=b.getXMin(); bbox[1]=b.getXMax(); bbox[2]=b.getYMin(); bbox[3]=b.getYMax(); edge->decrRef();
6524 namespace ParaMEDMEMImpl
6529 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6530 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6539 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6540 bool operator() (const int& pos) { return _conn[pos]==_val; }
6550 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6551 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6552 * \a this is composed in cell types.
6553 * The returned array is of size 3*n where n is the number of different types present in \a this.
6554 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6555 * This parameter is kept only for compatibility with other methode listed above.
6557 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const
6559 checkConnectivityFullyDefined();
6560 const int *conn=_nodal_connec->getConstPointer();
6561 const int *connI=_nodal_connec_index->getConstPointer();
6562 const int *work=connI;
6563 int nbOfCells=getNumberOfCells();
6564 std::size_t n=getAllGeoTypes().size();
6565 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6566 std::set<INTERP_KERNEL::NormalizedCellType> types;
6567 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6569 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6570 if(types.find(typ)!=types.end())
6572 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6573 oss << " is not contiguous !";
6574 throw INTERP_KERNEL::Exception(oss.str().c_str());
6578 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6579 ret[3*i+1]=(int)std::distance(work,work2);
6586 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6587 * only for types cell, type node is not managed.
6588 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6589 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6590 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6591 * If 2 or more same geometric type is in \a code and exception is thrown too.
6593 * This method firstly checks
6594 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6595 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6596 * an exception is thrown too.
6598 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6599 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6600 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6602 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const
6605 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6606 std::size_t sz=code.size();
6609 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6610 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6612 bool isNoPflUsed=true;
6613 for(std::size_t i=0;i<n;i++)
6614 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6616 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6618 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6619 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6620 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6623 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6626 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6627 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6628 if(types.size()==_types.size())
6631 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6633 int *retPtr=ret->getPointer();
6634 const int *connI=_nodal_connec_index->getConstPointer();
6635 const int *conn=_nodal_connec->getConstPointer();
6636 int nbOfCells=getNumberOfCells();
6639 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6641 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6642 int offset=(int)std::distance(connI,i);
6643 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6644 int nbOfCellsOfCurType=(int)std::distance(i,j);
6645 if(code[3*kk+2]==-1)
6646 for(int k=0;k<nbOfCellsOfCurType;k++)
6650 int idInIdsPerType=code[3*kk+2];
6651 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6653 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6656 zePfl->checkAllocated();
6657 if(zePfl->getNumberOfComponents()==1)
6659 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6661 if(*k>=0 && *k<nbOfCellsOfCurType)
6662 *retPtr=(*k)+offset;
6665 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6666 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6667 throw INTERP_KERNEL::Exception(oss.str().c_str());
6672 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6675 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6679 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6680 oss << " should be in [0," << idsPerType.size() << ") !";
6681 throw INTERP_KERNEL::Exception(oss.str().c_str());
6690 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6691 * 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.
6692 * 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.
6693 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6695 * \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.
6696 * \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,
6697 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6698 * \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.
6699 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6700 * \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
6702 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const
6705 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6706 if(profile->getNumberOfComponents()!=1)
6707 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6708 checkConnectivityFullyDefined();
6709 const int *conn=_nodal_connec->getConstPointer();
6710 const int *connI=_nodal_connec_index->getConstPointer();
6711 int nbOfCells=getNumberOfCells();
6712 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6713 std::vector<int> typeRangeVals(1);
6714 for(const int *i=connI;i!=connI+nbOfCells;)
6716 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6717 if(std::find(types.begin(),types.end(),curType)!=types.end())
6719 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6721 types.push_back(curType);
6722 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6723 typeRangeVals.push_back((int)std::distance(connI,i));
6726 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6727 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6728 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6729 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6730 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6732 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6733 code.resize(3*nbOfCastsFinal);
6734 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6735 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6736 for(int i=0;i<nbOfCastsFinal;i++)
6738 int castId=castsPresent->getIJ(i,0);
6739 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6740 idsInPflPerType2.push_back(tmp3);
6741 code[3*i]=(int)types[castId];
6742 code[3*i+1]=tmp3->getNumberOfTuples();
6743 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6744 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6746 tmp4->copyStringInfoFrom(*profile);
6747 idsPerType2.push_back(tmp4);
6748 code[3*i+2]=(int)idsPerType2.size()-1;
6755 std::size_t sz2=idsInPflPerType2.size();
6756 idsInPflPerType.resize(sz2);
6757 for(std::size_t i=0;i<sz2;i++)
6759 DataArrayInt *locDa=idsInPflPerType2[i];
6761 idsInPflPerType[i]=locDa;
6763 std::size_t sz=idsPerType2.size();
6764 idsPerType.resize(sz);
6765 for(std::size_t i=0;i<sz;i++)
6767 DataArrayInt *locDa=idsPerType2[i];
6769 idsPerType[i]=locDa;
6774 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6775 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6776 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6777 * 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.
6779 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const
6781 checkFullyDefined();
6782 nM1LevMesh->checkFullyDefined();
6783 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6784 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6785 if(_coords!=nM1LevMesh->getCoords())
6786 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6787 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6788 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6789 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6790 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6791 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6792 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6793 tmp->setConnectivity(tmp0,tmp1);
6794 tmp->renumberCells(ret0->getConstPointer(),false);
6795 revDesc=tmp->getNodalConnectivity();
6796 revDescIndx=tmp->getNodalConnectivityIndex();
6797 DataArrayInt *ret=0;
6798 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6801 ret->getMaxValue(tmp2);
6803 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6804 throw INTERP_KERNEL::Exception(oss.str().c_str());
6809 revDescIndx->incrRef();
6812 meshnM1Old2New=ret0;
6817 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6818 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6819 * in "Old to New" mode.
6820 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6821 * this array using decrRef() as it is no more needed.
6822 * \throw If the nodal connectivity of cells is not defined.
6824 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt()
6826 checkConnectivityFullyDefined();
6827 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6828 renumberCells(ret->getConstPointer(),false);
6833 * This methods checks that cells are sorted by their types.
6834 * This method makes asumption (no check) that connectivity is correctly set before calling.
6836 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6838 checkFullyDefined();
6839 const int *conn=_nodal_connec->getConstPointer();
6840 const int *connI=_nodal_connec_index->getConstPointer();
6841 int nbOfCells=getNumberOfCells();
6842 std::set<INTERP_KERNEL::NormalizedCellType> types;
6843 for(const int *i=connI;i!=connI+nbOfCells;)
6845 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6846 if(types.find(curType)!=types.end())
6848 types.insert(curType);
6849 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6855 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6856 * The geometric type order is specified by MED file.
6858 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6860 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const
6862 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6866 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6867 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6868 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6869 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6871 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6873 checkFullyDefined();
6874 const int *conn=_nodal_connec->getConstPointer();
6875 const int *connI=_nodal_connec_index->getConstPointer();
6876 int nbOfCells=getNumberOfCells();
6880 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6881 for(const int *i=connI;i!=connI+nbOfCells;)
6883 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6884 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6885 if(isTypeExists!=orderEnd)
6887 int pos=(int)std::distance(orderBg,isTypeExists);
6891 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6895 if(sg.find(curType)==sg.end())
6897 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6908 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6909 * 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
6910 * 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'.
6912 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const
6914 checkConnectivityFullyDefined();
6915 int nbOfCells=getNumberOfCells();
6916 const int *conn=_nodal_connec->getConstPointer();
6917 const int *connI=_nodal_connec_index->getConstPointer();
6918 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6919 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6920 tmpa->alloc(nbOfCells,1);
6921 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6922 tmpb->fillWithZero();
6923 int *tmp=tmpa->getPointer();
6924 int *tmp2=tmpb->getPointer();
6925 for(const int *i=connI;i!=connI+nbOfCells;i++)
6927 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6930 int pos=(int)std::distance(orderBg,where);
6932 tmp[std::distance(connI,i)]=pos;
6936 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6937 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6938 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6939 throw INTERP_KERNEL::Exception(oss.str().c_str());
6942 nbPerType=tmpb.retn();
6947 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6949 * \return a new object containing the old to new correspondance.
6951 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6953 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const
6955 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6959 * 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.
6960 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6961 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6962 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6964 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6966 DataArrayInt *nbPerType=0;
6967 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6968 nbPerType->decrRef();
6969 return tmpa->buildPermArrPerLevel();
6973 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6974 * The number of cells remains unchanged after the call of this method.
6975 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6976 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6978 * \return the array giving the correspondance old to new.
6980 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6982 checkFullyDefined();
6984 const int *conn=_nodal_connec->getConstPointer();
6985 const int *connI=_nodal_connec_index->getConstPointer();
6986 int nbOfCells=getNumberOfCells();
6987 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6988 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6989 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6991 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6992 types.push_back(curType);
6993 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6995 DataArrayInt *ret=DataArrayInt::New();
6996 ret->alloc(nbOfCells,1);
6997 int *retPtr=ret->getPointer();
6998 std::fill(retPtr,retPtr+nbOfCells,-1);
7000 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7002 for(const int *i=connI;i!=connI+nbOfCells;i++)
7003 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7004 retPtr[std::distance(connI,i)]=newCellId++;
7006 renumberCells(retPtr,false);
7011 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
7012 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
7013 * This method makes asumption that connectivity is correctly set before calling.
7015 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
7017 checkConnectivityFullyDefined();
7018 const int *conn=_nodal_connec->getConstPointer();
7019 const int *connI=_nodal_connec_index->getConstPointer();
7020 int nbOfCells=getNumberOfCells();
7021 std::vector<MEDCouplingUMesh *> ret;
7022 for(const int *i=connI;i!=connI+nbOfCells;)
7024 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
7025 int beginCellId=(int)std::distance(connI,i);
7026 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
7027 int endCellId=(int)std::distance(connI,i);
7028 int sz=endCellId-beginCellId;
7029 int *cells=new int[sz];
7030 for(int j=0;j<sz;j++)
7031 cells[j]=beginCellId+j;
7032 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
7040 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
7041 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
7042 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
7044 * \return a newly allocated instance, that the caller must manage.
7045 * \throw If \a this contains more than one geometric type.
7046 * \throw If the nodal connectivity of \a this is not fully defined.
7047 * \throw If the internal data is not coherent.
7049 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const
7051 checkConnectivityFullyDefined();
7052 if(_types.size()!=1)
7053 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7054 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7055 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
7056 ret->setCoords(getCoords());
7057 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7060 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
7061 retC->setNodalConnectivity(c);
7065 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
7067 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
7068 DataArrayInt *c=0,*ci=0;
7069 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
7070 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
7071 retD->setNodalConnectivity(cs,cis);
7076 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const
7078 checkConnectivityFullyDefined();
7079 if(_types.size()!=1)
7080 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7081 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
7082 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7085 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
7086 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
7087 throw INTERP_KERNEL::Exception(oss.str().c_str());
7089 int nbCells=getNumberOfCells();
7091 int nbNodesPerCell=(int)cm.getNumberOfNodes();
7092 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
7093 int *outPtr=connOut->getPointer();
7094 const int *conn=_nodal_connec->begin();
7095 const int *connI=_nodal_connec_index->begin();
7097 for(int i=0;i<nbCells;i++,connI++)
7099 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
7100 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
7103 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 << ") !";
7104 throw INTERP_KERNEL::Exception(oss.str().c_str());
7107 return connOut.retn();
7110 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const
7112 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
7113 checkConnectivityFullyDefined();
7114 if(_types.size()!=1)
7115 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
7116 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
7118 throw INTERP_KERNEL::Exception(msg0);
7119 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
7120 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
7121 int *cp(c->getPointer()),*cip(ci->getPointer());
7122 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
7124 for(int i=0;i<nbCells;i++,cip++,incip++)
7126 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
7127 int delta(stop-strt);
7130 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
7131 cp=std::copy(incp+strt,incp+stop,cp);
7133 throw INTERP_KERNEL::Exception(msg0);
7136 throw INTERP_KERNEL::Exception(msg0);
7137 cip[1]=cip[0]+delta;
7139 nodalConn=c.retn(); nodalConnIndex=ci.retn();
7143 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
7144 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
7145 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
7146 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
7147 * are not used here to avoid the build of big permutation array.
7149 * \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
7150 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7151 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
7152 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
7153 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
7154 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
7155 * \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
7156 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
7158 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
7159 DataArrayInt *&szOfCellGrpOfSameType,
7160 DataArrayInt *&idInMsOfCellGrpOfSameType)
7162 std::vector<const MEDCouplingUMesh *> ms2;
7163 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
7166 (*it)->checkConnectivityFullyDefined();
7170 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
7171 const DataArrayDouble *refCoo=ms2[0]->getCoords();
7172 int meshDim=ms2[0]->getMeshDimension();
7173 std::vector<const MEDCouplingUMesh *> m1ssm;
7174 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
7176 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
7177 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
7179 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
7180 ret1->alloc(0,1); ret2->alloc(0,1);
7181 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
7183 if(meshDim!=(*it)->getMeshDimension())
7184 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
7185 if(refCoo!=(*it)->getCoords())
7186 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
7187 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
7188 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
7189 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
7190 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
7192 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
7193 m1ssmSingleAuto.push_back(singleCell);
7194 m1ssmSingle.push_back(singleCell);
7195 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
7198 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
7199 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
7200 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
7201 for(std::size_t i=0;i<m1ssm.size();i++)
7202 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
7203 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
7204 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
7205 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
7210 * This method returns a newly created DataArrayInt instance.
7211 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
7213 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const
7215 checkFullyDefined();
7216 const int *conn=_nodal_connec->getConstPointer();
7217 const int *connIndex=_nodal_connec_index->getConstPointer();
7218 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
7219 for(const int *w=begin;w!=end;w++)
7220 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
7221 ret->pushBackSilent(*w);
7226 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
7227 * are in [0:getNumberOfCells())
7229 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const
7231 checkFullyDefined();
7232 const int *conn=_nodal_connec->getConstPointer();
7233 const int *connI=_nodal_connec_index->getConstPointer();
7234 int nbOfCells=getNumberOfCells();
7235 std::set<INTERP_KERNEL::NormalizedCellType> types(getAllGeoTypes());
7236 int *tmp=new int[nbOfCells];
7237 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
7240 for(const int *i=connI;i!=connI+nbOfCells;i++)
7241 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
7242 tmp[std::distance(connI,i)]=j++;
7244 DataArrayInt *ret=DataArrayInt::New();
7245 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
7246 ret->copyStringInfoFrom(*da);
7247 int *retPtr=ret->getPointer();
7248 const int *daPtr=da->getConstPointer();
7249 int nbOfElems=da->getNbOfElems();
7250 for(int k=0;k<nbOfElems;k++)
7251 retPtr[k]=tmp[daPtr[k]];
7257 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
7258 * This method \b works \b for mesh sorted by type.
7259 * cells whose ids is in 'idsPerGeoType' array.
7260 * This method conserves coords and name of mesh.
7262 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
7264 std::vector<int> code=getDistributionOfTypes();
7265 std::size_t nOfTypesInThis=code.size()/3;
7266 int sz=0,szOfType=0;
7267 for(std::size_t i=0;i<nOfTypesInThis;i++)
7272 szOfType=code[3*i+1];
7274 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
7275 if(*work<0 || *work>=szOfType)
7277 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
7278 oss << ". It should be in [0," << szOfType << ") !";
7279 throw INTERP_KERNEL::Exception(oss.str().c_str());
7281 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
7282 int *idsPtr=idsTokeep->getPointer();
7284 for(std::size_t i=0;i<nOfTypesInThis;i++)
7287 for(int j=0;j<code[3*i+1];j++)
7290 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
7291 offset+=code[3*i+1];
7293 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
7294 ret->copyTinyInfoFrom(this);
7299 * This method returns a vector of size 'this->getNumberOfCells()'.
7300 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7302 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const
7304 int ncell=getNumberOfCells();
7305 std::vector<bool> ret(ncell);
7306 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7307 const int *c=getNodalConnectivity()->getConstPointer();
7308 for(int i=0;i<ncell;i++)
7310 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7311 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7312 ret[i]=cm.isQuadratic();
7318 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7320 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7322 if(other->getType()!=UNSTRUCTURED)
7323 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7324 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7325 return MergeUMeshes(this,otherC);
7329 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7330 * computed by averaging coordinates of cell nodes, so this method is not a right
7331 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7332 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7333 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7334 * components. The caller is to delete this array using decrRef() as it is
7336 * \throw If the coordinates array is not set.
7337 * \throw If the nodal connectivity of cells is not defined.
7338 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7340 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7342 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7343 int spaceDim=getSpaceDimension();
7344 int nbOfCells=getNumberOfCells();
7345 ret->alloc(nbOfCells,spaceDim);
7346 ret->copyStringInfoFrom(*getCoords());
7347 double *ptToFill=ret->getPointer();
7348 const int *nodal=_nodal_connec->getConstPointer();
7349 const int *nodalI=_nodal_connec_index->getConstPointer();
7350 const double *coor=_coords->getConstPointer();
7351 for(int i=0;i<nbOfCells;i++)
7353 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7354 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7361 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7362 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7364 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7365 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7367 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7368 * \throw If \a this is not fully defined (coordinates and connectivity)
7369 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7371 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const
7373 checkFullyDefined();
7374 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7375 int spaceDim=getSpaceDimension();
7376 int nbOfCells=getNumberOfCells();
7377 int nbOfNodes=getNumberOfNodes();
7378 ret->alloc(nbOfCells,spaceDim);
7379 double *ptToFill=ret->getPointer();
7380 const int *nodal=_nodal_connec->getConstPointer();
7381 const int *nodalI=_nodal_connec_index->getConstPointer();
7382 const double *coor=_coords->getConstPointer();
7383 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7385 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7386 std::fill(ptToFill,ptToFill+spaceDim,0.);
7387 if(type!=INTERP_KERNEL::NORM_POLYHED)
7389 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7391 if(*conn>=0 && *conn<nbOfNodes)
7392 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7395 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7396 throw INTERP_KERNEL::Exception(oss.str().c_str());
7399 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7400 if(nbOfNodesInCell>0)
7401 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7404 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7405 throw INTERP_KERNEL::Exception(oss.str().c_str());
7410 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7412 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7414 if(*it>=0 && *it<nbOfNodes)
7415 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7418 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7419 throw INTERP_KERNEL::Exception(oss.str().c_str());
7423 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7426 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7427 throw INTERP_KERNEL::Exception(oss.str().c_str());
7435 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7436 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7437 * are specified via an array of cell ids.
7438 * \warning Validity of the specified cell ids is not checked!
7439 * Valid range is [ 0, \a this->getNumberOfCells() ).
7440 * \param [in] begin - an array of cell ids of interest.
7441 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7442 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7443 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7444 * caller is to delete this array using decrRef() as it is no more needed.
7445 * \throw If the coordinates array is not set.
7446 * \throw If the nodal connectivity of cells is not defined.
7448 * \if ENABLE_EXAMPLES
7449 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7450 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7453 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7455 DataArrayDouble *ret=DataArrayDouble::New();
7456 int spaceDim=getSpaceDimension();
7457 int nbOfTuple=(int)std::distance(begin,end);
7458 ret->alloc(nbOfTuple,spaceDim);
7459 double *ptToFill=ret->getPointer();
7460 double *tmp=new double[spaceDim];
7461 const int *nodal=_nodal_connec->getConstPointer();
7462 const int *nodalI=_nodal_connec_index->getConstPointer();
7463 const double *coor=_coords->getConstPointer();
7464 for(const int *w=begin;w!=end;w++)
7466 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7467 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7475 * 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".
7476 * So the returned instance will have 4 components and \c this->getNumberOfCells() tuples.
7477 * So this method expects that \a this has a spaceDimension equal to 3 and meshDimension equal to 2.
7478 * The computation of the plane equation is done using each time the 3 first nodes of 2D cells.
7479 * This method is useful to detect 2D cells in 3D space that are not coplanar.
7481 * \return DataArrayDouble * - a new instance of DataArrayDouble having 4 components and a number of tuples equal to number of cells in \a this.
7482 * \throw If spaceDim!=3 or meshDim!=2.
7483 * \throw If connectivity of \a this is invalid.
7484 * \throw If connectivity of a cell in \a this points to an invalid node.
7486 DataArrayDouble *MEDCouplingUMesh::computePlaneEquationOf3DFaces() const
7488 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New());
7489 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
7490 if(getSpaceDimension()!=3 || getMeshDimension()!=2)
7491 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::computePlaneEquationOf3DFaces : This method must be applied on a mesh having meshDimension equal 2 and a spaceDimension equal to 3 !");
7492 ret->alloc(nbOfCells,4);
7493 double *retPtr(ret->getPointer());
7494 const int *nodal(_nodal_connec->begin()),*nodalI(_nodal_connec_index->begin());
7495 const double *coor(_coords->begin());
7496 for(int i=0;i<nbOfCells;i++,nodalI++,retPtr+=4)
7498 double matrix[16]={0,0,0,1,0,0,0,1,0,0,0,1,1,1,1,0},matrix2[16];
7499 if(nodalI[1]-nodalI[0]>=3)
7501 for(int j=0;j<3;j++)
7503 int nodeId(nodal[nodalI[0]+1+j]);
7504 if(nodeId>=0 && nodeId<nbOfNodes)
7505 std::copy(coor+nodeId*3,coor+(nodeId+1)*3,matrix+4*j);
7508 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! This cell points to an invalid nodeId : " << nodeId << " !";
7509 throw INTERP_KERNEL::Exception(oss.str().c_str());
7515 std::ostringstream oss; oss << "MEDCouplingUMesh::computePlaneEquationOf3DFaces : invalid 2D cell #" << i << " ! Must be constitued by more than 3 nodes !";
7516 throw INTERP_KERNEL::Exception(oss.str().c_str());
7518 INTERP_KERNEL::inverseMatrix(matrix,4,matrix2);
7519 retPtr[0]=matrix2[3]; retPtr[1]=matrix2[7]; retPtr[2]=matrix2[11]; retPtr[3]=matrix2[15];
7525 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7528 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da)
7531 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7532 da->checkAllocated();
7533 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName(),0);
7535 int nbOfTuples=da->getNumberOfTuples();
7536 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7537 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7538 c->alloc(2*nbOfTuples,1);
7539 cI->alloc(nbOfTuples+1,1);
7540 int *cp=c->getPointer();
7541 int *cip=cI->getPointer();
7543 for(int i=0;i<nbOfTuples;i++)
7545 *cp++=INTERP_KERNEL::NORM_POINT1;
7549 ret->setConnectivity(c,cI,true);
7553 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7554 * Cells and nodes of
7555 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7556 * \param [in] mesh1 - the first mesh.
7557 * \param [in] mesh2 - the second mesh.
7558 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7559 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7560 * is no more needed.
7561 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7562 * \throw If the coordinates array is not set in none of the meshes.
7563 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7564 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7566 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7568 std::vector<const MEDCouplingUMesh *> tmp(2);
7569 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7570 return MergeUMeshes(tmp);
7574 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7575 * Cells and nodes of
7576 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7577 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7578 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7579 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7580 * is no more needed.
7581 * \throw If \a a.size() == 0.
7582 * \throw If \a a[ *i* ] == NULL.
7583 * \throw If the coordinates array is not set in none of the meshes.
7584 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7585 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7587 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a)
7589 std::size_t sz=a.size();
7591 return MergeUMeshesLL(a);
7592 for(std::size_t ii=0;ii<sz;ii++)
7595 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7596 throw INTERP_KERNEL::Exception(oss.str().c_str());
7598 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7599 std::vector< const MEDCouplingUMesh * > aa(sz);
7601 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7603 const MEDCouplingUMesh *cur=a[i];
7604 const DataArrayDouble *coo=cur->getCoords();
7606 spaceDim=coo->getNumberOfComponents();
7609 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7610 for(std::size_t i=0;i<sz;i++)
7612 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7615 return MergeUMeshesLL(aa);
7620 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a)
7623 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7624 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7625 int meshDim=(*it)->getMeshDimension();
7626 int nbOfCells=(*it)->getNumberOfCells();
7627 int meshLgth=(*it++)->getMeshLength();
7628 for(;it!=a.end();it++)
7630 if(meshDim!=(*it)->getMeshDimension())
7631 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7632 nbOfCells+=(*it)->getNumberOfCells();
7633 meshLgth+=(*it)->getMeshLength();
7635 std::vector<const MEDCouplingPointSet *> aps(a.size());
7636 std::copy(a.begin(),a.end(),aps.begin());
7637 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7638 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7639 ret->setCoords(pts);
7640 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7641 c->alloc(meshLgth,1);
7642 int *cPtr=c->getPointer();
7643 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7644 cI->alloc(nbOfCells+1,1);
7645 int *cIPtr=cI->getPointer();
7649 for(it=a.begin();it!=a.end();it++)
7651 int curNbOfCell=(*it)->getNumberOfCells();
7652 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7653 const int *curC=(*it)->_nodal_connec->getConstPointer();
7654 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7655 for(int j=0;j<curNbOfCell;j++)
7657 const int *src=curC+curCI[j];
7659 for(;src!=curC+curCI[j+1];src++,cPtr++)
7667 offset+=curCI[curNbOfCell];
7668 offset2+=(*it)->getNumberOfNodes();
7671 ret->setConnectivity(c,cI,true);
7678 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7679 * dimension and sharing the node coordinates array.
7680 * All cells of the first mesh precede all cells of the second mesh
7681 * within the result mesh.
7682 * \param [in] mesh1 - the first mesh.
7683 * \param [in] mesh2 - the second mesh.
7684 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7685 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7686 * is no more needed.
7687 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7688 * \throw If the meshes do not share the node coordinates array.
7689 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7690 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7692 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2)
7694 std::vector<const MEDCouplingUMesh *> tmp(2);
7695 tmp[0]=mesh1; tmp[1]=mesh2;
7696 return MergeUMeshesOnSameCoords(tmp);
7700 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7701 * dimension and sharing the node coordinates array.
7702 * All cells of the *i*-th mesh precede all cells of the
7703 * (*i*+1)-th mesh within the result mesh.
7704 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7705 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7706 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7707 * is no more needed.
7708 * \throw If \a a.size() == 0.
7709 * \throw If \a a[ *i* ] == NULL.
7710 * \throw If the meshes do not share the node coordinates array.
7711 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7712 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7714 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7717 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7718 for(std::size_t ii=0;ii<meshes.size();ii++)
7721 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7722 throw INTERP_KERNEL::Exception(oss.str().c_str());
7724 const DataArrayDouble *coords=meshes.front()->getCoords();
7725 int meshDim=meshes.front()->getMeshDimension();
7726 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7728 int meshIndexLgth=0;
7729 for(;iter!=meshes.end();iter++)
7731 if(coords!=(*iter)->getCoords())
7732 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7733 if(meshDim!=(*iter)->getMeshDimension())
7734 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7735 meshLgth+=(*iter)->getMeshLength();
7736 meshIndexLgth+=(*iter)->getNumberOfCells();
7738 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7739 nodal->alloc(meshLgth,1);
7740 int *nodalPtr=nodal->getPointer();
7741 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7742 nodalIndex->alloc(meshIndexLgth+1,1);
7743 int *nodalIndexPtr=nodalIndex->getPointer();
7745 for(iter=meshes.begin();iter!=meshes.end();iter++)
7747 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7748 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7749 int nbOfCells=(*iter)->getNumberOfCells();
7750 int meshLgth2=(*iter)->getMeshLength();
7751 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7752 if(iter!=meshes.begin())
7753 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7755 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7758 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7759 ret->setName("merge");
7760 ret->setMeshDimension(meshDim);
7761 ret->setConnectivity(nodal,nodalIndex,true);
7762 ret->setCoords(coords);
7767 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7768 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7769 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7770 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7771 * New" mode are returned for each input mesh.
7772 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7773 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7774 * valid values [0,1,2], see zipConnectivityTraducer().
7775 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7776 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7777 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7779 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7780 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7781 * is no more needed.
7782 * \throw If \a meshes.size() == 0.
7783 * \throw If \a meshes[ *i* ] == NULL.
7784 * \throw If the meshes do not share the node coordinates array.
7785 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7786 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7787 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7788 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7790 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7792 //All checks are delegated to MergeUMeshesOnSameCoords
7793 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7794 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7795 corr.resize(meshes.size());
7796 std::size_t nbOfMeshes=meshes.size();
7798 const int *o2nPtr=o2n->getConstPointer();
7799 for(std::size_t i=0;i<nbOfMeshes;i++)
7801 DataArrayInt *tmp=DataArrayInt::New();
7802 int curNbOfCells=meshes[i]->getNumberOfCells();
7803 tmp->alloc(curNbOfCells,1);
7804 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7805 offset+=curNbOfCells;
7806 tmp->setName(meshes[i]->getName());
7813 * Makes all given meshes share the nodal connectivity array. The common connectivity
7814 * array is created by concatenating the connectivity arrays of all given meshes. All
7815 * the given meshes must be of the same space dimension but dimension of cells **can
7816 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7817 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7818 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7819 * \param [in,out] meshes - a vector of meshes to update.
7820 * \throw If any of \a meshes is NULL.
7821 * \throw If the coordinates array is not set in any of \a meshes.
7822 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7823 * \throw If \a meshes are of different space dimension.
7825 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes)
7827 std::size_t sz=meshes.size();
7830 std::vector< const DataArrayDouble * > coords(meshes.size());
7831 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7832 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7836 (*it)->checkConnectivityFullyDefined();
7837 const DataArrayDouble *coo=(*it)->getCoords();
7842 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7843 oss << " has no coordinate array defined !";
7844 throw INTERP_KERNEL::Exception(oss.str().c_str());
7849 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7850 oss << " is null !";
7851 throw INTERP_KERNEL::Exception(oss.str().c_str());
7854 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7855 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7856 int offset=(*it)->getNumberOfNodes();
7857 (*it++)->setCoords(res);
7858 for(;it!=meshes.end();it++)
7860 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7861 (*it)->setCoords(res);
7862 (*it)->shiftNodeNumbersInConn(offset);
7863 offset+=oldNumberOfNodes;
7868 * Merges nodes coincident with a given precision within all given meshes that share
7869 * the nodal connectivity array. The given meshes **can be of different** mesh
7870 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7871 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7872 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7873 * \param [in,out] meshes - a vector of meshes to update.
7874 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7875 * \throw If any of \a meshes is NULL.
7876 * \throw If the \a meshes do not share the same node coordinates array.
7877 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7879 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps)
7883 std::set<const DataArrayDouble *> s;
7884 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7887 s.insert((*it)->getCoords());
7890 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 !";
7891 throw INTERP_KERNEL::Exception(oss.str().c_str());
7896 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 !";
7897 throw INTERP_KERNEL::Exception(oss.str().c_str());
7899 const DataArrayDouble *coo=*(s.begin());
7903 DataArrayInt *comm,*commI;
7904 coo->findCommonTuples(eps,-1,comm,commI);
7905 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7906 int oldNbOfNodes=coo->getNumberOfTuples();
7908 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7909 if(oldNbOfNodes==newNbOfNodes)
7911 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7912 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7914 (*it)->renumberNodesInConn(o2n->getConstPointer());
7915 (*it)->setCoords(newCoords);
7920 * 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.
7921 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7922 * \param isQuad specifies the policy of connectivity.
7923 * @ret in/out parameter in which the result will be append
7925 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7927 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7928 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7929 ret.push_back(cm.getExtrudedType());
7930 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7933 case INTERP_KERNEL::NORM_POINT1:
7935 ret.push_back(connBg[1]);
7936 ret.push_back(connBg[1]+nbOfNodesPerLev);
7939 case INTERP_KERNEL::NORM_SEG2:
7941 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7942 ret.insert(ret.end(),conn,conn+4);
7945 case INTERP_KERNEL::NORM_SEG3:
7947 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7948 ret.insert(ret.end(),conn,conn+8);
7951 case INTERP_KERNEL::NORM_QUAD4:
7953 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7954 ret.insert(ret.end(),conn,conn+8);
7957 case INTERP_KERNEL::NORM_TRI3:
7959 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7960 ret.insert(ret.end(),conn,conn+6);
7963 case INTERP_KERNEL::NORM_TRI6:
7965 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,
7966 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7967 ret.insert(ret.end(),conn,conn+15);
7970 case INTERP_KERNEL::NORM_QUAD8:
7973 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7974 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7975 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7977 ret.insert(ret.end(),conn,conn+20);
7980 case INTERP_KERNEL::NORM_POLYGON:
7982 std::back_insert_iterator< std::vector<int> > ii(ret);
7983 std::copy(connBg+1,connEnd,ii);
7985 std::reverse_iterator<const int *> rConnBg(connEnd);
7986 std::reverse_iterator<const int *> rConnEnd(connBg+1);
7987 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7988 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7989 for(std::size_t i=0;i<nbOfRadFaces;i++)
7992 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7993 std::copy(conn,conn+4,ii);
7998 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
8003 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
8005 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
8008 double v[3]={0.,0.,0.};
8009 std::size_t sz=std::distance(begin,end);
8014 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];
8015 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
8016 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
8018 double ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8020 // Try using quadratic points if standard points are degenerated (for example a QPOLYG with two
8021 // SEG3 forming a circle):
8022 if (fabs(ret) < INTERP_KERNEL::DEFAULT_ABS_TOL && isQuadratic)
8024 v[0] = 0.0; v[1] = 0.0; v[2] = 0.0;
8025 for(std::size_t j=0;j<sz;j++)
8027 if (j%2) // current point i is quadratic, next point i+1 is standard
8030 ip1 = (j+1)%sz; // ip1 = "i+1"
8032 else // current point i is standard, next point i+1 is quadratic
8037 v[0]+=coords[3*begin[i]+1]*coords[3*begin[ip1]+2]-coords[3*begin[i]+2]*coords[3*begin[ip1]+1];
8038 v[1]+=coords[3*begin[i]+2]*coords[3*begin[ip1]]-coords[3*begin[i]]*coords[3*begin[ip1]+2];
8039 v[2]+=coords[3*begin[i]]*coords[3*begin[ip1]+1]-coords[3*begin[i]+1]*coords[3*begin[ip1]];
8041 ret = vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2];
8047 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
8049 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
8051 std::vector<std::pair<int,int> > edges;
8052 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8053 const int *bgFace=begin;
8054 for(std::size_t i=0;i<nbOfFaces;i++)
8056 const int *endFace=std::find(bgFace+1,end,-1);
8057 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8058 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8060 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8061 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
8063 edges.push_back(p1);
8067 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
8071 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
8073 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
8075 double vec0[3],vec1[3];
8076 std::size_t sz=std::distance(begin,end);
8078 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
8079 int nbOfNodes=(int)sz/2;
8080 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
8081 const double *pt0=coords+3*begin[0];
8082 const double *pt1=coords+3*begin[nbOfNodes];
8083 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
8084 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
8087 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
8089 std::size_t sz=std::distance(begin,end);
8090 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8091 std::size_t nbOfNodes(sz/2);
8092 std::copy(begin,end,(int *)tmp);
8093 for(std::size_t j=1;j<nbOfNodes;j++)
8095 begin[j]=tmp[nbOfNodes-j];
8096 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
8100 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
8102 std::size_t sz=std::distance(begin,end);
8104 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
8105 double vec0[3],vec1[3];
8106 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
8107 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];
8108 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;
8111 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
8113 std::size_t sz=std::distance(begin,end);
8115 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
8117 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
8118 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
8119 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
8123 * 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 )
8124 * 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
8127 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
8128 * \param [in] coords the coordinates with nb of components exactly equal to 3
8129 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
8130 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
8131 * \param [out] res the result is put at the end of the vector without any alteration of the data.
8133 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res)
8135 int nbFaces=std::count(begin+1,end,-1)+1;
8136 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
8137 double *vPtr=v->getPointer();
8138 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
8139 double *pPtr=p->getPointer();
8140 const int *stFaceConn=begin+1;
8141 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
8143 const int *endFaceConn=std::find(stFaceConn,end,-1);
8144 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
8145 stFaceConn=endFaceConn+1;
8147 pPtr=p->getPointer(); vPtr=v->getPointer();
8148 DataArrayInt *comm1=0,*commI1=0;
8149 v->findCommonTuples(eps,-1,comm1,commI1);
8150 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
8151 const int *comm1Ptr=comm1->getConstPointer();
8152 const int *commI1Ptr=commI1->getConstPointer();
8153 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
8154 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
8156 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
8157 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
8158 mm->finishInsertingCells();
8160 for(int i=0;i<nbOfGrps1;i++)
8162 int vecId=comm1Ptr[commI1Ptr[i]];
8163 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8164 DataArrayInt *comm2=0,*commI2=0;
8165 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
8166 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
8167 const int *comm2Ptr=comm2->getConstPointer();
8168 const int *commI2Ptr=commI2->getConstPointer();
8169 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
8170 for(int j=0;j<nbOfGrps2;j++)
8172 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
8174 res->insertAtTheEnd(begin,end);
8175 res->pushBackSilent(-1);
8179 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
8180 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
8181 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
8182 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
8183 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
8184 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
8185 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
8186 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
8187 const int *idsNodePtr=idsNode->getConstPointer();
8188 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];
8189 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
8190 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
8191 if(std::abs(norm)>eps)
8193 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
8194 mm3->rotate(center,vec,angle);
8196 mm3->changeSpaceDimension(2);
8197 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
8198 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
8199 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
8200 int nbOfCells=mm4->getNumberOfCells();
8201 for(int k=0;k<nbOfCells;k++)
8204 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
8205 res->pushBackSilent(idsNodePtr[*work]);
8206 res->pushBackSilent(-1);
8211 res->popBackSilent();
8215 * 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
8216 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
8218 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
8219 * \param [in] coords coordinates expected to have 3 components.
8220 * \param [in] begin start of the nodal connectivity of the face.
8221 * \param [in] end end of the nodal connectivity (excluded) of the face.
8222 * \param [out] v the normalized vector of size 3
8223 * \param [out] p the pos of plane
8225 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p)
8227 std::size_t nbPoints=std::distance(begin,end);
8229 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
8230 double vec[3]={0.,0.,0.};
8232 bool refFound=false;
8233 for(;j<nbPoints-1 && !refFound;j++)
8235 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
8236 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
8237 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
8238 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
8242 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
8245 for(std::size_t i=j;i<nbPoints-1;i++)
8248 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
8249 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
8250 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
8251 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
8254 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
8255 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];
8256 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
8259 v[0]/=norm; v[1]/=norm; v[2]/=norm;
8260 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
8264 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
8268 * This method tries to obtain a well oriented polyhedron.
8269 * If the algorithm fails, an exception will be thrown.
8271 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords)
8273 std::list< std::pair<int,int> > edgesOK,edgesFinished;
8274 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
8275 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
8277 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
8278 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
8279 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
8281 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
8284 std::size_t smthChanged=0;
8285 for(std::size_t i=0;i<nbOfFaces;i++)
8287 endFace=std::find(bgFace+1,end,-1);
8288 nbOfEdgesInFace=std::distance(bgFace,endFace);
8292 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8294 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8295 std::pair<int,int> p2(p1.second,p1.first);
8296 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
8297 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
8298 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
8303 std::reverse(bgFace+1,endFace);
8304 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
8306 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
8307 std::pair<int,int> p2(p1.second,p1.first);
8308 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
8309 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8310 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
8311 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
8312 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
8313 if(it!=edgesOK.end())
8316 edgesFinished.push_back(p1);
8319 edgesOK.push_back(p1);
8326 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
8328 if(!edgesOK.empty())
8329 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
8330 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
8331 {//not lucky ! The first face was not correctly oriented : reorient all faces...
8333 for(std::size_t i=0;i<nbOfFaces;i++)
8335 endFace=std::find(bgFace+1,end,-1);
8336 std::reverse(bgFace+1,endFace);
8342 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshLinear(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8344 int nbOfNodesExpected(skin->getNumberOfNodes());
8345 const int *n2oPtr(n2o->getConstPointer());
8346 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8347 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8348 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8349 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8350 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8351 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8352 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_POLYGON;
8353 if(nbOfNodesExpected<1)
8355 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8356 *work++=n2oPtr[prevNode];
8357 for(int i=1;i<nbOfNodesExpected;i++)
8359 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
8361 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8362 conn.erase(prevNode);
8365 int curNode(*(conn.begin()));
8366 *work++=n2oPtr[curNode];
8367 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8368 shar.erase(prevCell);
8371 prevCell=*(shar.begin());
8375 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 2 !");
8378 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected 1 !");
8381 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshLinear : presence of unexpected cell !");
8386 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMeshQuadratic(const MEDCouplingUMesh *skin, const DataArrayInt *n2o) const
8388 int nbOfNodesExpected(skin->getNumberOfNodes());
8389 int nbOfTurn(nbOfNodesExpected/2);
8390 const int *n2oPtr(n2o->getConstPointer());
8391 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
8392 skin->getReverseNodalConnectivity(revNodal,revNodalI);
8393 const int *revNodalPtr(revNodal->getConstPointer()),*revNodalIPtr(revNodalI->getConstPointer());
8394 const int *nodalPtr(skin->getNodalConnectivity()->getConstPointer());
8395 const int *nodalIPtr(skin->getNodalConnectivityIndex()->getConstPointer());
8396 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfNodesExpected+1,1);
8397 int *work(ret->getPointer()); *work++=INTERP_KERNEL::NORM_QPOLYG;
8398 if(nbOfNodesExpected<1)
8400 int prevCell(0),prevNode(nodalPtr[nodalIPtr[0]+1]);
8401 *work=n2oPtr[prevNode]; work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[0]+3]]; work++;
8402 for(int i=1;i<nbOfTurn;i++)
8404 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==4)
8406 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8407 conn.erase(prevNode);
8410 int curNode(*(conn.begin()));
8411 *work=n2oPtr[curNode];
8412 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8413 shar.erase(prevCell);
8416 int curCell(*(shar.begin()));
8417 work[nbOfTurn]=n2oPtr[nodalPtr[nodalIPtr[curCell]+3]];
8423 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 2 !");
8426 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected 1 !");
8429 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMeshQuadratic : presence of unexpected cell !");
8435 * This method makes the assumption spacedimension == meshdimension == 2.
8436 * This method works only for linear cells.
8438 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
8440 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const
8442 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
8443 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
8444 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin(computeSkin());
8445 int oldNbOfNodes(skin->getNumberOfNodes());
8446 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n(skin->zipCoordsTraducer());
8447 int nbOfNodesExpected(skin->getNumberOfNodes());
8448 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o(o2n->invertArrayO2N2N2O(oldNbOfNodes));
8449 int nbCells(skin->getNumberOfCells());
8450 if(nbCells==nbOfNodesExpected)
8451 return buildUnionOf2DMeshLinear(skin,n2o);
8452 else if(2*nbCells==nbOfNodesExpected)
8453 return buildUnionOf2DMeshQuadratic(skin,n2o);
8455 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part of a 2D mesh !");
8459 * This method makes the assumption spacedimension == meshdimension == 3.
8460 * This method works only for linear cells.
8462 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8464 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const
8466 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8467 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8468 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8469 const int *conn=m->getNodalConnectivity()->getConstPointer();
8470 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8471 int nbOfCells=m->getNumberOfCells();
8472 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8473 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8476 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8477 for(int i=1;i<nbOfCells;i++)
8480 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8486 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8487 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8489 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt)
8493 for(int i=0;i<nbOfNodesInCell;i++)
8494 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8495 else if(spaceDim==2)
8497 for(int i=0;i<nbOfNodesInCell;i++)
8499 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8504 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8507 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData, DataArrayByte *byteData) const
8509 int nbOfCells=getNumberOfCells();
8511 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8512 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};
8513 ofs << " <" << getVTKDataSetType() << ">\n";
8514 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8515 ofs << " <PointData>\n" << pointData << std::endl;
8516 ofs << " </PointData>\n";
8517 ofs << " <CellData>\n" << cellData << std::endl;
8518 ofs << " </CellData>\n";
8519 ofs << " <Points>\n";
8520 if(getSpaceDimension()==3)
8521 _coords->writeVTK(ofs,8,"Points",byteData);
8524 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8525 coo->writeVTK(ofs,8,"Points",byteData);
8527 ofs << " </Points>\n";
8528 ofs << " <Cells>\n";
8529 const int *cPtr=_nodal_connec->getConstPointer();
8530 const int *cIPtr=_nodal_connec_index->getConstPointer();
8531 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8532 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8533 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8534 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8535 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8536 int szFaceOffsets=0,szConn=0;
8537 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8540 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8543 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8544 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8548 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8549 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8550 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8551 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8552 w4=std::copy(c.begin(),c.end(),w4);
8555 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE+1);
8556 types->writeVTK(ofs,8,"UInt8","types",byteData);
8557 offsets->writeVTK(ofs,8,"Int32","offsets",byteData);
8558 if(szFaceOffsets!=0)
8559 {//presence of Polyhedra
8560 connectivity->reAlloc(szConn);
8561 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets",byteData);
8562 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8563 w1=faces->getPointer();
8564 for(int i=0;i<nbOfCells;i++)
8565 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8567 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8569 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8570 for(int j=0;j<nbFaces;j++)
8572 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8573 *w1++=(int)std::distance(w6,w5);
8574 w1=std::copy(w6,w5,w1);
8578 faces->writeVTK(ofs,8,"Int32","faces",byteData);
8580 connectivity->writeVTK(ofs,8,"Int32","connectivity",byteData);
8581 ofs << " </Cells>\n";
8582 ofs << " </Piece>\n";
8583 ofs << " </" << getVTKDataSetType() << ">\n";
8586 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const
8588 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8590 { stream << " Not set !"; return ; }
8591 stream << " Mesh dimension : " << _mesh_dim << ".";
8595 { stream << " No coordinates set !"; return ; }
8596 if(!_coords->isAllocated())
8597 { stream << " Coordinates set but not allocated !"; return ; }
8598 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8599 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8600 if(!_nodal_connec_index)
8601 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8602 if(!_nodal_connec_index->isAllocated())
8603 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8604 int lgth=_nodal_connec_index->getNumberOfTuples();
8605 int cpt=_nodal_connec_index->getNumberOfComponents();
8606 if(cpt!=1 || lgth<1)
8608 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8611 std::string MEDCouplingUMesh::getVTKDataSetType() const
8613 return std::string("UnstructuredGrid");
8617 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8618 * returns a result mesh constituted by polygons.
8619 * Thus the final result contains all nodes from m1 plus new nodes. However it doesn't necessarily contains
8620 * all nodes from m2.
8621 * The meshes should be in 2D space. In
8622 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8624 * \param [in] m1 - the first input mesh which is a partitioned object.
8625 * \param [in] m2 - the second input mesh which is a partition tool.
8626 * \param [in] eps - precision used to detect coincident mesh entities.
8627 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8628 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8629 * this array using decrRef() as it is no more needed.
8630 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8631 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8632 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8633 * any cell of \a m2. The caller is to delete this array using decrRef() as
8634 * it is no more needed.
8635 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8636 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8637 * is no more needed.
8638 * \throw If the coordinates array is not set in any of the meshes.
8639 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8640 * \throw If any of the meshes is not a 2D mesh in 2D space.
8642 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
8643 double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2)
8645 m1->checkFullyDefined();
8646 m2->checkFullyDefined();
8647 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8648 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8650 // Step 1: compute all edge intersections (new nodes)
8651 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8652 MEDCouplingUMesh *m1Desc=0,*m2Desc=0; // descending connec. meshes
8653 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8654 std::vector<double> addCoo,addCoordsQuadratic; // coordinates of newly created nodes
8655 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8656 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8657 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,
8658 m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8659 addCoo, m2Desc,desc2,descIndx2,revDesc2,revDescIndx2);
8660 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8661 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8662 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8664 // Step 2: re-order newly created nodes according to the ordering found in m2
8665 std::vector< std::vector<int> > intersectEdge2;
8666 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8667 subDiv2.clear(); dd5=0; dd6=0;
8670 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8671 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8672 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8673 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8675 // Step 4: Prepare final result:
8676 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8677 addCooDa->alloc((int)(addCoo.size())/2,2);
8678 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8679 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8680 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8681 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8682 std::vector<const DataArrayDouble *> coordss(4);
8683 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8684 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8685 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8686 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8687 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8688 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8689 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8690 ret->setConnectivity(conn,connI,true);
8691 ret->setCoords(coo);
8692 cellNb1=c1.retn(); cellNb2=c2.retn();
8698 * Private. Third step of the partitioning algorithm (Intersect2DMeshes): reconstruct full 2D cells from the
8699 * (newly created) nodes corresponding to the edge intersections.
8701 * @param[out] cr, crI connectivity of the resulting mesh
8702 * @param[out] cNb1, cNb2 correspondance arrays giving for the merged mesh the initial cells IDs in m1 / m2
8703 * TODO: describe input parameters
8705 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8706 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8707 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8708 const std::vector<double>& addCoords,
8709 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8711 static const int SPACEDIM=2;
8712 const double *coo1=m1->getCoords()->getConstPointer();
8713 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8714 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8715 int offset1=m1->getNumberOfNodes();
8716 const double *coo2=m2->getCoords()->getConstPointer();
8717 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8718 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8719 int offset2=offset1+m2->getNumberOfNodes();
8720 int offset3=offset2+((int)addCoords.size())/2;
8721 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8722 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8723 // Here a BBTree on 2D-cells, not on segments:
8724 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8725 int ncell1=m1->getNumberOfCells();
8727 for(int i=0;i<ncell1;i++)
8729 std::vector<int> candidates2;
8730 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8731 std::map<INTERP_KERNEL::Node *,int> mapp;
8732 std::map<int,INTERP_KERNEL::Node *> mappRev;
8733 INTERP_KERNEL::QuadraticPolygon pol1;
8734 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8735 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8736 // Populate mapp and mappRev with nodes from the current cell (i) from mesh1 - this also builds the Node* objects:
8737 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8738 // pol1 is the full cell from mesh2, in QP format, with all the additional intersecting nodes.
8739 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8740 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8742 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
8743 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8744 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8745 for(it1.first();!it1.finished();it1.next())
8746 edges1.insert(it1.current()->getPtr());
8748 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare; // common edges
8749 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8751 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8753 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8754 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8755 // Complete mapping with elements coming from the current cell it2 in mesh2:
8756 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8757 // pol2 is the new QP in the final merged result.
8758 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8759 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2, /* output */ edgesIn2ForShare);
8762 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8764 pol1.initLocationsWithOther(pol2s[ii]);
8765 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8766 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8767 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8769 // Deals with remaining (non-consumed) edges from m1: these are the edges that were never touched
8770 // by m2 but that we still want to keep in the final result.
8775 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8777 catch(INTERP_KERNEL::Exception& e)
8779 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();
8780 throw INTERP_KERNEL::Exception(oss.str().c_str());
8783 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8784 (*it).second->decrRef();
8788 void IKGeo2DInternalMapper2(INTERP_KERNEL::Node *n, const std::map<INTERP_KERNEL::Node *,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
8790 std::map<INTERP_KERNEL::Node *,int>::const_iterator it(m.find(n));
8792 throw INTERP_KERNEL::Exception("Internal error in remapping !");
8793 int v((*it).second);
8794 if(v==forbVal0 || v==forbVal1)
8796 if(std::find(isect.begin(),isect.end(),v)==isect.end())
8800 bool IKGeo2DInternalMapper(const INTERP_KERNEL::ComposedEdge& c, const std::map<INTERP_KERNEL::Node *,int>& m, int forbVal0, int forbVal1, std::vector<int>& isect)
8805 bool presenceOfOn(false);
8806 for(int i=0;i<sz;i++)
8808 INTERP_KERNEL::ElementaryEdge *e(c[i]);
8809 if(e->getLoc()!=INTERP_KERNEL::FULL_ON_1)
8811 IKGeo2DInternalMapper2(e->getStartNode(),m,forbVal0,forbVal1,isect);
8812 IKGeo2DInternalMapper2(e->getEndNode(),m,forbVal0,forbVal1,isect);
8814 return presenceOfOn;
8818 * 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.
8819 * 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.
8820 * 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.
8821 * \b WARNING : is returned value is different from 0 a call to MEDCouplingUMesh::mergeNodes is necessary to avoid to have a non conform mesh.
8823 * \return int - the number of new nodes created (in most of cases 0).
8825 * \throw If \a this is not coherent.
8826 * \throw If \a this has not spaceDim equal to 2.
8827 * \throw If \a this has not meshDim equal to 2.
8828 * \throw If some subcells needed to be split are orphan.
8829 * \sa MEDCouplingUMesh::conformize2D
8831 int MEDCouplingUMesh::split2DCells(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *midOpt, const DataArrayInt *midOptI)
8833 if(!desc || !descI || !subNodesInSeg || !subNodesInSegI)
8834 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : the 4 first arrays must be not null !");
8835 desc->checkAllocated(); descI->checkAllocated(); subNodesInSeg->checkAllocated(); subNodesInSegI->checkAllocated();
8836 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
8837 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : This method only works for meshes with spaceDim=2 and meshDim=2 !");
8838 if(midOpt==0 && midOptI==0)
8840 split2DCellsLinear(desc,descI,subNodesInSeg,subNodesInSegI);
8843 else if(midOpt!=0 && midOptI!=0)
8844 return split2DCellsQuadratic(desc,descI,subNodesInSeg,subNodesInSegI,midOpt,midOptI);
8846 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCells : middle parameters must be set to null for all or not null for all.");
8850 * \b WARNING this method is \b potentially \b non \b const (if returned array is empty).
8851 * \b WARNING this method lead to have a non geometric type sorted mesh (for MED file users) !
8852 * 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
8853 * will suppress such edges to use sub edges in \a this. So this method does not add nodes in \a this if merged edges are both linear (INTERP_KERNEL::NORM_SEG2).
8854 * In the other cases new nodes can be created. If any are created, they will be appended at the end of the coordinates object before the invokation of this method.
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 initial quadraticness of geometric type.
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 non const method works on 2D mesh. This method scans every cell in \a this and look if each edge constituting this cell is not mergeable with neighbors edges of that cell.
8994 * If yes, the cell is "repaired" to minimize at most its number of edges. So this method do not change the overall shape of cells in \a this (with eps precision).
8995 * This method do not take care of shared edges between cells, so this method can lead to a non conform mesh (\a this). If a conform mesh is required you're expected
8996 * to invoke MEDCouplingUMesh::mergeNodes and MEDCouplingUMesh::conformize2D right after this call.
8997 * This method works on any 2D geometric types of cell (even static one). If a cell is touched its type becomes dynamic automaticaly. For 2D "repaired" quadratic cells
8998 * new nodes for center of merged edges is are systematically created and appended at the end of the previously existing nodes.
9000 * If the returned array is empty it means that nothing has changed in \a this (as if it were a const method). If the array is not empty the connectivity of \a this is modified
9001 * using new instance, idem for coordinates.
9003 * If \a this is constituted by only linear 2D cells, this method is close to the computation of the convex hull of each cells in \a this.
9005 * \return DataArrayInt * - The list of cellIds in \a this that have at least one edge colinearized.
9007 * \throw If \a this is not coherent.
9008 * \throw If \a this has not spaceDim equal to 2.
9009 * \throw If \a this has not meshDim equal to 2.
9011 * \sa MEDCouplingUMesh::conformize2D, MEDCouplingUMesh::mergeNodes, MEDCouplingUMesh::convexEnvelop2D.
9013 DataArrayInt *MEDCouplingUMesh::colinearize2D(double eps)
9015 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
9017 if(getSpaceDimension()!=2 || getMeshDimension()!=2)
9018 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::colinearize2D : This method only works for meshes with spaceDim=2 and meshDim=2 !");
9019 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
9020 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
9021 int nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
9022 const int *cptr(_nodal_connec->begin()),*ciptr(_nodal_connec_index->begin());
9023 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newc(DataArrayInt::New()),newci(DataArrayInt::New()); newci->alloc(nbOfCells+1,1); newc->alloc(0,1); newci->setIJ(0,0,0);
9024 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> appendedCoords(DataArrayDouble::New()); appendedCoords->alloc(0,1);//1 not 2 it is not a bug.
9025 const double *coords(_coords->begin());
9026 int *newciptr(newci->getPointer());
9027 for(int i=0;i<nbOfCells;i++,newciptr++,ciptr++)
9029 if(Colinearize2DCell(coords,cptr+ciptr[0],cptr+ciptr[1],nbOfNodes,newc,appendedCoords))
9030 ret->pushBackSilent(i);
9031 newciptr[1]=newc->getNumberOfTuples();
9036 if(!appendedCoords->empty())
9038 appendedCoords->rearrange(2);
9039 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords(DataArrayDouble::Aggregate(getCoords(),appendedCoords));//treat info on components
9041 setCoords(newCoords);
9044 setConnectivity(newc,newci,true);
9049 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
9050 * It builds the descending connectivity of the two meshes, and then using a binary tree
9051 * it computes the edge intersections. This results in new points being created : they're stored in addCoo.
9052 * Documentation about parameters colinear2 and subDiv2 can be found in method QuadraticPolygon::splitAbs().
9054 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
9055 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
9056 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
9057 std::vector<double>& addCoo,
9058 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2)
9060 static const int SPACEDIM=2;
9061 // Build desc connectivity
9062 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
9063 desc2=DataArrayInt::New();
9064 descIndx2=DataArrayInt::New();
9065 revDesc2=DataArrayInt::New();
9066 revDescIndx2=DataArrayInt::New();
9067 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
9068 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
9069 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
9070 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
9071 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
9072 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
9073 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
9075 // Build BB tree of all edges in the tool mesh (second mesh)
9076 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
9077 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
9078 int nDescCell1=m1Desc->getNumberOfCells();
9079 int nDescCell2=m2Desc->getNumberOfCells();
9080 intersectEdge1.resize(nDescCell1);
9081 colinear2.resize(nDescCell2);
9082 subDiv2.resize(nDescCell2);
9083 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
9085 std::vector<int> candidates1(1);
9086 int offset1=m1->getNumberOfNodes();
9087 int offset2=offset1+m2->getNumberOfNodes();
9088 for(int i=0;i<nDescCell1;i++) // for all edges in the first mesh
9090 std::vector<int> candidates2; // edges of mesh2 candidate for intersection
9091 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
9092 if(!candidates2.empty()) // candidates2 holds edges from the second mesh potentially intersecting current edge i in mesh1
9094 std::map<INTERP_KERNEL::Node *,int> map1,map2;
9095 // pol2 is not necessarily a closed polygon: just a set of (quadratic) edges (same as candidates2) in the Geometric DS format
9096 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
9098 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
9099 // 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
9100 // This trick guarantees that Node * are discriminant (i.e. form a unique identifier)
9101 std::set<INTERP_KERNEL::Node *> nodes;
9102 pol1->getAllNodes(nodes); pol2->getAllNodes(nodes);
9103 std::size_t szz(nodes.size());
9104 std::vector< MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Node> > nodesSafe(szz);
9105 std::set<INTERP_KERNEL::Node *>::const_iterator itt(nodes.begin());
9106 for(std::size_t iii=0;iii<szz;iii++,itt++)
9107 { (*itt)->incrRef(); nodesSafe[iii]=*itt; }
9108 // end of protection
9109 // Performs egde cutting:
9110 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
9115 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
9117 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
9118 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
9122 * This method performs the 2nd step of Partition of 2D mesh.
9123 * This method has 4 inputs :
9124 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
9125 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
9126 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids randomly sorted.
9127 * 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'
9128 * Nodes end up lying consecutively on a cutted edge.
9129 * \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.
9130 * (Only present for its coords in case of 'subDiv' shares some nodes of 'm1')
9131 * \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.
9132 * \param addCoo input parameter with additional nodes linked to intersection of the 2 meshes.
9133 * \param[out] intersectEdge the same content as subDiv, but correclty oriented.
9135 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2,
9136 const std::vector<double>& addCoo,
9137 const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge)
9139 int offset1=m1->getNumberOfNodes();
9140 int ncell=m2->getNumberOfCells();
9141 const int *c=m2->getNodalConnectivity()->getConstPointer();
9142 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
9143 const double *coo=m2->getCoords()->getConstPointer();
9144 const double *cooBis=m1->getCoords()->getConstPointer();
9145 int offset2=offset1+m2->getNumberOfNodes();
9146 intersectEdge.resize(ncell);
9147 for(int i=0;i<ncell;i++,cI++)
9149 const std::vector<int>& divs=subDiv[i];
9150 int nnode=cI[1]-cI[0]-1;
9151 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
9152 std::map<INTERP_KERNEL::Node *, int> mapp22;
9153 for(int j=0;j<nnode;j++)
9155 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
9156 int nnid=c[(*cI)+j+1];
9157 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
9158 mapp22[nn]=nnid+offset1;
9160 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
9161 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
9162 ((*it).second.first)->decrRef();
9163 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
9164 std::map<INTERP_KERNEL::Node *,int> mapp3;
9165 for(std::size_t j=0;j<divs.size();j++)
9168 INTERP_KERNEL::Node *tmp=0;
9170 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
9172 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
9174 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
9178 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
9179 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
9186 * 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).
9187 * 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
9188 * with a plane. The result will be put in 'cut3DSuf' out parameter.
9189 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
9190 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
9191 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
9192 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
9193 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
9194 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
9195 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
9196 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
9197 * \param [out] cut3DSuf input/output param.
9199 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
9200 const int *nodal3DCurve, const int *nodalIndx3DCurve,
9201 const int *desc, const int *descIndx,
9202 std::vector< std::pair<int,int> >& cut3DSurf)
9204 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
9205 int nbOf3DSurfCell=(int)cut3DSurf.size();
9206 for(int i=0;i<nbOf3DSurfCell;i++)
9208 std::vector<int> res;
9209 int offset=descIndx[i];
9210 int nbOfSeg=descIndx[i+1]-offset;
9211 for(int j=0;j<nbOfSeg;j++)
9213 int edgeId=desc[offset+j];
9214 int status=cut3DCurve[edgeId];
9218 res.push_back(status);
9221 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
9222 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
9230 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9236 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
9237 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
9240 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
9244 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
9249 {// case when plane is on a multi colinear edge of a polyhedron
9250 if((int)res.size()==2*nbOfSeg)
9252 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
9255 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
9262 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
9263 * 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).
9264 * 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
9265 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
9266 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
9267 * \param desc is the descending connectivity 3D->3DSurf
9268 * \param descIndx is the descending connectivity index 3D->3DSurf
9270 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
9271 const int *desc, const int *descIndx,
9272 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const
9274 checkFullyDefined();
9275 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9276 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
9277 const int *nodal3D=_nodal_connec->getConstPointer();
9278 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
9279 int nbOfCells=getNumberOfCells();
9280 for(int i=0;i<nbOfCells;i++)
9282 std::map<int, std::set<int> > m;
9283 int offset=descIndx[i];
9284 int nbOfFaces=descIndx[i+1]-offset;
9287 for(int j=0;j<nbOfFaces;j++)
9289 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
9290 if(p.first!=-1 && p.second!=-1)
9294 start=p.first; end=p.second;
9295 m[p.first].insert(p.second);
9296 m[p.second].insert(p.first);
9300 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
9301 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
9302 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
9303 INTERP_KERNEL::NormalizedCellType cmsId;
9304 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
9305 start=tmp[0]; end=tmp[nbOfNodesSon-1];
9306 for(unsigned k=0;k<nbOfNodesSon;k++)
9308 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
9309 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
9316 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
9320 std::map<int, std::set<int> >::const_iterator it=m.find(start);
9321 const std::set<int>& s=(*it).second;
9322 std::set<int> s2; s2.insert(prev);
9324 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
9327 int val=*s3.begin();
9328 conn.push_back(start);
9335 conn.push_back(end);
9338 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
9339 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
9340 cellIds->pushBackSilent(i);
9346 * 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
9347 * 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
9348 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
9349 * 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
9350 * 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.
9352 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
9354 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut)
9356 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
9359 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
9360 if(cm.getDimension()==2)
9362 const int *node=nodalConnBg+1;
9363 int startNode=*node++;
9364 double refX=coords[2*startNode];
9365 for(;node!=nodalConnEnd;node++)
9367 if(coords[2*(*node)]<refX)
9370 refX=coords[2*startNode];
9373 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
9377 double angle0=-M_PI/2;
9382 double angleNext=0.;
9383 while(nextNode!=startNode)
9387 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
9389 if(*node!=tmpOut.back() && *node!=prevNode)
9391 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
9392 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
9397 res=angle0-angleM+2.*M_PI;
9406 if(nextNode!=startNode)
9408 angle0=angleNext-M_PI;
9411 prevNode=tmpOut.back();
9412 tmpOut.push_back(nextNode);
9415 std::vector<int> tmp3(2*(sz-1));
9416 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
9417 std::copy(nodalConnBg+1,nodalConnEnd,it);
9418 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
9420 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9423 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
9425 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
9430 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
9431 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
9436 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9439 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
9443 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
9444 * 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.
9446 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
9447 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
9448 * \param [in,out] arr array in which the remove operation will be done.
9449 * \param [in,out] arrIndx array in the remove operation will modify
9450 * \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])
9451 * \return true if \b arr and \b arrIndx have been modified, false if not.
9453 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval)
9455 if(!arrIndx || !arr)
9456 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
9457 if(offsetForRemoval<0)
9458 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
9459 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
9460 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
9461 int *arrIPtr=arrIndx->getPointer();
9464 const int *arrPtr=arr->getConstPointer();
9465 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
9466 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
9468 if(*arrIPtr-previousArrI>offsetForRemoval)
9470 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
9472 if(s.find(*work)==s.end())
9473 arrOut.push_back(*work);
9476 previousArrI=*arrIPtr;
9477 *arrIPtr=(int)arrOut.size();
9479 if(arr->getNumberOfTuples()==(int)arrOut.size())
9481 arr->alloc((int)arrOut.size(),1);
9482 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
9487 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9488 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
9489 * The selection of extraction is done standardly in new2old format.
9490 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9492 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9493 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9494 * \param [in] arrIn arr origin array from which the extraction will be done.
9495 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9496 * \param [out] arrOut the resulting array
9497 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9498 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
9500 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9501 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
9503 if(!arrIn || !arrIndxIn)
9504 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
9505 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9506 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9507 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
9508 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
9509 const int *arrInPtr=arrIn->getConstPointer();
9510 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9511 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9513 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9514 int maxSizeOfArr=arrIn->getNumberOfTuples();
9515 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9516 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9517 arrIo->alloc((int)(sz+1),1);
9518 const int *idsIt=idsOfSelectBg;
9519 int *work=arrIo->getPointer();
9522 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
9524 if(*idsIt>=0 && *idsIt<nbOfGrps)
9525 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
9528 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9529 throw INTERP_KERNEL::Exception(oss.str().c_str());
9535 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
9536 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
9537 throw INTERP_KERNEL::Exception(oss.str().c_str());
9540 arro->alloc(lgth,1);
9541 work=arro->getPointer();
9542 idsIt=idsOfSelectBg;
9543 for(std::size_t i=0;i<sz;i++,idsIt++)
9545 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
9546 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
9549 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
9550 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9551 throw INTERP_KERNEL::Exception(oss.str().c_str());
9555 arrIndexOut=arrIo.retn();
9559 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9560 * 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 ).
9561 * The selection of extraction is done standardly in new2old format.
9562 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
9564 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9565 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9566 * \param [in] arrIn arr origin array from which the extraction will be done.
9567 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9568 * \param [out] arrOut the resulting array
9569 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9570 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
9572 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9573 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
9575 if(!arrIn || !arrIndxIn)
9576 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
9577 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
9578 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
9579 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
9580 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
9581 const int *arrInPtr=arrIn->getConstPointer();
9582 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9583 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
9585 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
9586 int maxSizeOfArr=arrIn->getNumberOfTuples();
9587 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9588 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9589 arrIo->alloc((int)(sz+1),1);
9590 int idsIt=idsOfSelectStart;
9591 int *work=arrIo->getPointer();
9594 for(int i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
9596 if(idsIt>=0 && idsIt<nbOfGrps)
9597 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
9600 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
9601 throw INTERP_KERNEL::Exception(oss.str().c_str());
9607 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
9608 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
9609 throw INTERP_KERNEL::Exception(oss.str().c_str());
9612 arro->alloc(lgth,1);
9613 work=arro->getPointer();
9614 idsIt=idsOfSelectStart;
9615 for(int i=0;i<sz;i++,idsIt+=idsOfSelectStep)
9617 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
9618 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
9621 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
9622 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
9623 throw INTERP_KERNEL::Exception(oss.str().c_str());
9627 arrIndexOut=arrIo.retn();
9631 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9632 * 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
9633 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9634 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9636 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9637 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9638 * \param [in] arrIn arr origin array from which the extraction will be done.
9639 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9640 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
9641 * \param [in] srcArrIndex index array of \b srcArr
9642 * \param [out] arrOut the resulting array
9643 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9645 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9647 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9648 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9649 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
9651 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9652 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
9653 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9654 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9655 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9656 std::vector<bool> v(nbOfTuples,true);
9658 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9659 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9660 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9662 if(*it>=0 && *it<nbOfTuples)
9665 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
9669 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9670 throw INTERP_KERNEL::Exception(oss.str().c_str());
9673 srcArrIndexPtr=srcArrIndex->getConstPointer();
9674 arrIo->alloc(nbOfTuples+1,1);
9675 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9676 const int *arrInPtr=arrIn->getConstPointer();
9677 const int *srcArrPtr=srcArr->getConstPointer();
9678 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9679 int *arroPtr=arro->getPointer();
9680 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9684 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9685 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9689 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
9690 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9691 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9695 arrIndexOut=arrIo.retn();
9699 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9700 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9702 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
9703 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
9704 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9705 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9706 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
9707 * \param [in] srcArrIndex index array of \b srcArr
9709 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
9711 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9712 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
9714 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9715 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
9716 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9717 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9718 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9719 int *arrInOutPtr=arrInOut->getPointer();
9720 const int *srcArrPtr=srcArr->getConstPointer();
9721 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
9723 if(*it>=0 && *it<nbOfTuples)
9725 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
9726 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
9729 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] !";
9730 throw INTERP_KERNEL::Exception(oss.str().c_str());
9735 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
9736 throw INTERP_KERNEL::Exception(oss.str().c_str());
9742 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9743 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9744 * 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]].
9745 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9746 * A negative value in \b arrIn means that it is ignored.
9747 * 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.
9749 * \param [in] arrIn arr origin array from which the extraction will be done.
9750 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9751 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9752 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9754 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn)
9756 int seed=0,nbOfDepthPeelingPerformed=0;
9757 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9761 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9762 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9763 * 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]].
9764 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9765 * A negative value in \b arrIn means that it is ignored.
9766 * 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.
9767 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9768 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9769 * \param [in] arrIn arr origin array from which the extraction will be done.
9770 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9771 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9772 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9773 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9774 * \sa MEDCouplingUMesh::partitionBySpreadZone
9776 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9778 nbOfDepthPeelingPerformed=0;
9780 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9781 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9784 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9788 std::vector<bool> fetched(nbOfTuples,false);
9789 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9792 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed)
9794 nbOfDepthPeelingPerformed=0;
9795 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9796 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9797 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9798 std::vector<bool> fetched2(nbOfTuples,false);
9800 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9802 if(*seedElt>=0 && *seedElt<nbOfTuples)
9803 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9805 { 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()); }
9807 const int *arrInPtr=arrIn->getConstPointer();
9808 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9809 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9810 std::vector<int> idsToFetch1(seedBg,seedEnd);
9811 std::vector<int> idsToFetch2;
9812 std::vector<int> *idsToFetch=&idsToFetch1;
9813 std::vector<int> *idsToFetchOther=&idsToFetch2;
9814 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9816 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9817 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9819 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9820 std::swap(idsToFetch,idsToFetchOther);
9821 idsToFetchOther->clear();
9822 nbOfDepthPeelingPerformed++;
9824 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9826 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9827 int *retPtr=ret->getPointer();
9828 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9835 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9836 * 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
9837 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9838 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9840 * \param [in] start begin of set of ids of the input extraction (included)
9841 * \param [in] end end of set of ids of the input extraction (excluded)
9842 * \param [in] step step of the set of ids in range mode.
9843 * \param [in] arrIn arr origin array from which the extraction will be done.
9844 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9845 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9846 * \param [in] srcArrIndex index array of \b srcArr
9847 * \param [out] arrOut the resulting array
9848 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9850 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9852 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9853 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9854 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut)
9856 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9857 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9858 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9859 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9860 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9862 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9863 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9864 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9866 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9868 if(it>=0 && it<nbOfTuples)
9869 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9872 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9873 throw INTERP_KERNEL::Exception(oss.str().c_str());
9876 srcArrIndexPtr=srcArrIndex->getConstPointer();
9877 arrIo->alloc(nbOfTuples+1,1);
9878 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9879 const int *arrInPtr=arrIn->getConstPointer();
9880 const int *srcArrPtr=srcArr->getConstPointer();
9881 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9882 int *arroPtr=arro->getPointer();
9883 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9885 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9888 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9889 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9893 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9894 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9898 arrIndexOut=arrIo.retn();
9902 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9903 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9905 * \param [in] start begin of set of ids of the input extraction (included)
9906 * \param [in] end end of set of ids of the input extraction (excluded)
9907 * \param [in] step step of the set of ids in range mode.
9908 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9909 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9910 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9911 * \param [in] srcArrIndex index array of \b srcArr
9913 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9915 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9916 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex)
9918 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9919 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9920 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9921 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9922 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9923 int *arrInOutPtr=arrInOut->getPointer();
9924 const int *srcArrPtr=srcArr->getConstPointer();
9925 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9927 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9929 if(it>=0 && it<nbOfTuples)
9931 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9932 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9935 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9936 throw INTERP_KERNEL::Exception(oss.str().c_str());
9941 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9942 throw INTERP_KERNEL::Exception(oss.str().c_str());
9948 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9949 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9950 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9951 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9952 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9954 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9956 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const
9958 checkFullyDefined();
9959 int mdim=getMeshDimension();
9960 int spaceDim=getSpaceDimension();
9962 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9963 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9964 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9965 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9966 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9967 ret->setCoords(getCoords());
9968 ret->allocateCells((int)partition.size());
9970 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9972 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9973 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9977 cell=tmp->buildUnionOf2DMesh();
9980 cell=tmp->buildUnionOf3DMesh();
9983 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9986 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9989 ret->finishInsertingCells();
9994 * This method partitions \b this into contiguous zone.
9995 * This method only needs a well defined connectivity. Coordinates are not considered here.
9996 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9998 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const
10000 int nbOfCellsCur=getNumberOfCells();
10001 std::vector<DataArrayInt *> ret;
10002 if(nbOfCellsCur<=0)
10004 DataArrayInt *neigh=0,*neighI=0;
10005 computeNeighborsOfCells(neigh,neighI);
10006 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
10007 std::vector<bool> fetchedCells(nbOfCellsCur,false);
10008 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
10010 while(seed<nbOfCellsCur)
10012 int nbOfPeelPerformed=0;
10013 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
10014 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
10016 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
10017 ret.push_back((*it).retn());
10022 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
10023 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
10025 * \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.
10026 * \return a newly allocated DataArrayInt to be managed by the caller.
10027 * \throw In case of \a code has not the right format (typically of size 3*n)
10029 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code)
10031 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
10032 std::size_t nb=code.size()/3;
10033 if(code.size()%3!=0)
10034 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
10035 ret->alloc((int)nb,2);
10036 int *retPtr=ret->getPointer();
10037 for(std::size_t i=0;i<nb;i++,retPtr+=2)
10039 retPtr[0]=code[3*i+2];
10040 retPtr[1]=code[3*i+2]+code[3*i+1];
10046 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
10047 * All cells in \a this are expected to be linear 3D cells.
10048 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
10049 * It leads to an increase to number of cells.
10050 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
10051 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
10052 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
10054 * \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.
10055 * For all other cells, the splitting policy will be ignored.
10056 * \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.
10057 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
10058 * an id of old cell producing it. The caller is to delete this array using
10059 * decrRef() as it is no more needed.
10060 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
10062 * \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
10063 * the policy PLANAR_FACE_6 should be used on a mesh sorted with MEDCoupling1SGTUMesh::sortHexa8EachOther.
10065 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
10066 * \throw If \a this is not fully constituted with linear 3D cells.
10067 * \sa MEDCouplingUMesh::simplexize, MEDCoupling1SGTUMesh::sortHexa8EachOther
10069 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const
10071 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
10072 checkConnectivityFullyDefined();
10073 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
10074 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
10075 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
10076 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName(),INTERP_KERNEL::NORM_TETRA4));
10077 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
10078 int *retPt(ret->getPointer());
10079 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
10080 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
10081 const int *oldc(_nodal_connec->begin());
10082 const int *oldci(_nodal_connec_index->begin());
10083 const double *coords(_coords->begin());
10084 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
10086 std::vector<int> a; std::vector<double> b;
10087 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
10088 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
10089 const int *aa(&a[0]);
10092 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
10094 *it=(-(*(it))-1+nbNodes);
10095 addPts->insertAtTheEnd(b.begin(),b.end());
10096 nbNodes+=(int)b.size()/3;
10098 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
10099 newConn->insertAtTheEnd(aa,aa+4);
10101 if(!addPts->empty())
10103 addPts->rearrange(3);
10104 nbOfAdditionalPoints=addPts->getNumberOfTuples();
10105 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
10106 ret0->setCoords(addPts);
10110 nbOfAdditionalPoints=0;
10111 ret0->setCoords(getCoords());
10113 ret0->setNodalConnectivity(newConn);
10115 ret->computeOffsets2();
10116 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
10117 return ret0.retn();
10121 * 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).
10123 * \sa MEDCouplingUMesh::split2DCells
10125 void MEDCouplingUMesh::split2DCellsLinear(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI)
10127 checkConnectivityFullyDefined();
10128 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+subNodesInSeg->getNumberOfTuples());
10129 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10130 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10131 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10132 int prevPosOfCi(ciPtr[0]);
10133 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10135 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(0);
10136 *cPtr++=(int)INTERP_KERNEL::NORM_POLYGON; *cPtr++=oldConn[prevPosOfCi+1];
10137 for(int j=0;j<sz;j++)
10139 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]);
10140 for(int k=0;k<sz2;k++)
10141 *cPtr++=subPtr[offset2+k];
10143 *cPtr++=oldConn[prevPosOfCi+j+2];
10146 prevPosOfCi=ciPtr[1];
10147 ciPtr[1]=ciPtr[0]+1+sz+deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10150 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsLinear : Some of edges to be split are orphan !");
10151 _nodal_connec->decrRef();
10152 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_POLYGON);
10155 int InternalAddPoint(const INTERP_KERNEL::Edge *e, int id, const double *coo, int startId, int endId, DataArrayDouble& addCoo, int& nodesCnter)
10161 int ret(nodesCnter++);
10163 e->getMiddleOfPoints(coo+2*startId,coo+2*endId,newPt);
10164 addCoo.insertAtTheEnd(newPt,newPt+2);
10171 void EnterTheResultOf2DCellFirst(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
10174 int trueStart(start>=0?start:nbOfEdges+start);
10175 tmp[0]=linOrArc?(int)INTERP_KERNEL::NORM_QPOLYG:(int)INTERP_KERNEL::NORM_POLYGON; tmp[1]=connBg[trueStart]; tmp[2]=connBg[stp];
10176 newConnOfCell->insertAtTheEnd(tmp,tmp+3);
10181 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10182 InternalAddPoint(e,-1,coords,tmp[1],tmp[2],*appendedCoords,tmp2);
10183 middles.push_back(tmp3+offset);
10186 middles.push_back(connBg[trueStart+nbOfEdges]);
10190 void EnterTheResultOf2DCellMiddle(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
10192 int tmpSrt(newConnOfCell->back()),tmpEnd(connBg[stp]);
10193 newConnOfCell->pushBackSilent(tmpEnd);
10198 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10199 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
10200 middles.push_back(tmp3+offset);
10203 middles.push_back(connBg[start+nbOfEdges]);
10207 void EnterTheResultOf2DCellEnd(const INTERP_KERNEL::Edge *e, int start, int stp, int nbOfEdges, bool linOrArc, const double *coords, const int *connBg, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords, std::vector<int>& middles)
10213 int tmpSrt(connBg[start]),tmpEnd(connBg[stp]);
10214 int tmp2(0),tmp3(appendedCoords->getNumberOfTuples()/2);
10215 InternalAddPoint(e,-1,coords,tmpSrt,tmpEnd,*appendedCoords,tmp2);
10216 middles.push_back(tmp3+offset);
10219 middles.push_back(connBg[start+nbOfEdges]);
10226 * Returns true if a colinearization has been found in the given cell. If false is returned the content pushed in \a newConnOfCell is equal to [ \a connBg , \a connEnd ) .
10227 * \a appendedCoords is a DataArrayDouble instance with number of components equal to one (even if the items are pushed by pair).
10229 bool MEDCouplingUMesh::Colinearize2DCell(const double *coords, const int *connBg, const int *connEnd, int offset, DataArrayInt *newConnOfCell, DataArrayDouble *appendedCoords)
10231 std::size_t sz(std::distance(connBg,connEnd));
10232 if(sz<3)//3 because 2+1(for the cell type) and 2 is the minimal number of edges of 2D cell.
10233 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Colinearize2DCell : the input cell has invalid format !");
10235 INTERP_KERNEL::AutoPtr<int> tmpConn(new int[sz]);
10236 const INTERP_KERNEL::CellModel& cm(INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connBg[0]));
10237 unsigned nbs(cm.getNumberOfSons2(connBg+1,sz)),nbOfHit(0);
10238 int posBaseElt(0),posEndElt(0),nbOfTurn(0);
10239 INTERP_KERNEL::NormalizedCellType typeOfSon;
10240 std::vector<int> middles;
10242 for(;nbOfHit<nbs;nbOfTurn++)
10244 cm.fillSonCellNodalConnectivity2(posBaseElt,connBg+1,sz,tmpConn,typeOfSon);
10245 std::map<INTERP_KERNEL::Node *,int> m;
10246 INTERP_KERNEL::Edge *e(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
10249 unsigned endI(nbs-nbOfHit);
10250 for(unsigned i=0;i<endI;i++)
10252 cm.fillSonCellNodalConnectivity2(posBaseElt+(int)i+1,connBg+1,sz,tmpConn,typeOfSon);
10253 INTERP_KERNEL::Edge *eCand(MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m));
10254 INTERP_KERNEL::EdgeIntersector *eint(INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand));
10255 bool isColinear(eint->areColinears());
10267 {//look if the first edge of cell is not colinear with last edges in this case the start of nodal connectivity is shifted back
10268 unsigned endII(nbs-nbOfHit-1);//warning nbOfHit can be modified, so put end condition in a variable.
10269 for(unsigned ii=0;ii<endII;ii++)
10271 cm.fillSonCellNodalConnectivity2(nbs-ii-1,connBg+1,sz,tmpConn,typeOfSon);
10272 eCand=MEDCouplingUMeshBuildQPFromEdge2(typeOfSon,tmpConn,coords,m);
10273 eint=INTERP_KERNEL::Edge::BuildIntersectorWith(e,eCand);
10274 isColinear=eint->areColinears();
10288 //push [posBaseElt,posEndElt) in newConnOfCell using e
10290 EnterTheResultOf2DCellFirst(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10291 else if(nbOfHit!=nbs)
10292 EnterTheResultOf2DCellMiddle(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10294 EnterTheResultOf2DCellEnd(e,posBaseElt,posEndElt,(int)nbs,cm.isQuadratic(),coords,connBg+1,offset,newConnOfCell,appendedCoords,middles);
10295 posBaseElt=posEndElt;
10296 for(std::map<INTERP_KERNEL::Node *,int>::const_iterator it=m.begin();it!=m.end();it++)
10297 (*it).first->decrRef();
10300 if(!middles.empty())
10301 newConnOfCell->insertAtTheEnd(middles.begin(),middles.end());
10306 * It is the quadratic part of MEDCouplingUMesh::split2DCells. Here some additionnal nodes can be added at the end of coordinates array object.
10308 * \return int - the number of new nodes created.
10309 * \sa MEDCouplingUMesh::split2DCells
10311 int MEDCouplingUMesh::split2DCellsQuadratic(const DataArrayInt *desc, const DataArrayInt *descI, const DataArrayInt *subNodesInSeg, const DataArrayInt *subNodesInSegI, const DataArrayInt *mid, const DataArrayInt *midI)
10314 int ncells(getNumberOfCells()),lgthToReach(getMeshLength()+2*subNodesInSeg->getNumberOfTuples()),nodesCnt(getNumberOfNodes());
10315 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()); c->alloc((std::size_t)lgthToReach);
10316 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoo(DataArrayDouble::New()); addCoo->alloc(0,1);
10317 const int *subPtr(subNodesInSeg->begin()),*subIPtr(subNodesInSegI->begin()),*descPtr(desc->begin()),*descIPtr(descI->begin()),*oldConn(getNodalConnectivity()->begin());
10318 const int *midPtr(mid->begin()),*midIPtr(midI->begin());
10319 const double *oldCoordsPtr(getCoords()->begin());
10320 int *cPtr(c->getPointer()),*ciPtr(getNodalConnectivityIndex()->getPointer());
10321 int prevPosOfCi(ciPtr[0]);
10322 for(int i=0;i<ncells;i++,ciPtr++,descIPtr++)
10324 int offset(descIPtr[0]),sz(descIPtr[1]-descIPtr[0]),deltaSz(sz);
10325 for(int j=0;j<sz;j++)
10326 { int sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]); deltaSz+=sz2; }
10327 *cPtr++=(int)INTERP_KERNEL::NORM_QPOLYG; cPtr[0]=oldConn[prevPosOfCi+1];
10328 for(int j=0;j<sz;j++)//loop over subedges of oldConn
10330 int offset2(subIPtr[descPtr[offset+j]]),sz2(subIPtr[descPtr[offset+j]+1]-subIPtr[descPtr[offset+j]]),offset3(midIPtr[descPtr[offset+j]]);
10334 cPtr[1]=oldConn[prevPosOfCi+2+j];
10335 cPtr[deltaSz]=oldConn[prevPosOfCi+1+j+sz]; cPtr++;
10338 std::vector<INTERP_KERNEL::Node *> ns(3);
10339 ns[0]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+j]+1]);
10340 ns[1]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+(1+j)%sz]+1]);
10341 ns[2]=new INTERP_KERNEL::Node(oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]],oldCoordsPtr[2*oldConn[prevPosOfCi+1+sz+j]+1]);
10342 MEDCouplingAutoRefCountObjectPtr<INTERP_KERNEL::Edge> e(INTERP_KERNEL::QuadraticPolygon::BuildArcCircleEdge(ns));
10343 for(int k=0;k<sz2;k++)//loop over subsplit of current subedge
10345 cPtr[1]=subPtr[offset2+k];
10346 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+k],oldCoordsPtr,cPtr[0],cPtr[1],*addCoo,nodesCnt); cPtr++;
10348 int tmpEnd(oldConn[prevPosOfCi+1+(j+1)%sz]);
10350 { cPtr[1]=tmpEnd; }
10351 cPtr[deltaSz]=InternalAddPoint(e,midPtr[offset3+sz2],oldCoordsPtr,cPtr[0],tmpEnd,*addCoo,nodesCnt); cPtr++;
10353 prevPosOfCi=ciPtr[1]; cPtr+=deltaSz;
10354 ciPtr[1]=ciPtr[0]+1+2*deltaSz;//sz==old nb of nodes because (nb of subedges=nb of nodes for polygons)
10357 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split2DCellsQuadratic : Some of edges to be split are orphan !");
10358 _nodal_connec->decrRef();
10359 _nodal_connec=c.retn(); _types.clear(); _types.insert(INTERP_KERNEL::NORM_QPOLYG);
10360 addCoo->rearrange(2);
10361 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo(DataArrayDouble::Aggregate(getCoords(),addCoo));//info are copied from getCoords() by using Aggregate
10363 return addCoo->getNumberOfTuples();
10366 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
10367 _own_cell(true),_cell_id(-1),_nb_cell(0)
10372 _nb_cell=mesh->getNumberOfCells();
10376 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
10384 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
10385 _own_cell(false),_cell_id(bg-1),
10392 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
10395 if(_cell_id<_nb_cell)
10404 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
10410 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
10412 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
10415 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
10421 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
10429 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
10435 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
10440 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
10445 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
10447 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
10450 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
10455 _nb_cell=mesh->getNumberOfCells();
10459 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
10466 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
10468 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
10469 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
10470 if(_cell_id<_nb_cell)
10472 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
10473 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
10474 int startId=_cell_id;
10475 _cell_id+=nbOfElems;
10476 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
10482 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
10486 _conn=mesh->getNodalConnectivity()->getPointer();
10487 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
10491 void MEDCouplingUMeshCell::next()
10493 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10498 _conn_lgth=_conn_indx[1]-_conn_indx[0];
10501 std::string MEDCouplingUMeshCell::repr() const
10503 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10505 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
10507 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
10511 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
10514 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
10516 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
10517 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
10519 return INTERP_KERNEL::NORM_ERROR;
10522 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
10525 if(_conn_lgth!=NOTICABLE_FIRST_VAL)