1 // Copyright (C) 2007-2013 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.
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 "InterpKernelMeshQuality.hxx"
34 #include "InterpKernelCellSimplify.hxx"
35 #include "InterpKernelGeo2DEdgeArcCircle.hxx"
36 #include "MEDCouplingAutoRefCountObjectPtr.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 char *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);
92 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other) throw(INTERP_KERNEL::Exception)
95 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
96 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
98 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
99 MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
100 setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
103 std::size_t MEDCouplingUMesh::getHeapMemorySize() const
107 ret+=_nodal_connec->getHeapMemorySize();
108 if(_nodal_connec_index)
109 ret+=_nodal_connec_index->getHeapMemorySize();
110 return MEDCouplingPointSet::getHeapMemorySize()+ret;
113 void MEDCouplingUMesh::updateTime() const
115 MEDCouplingPointSet::updateTime();
118 updateTimeWith(*_nodal_connec);
120 if(_nodal_connec_index)
122 updateTimeWith(*_nodal_connec_index);
126 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
131 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
132 * then \a this mesh is most probably is writable, exchangeable and available for most
133 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
134 * this method to check that all is in order with \a this mesh.
135 * \throw If the mesh dimension is not set.
136 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
137 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
138 * \throw If the connectivity data array has more than one component.
139 * \throw If the connectivity data array has a named component.
140 * \throw If the connectivity index data array has more than one component.
141 * \throw If the connectivity index data array has a named component.
143 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
146 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
148 MEDCouplingPointSet::checkCoherency();
149 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
151 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
153 std::ostringstream message;
154 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
155 throw INTERP_KERNEL::Exception(message.str().c_str());
160 if(_nodal_connec->getNumberOfComponents()!=1)
161 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
162 if(_nodal_connec->getInfoOnComponent(0)!="")
163 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
167 throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
168 if(_nodal_connec_index)
170 if(_nodal_connec_index->getNumberOfComponents()!=1)
171 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
172 if(_nodal_connec_index->getInfoOnComponent(0)!="")
173 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
177 throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
181 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
182 * then \a this mesh is most probably is writable, exchangeable and available for all
183 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
184 * method thoroughly checks the nodal connectivity.
185 * \param [in] eps - a not used parameter.
186 * \throw If the mesh dimension is not set.
187 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
188 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
189 * \throw If the connectivity data array has more than one component.
190 * \throw If the connectivity data array has a named component.
191 * \throw If the connectivity index data array has more than one component.
192 * \throw If the connectivity index data array has a named component.
193 * \throw If number of nodes defining an element does not correspond to the type of element.
194 * \throw If the nodal connectivity includes an invalid node id.
196 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
201 int meshDim=getMeshDimension();
202 int nbOfNodes=getNumberOfNodes();
203 int nbOfCells=getNumberOfCells();
204 const int *ptr=_nodal_connec->getConstPointer();
205 const int *ptrI=_nodal_connec_index->getConstPointer();
206 for(int i=0;i<nbOfCells;i++)
208 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
209 if((int)cm.getDimension()!=meshDim)
211 std::ostringstream oss;
212 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
213 throw INTERP_KERNEL::Exception(oss.str().c_str());
215 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
217 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
219 std::ostringstream oss;
220 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
221 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
222 throw INTERP_KERNEL::Exception(oss.str().c_str());
224 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
229 if(nodeId>=nbOfNodes)
231 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
232 throw INTERP_KERNEL::Exception(oss.str().c_str());
237 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
238 throw INTERP_KERNEL::Exception(oss.str().c_str());
242 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
244 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
245 throw INTERP_KERNEL::Exception(oss.str().c_str());
254 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
255 * then \a this mesh is most probably is writable, exchangeable and available for all
256 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
257 * \param [in] eps - a not used parameter.
258 * \throw If the mesh dimension is not set.
259 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
260 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
261 * \throw If the connectivity data array has more than one component.
262 * \throw If the connectivity data array has a named component.
263 * \throw If the connectivity index data array has more than one component.
264 * \throw If the connectivity index data array has a named component.
265 * \throw If number of nodes defining an element does not correspond to the type of element.
266 * \throw If the nodal connectivity includes an invalid node id.
268 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
270 checkCoherency1(eps);
274 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
275 * elements contained in the mesh. For more info on the mesh dimension see
276 * \ref MEDCouplingUMeshPage.
277 * \param [in] meshDim - a new mesh dimension.
278 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
280 void MEDCouplingUMesh::setMeshDimension(int meshDim)
282 if(meshDim<-1 || meshDim>3)
283 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
289 * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
290 * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
291 * If a nodal connectivity previouly existed before the call of this method, it will be reset.
293 * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
295 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
296 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
298 void MEDCouplingUMesh::allocateCells(int nbOfCells)
301 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
302 if(_nodal_connec_index)
304 _nodal_connec_index->decrRef();
308 _nodal_connec->decrRef();
310 _nodal_connec_index=DataArrayInt::New();
311 _nodal_connec_index->reserve(nbOfCells+1);
312 _nodal_connec_index->pushBackSilent(0);
313 _nodal_connec=DataArrayInt::New();
314 _nodal_connec->reserve(2*nbOfCells);
320 * Appends a cell to the connectivity array. For deeper understanding what is
321 * happening see \ref MEDCouplingUMeshNodalConnectivity.
322 * \param [in] type - type of cell to add.
323 * \param [in] size - number of nodes constituting this cell.
324 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
326 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
327 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
329 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
331 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
332 if(_nodal_connec_index==0)
333 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
334 if((int)cm.getDimension()==_mesh_dim)
337 if(size!=(int)cm.getNumberOfNodes())
339 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
340 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
341 throw INTERP_KERNEL::Exception(oss.str().c_str());
343 int idx=_nodal_connec_index->back();
345 _nodal_connec_index->pushBackSilent(val);
346 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
351 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
352 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
353 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
354 throw INTERP_KERNEL::Exception(oss.str().c_str());
359 * Compacts data arrays to release unused memory. This method is to be called after
360 * finishing cell insertion using \a this->insertNextCell().
362 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
363 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
365 void MEDCouplingUMesh::finishInsertingCells()
367 _nodal_connec->pack();
368 _nodal_connec_index->pack();
369 _nodal_connec->declareAsNew();
370 _nodal_connec_index->declareAsNew();
375 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
376 * Useful for python users.
378 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
380 return new MEDCouplingUMeshCellIterator(this);
384 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
385 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
386 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
387 * Useful for python users.
389 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
391 if(!checkConsecutiveCellTypes())
392 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
393 return new MEDCouplingUMeshCellByTypeEntry(this);
397 * Returns a set of all cell types available in \a this mesh.
398 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
399 * \warning this method does not throw any exception even if \a this is not defined.
401 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
407 * This method is a method that compares \a this and \a other.
408 * This method compares \b all attributes, even names and component names.
410 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
413 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
414 std::ostringstream oss; oss.precision(15);
415 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
418 reason="mesh given in input is not castable in MEDCouplingUMesh !";
421 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
423 if(_mesh_dim!=otherC->_mesh_dim)
425 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
429 if(_types!=otherC->_types)
431 oss << "umesh geometric type mismatch :\nThis geometric types are :";
432 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
433 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
434 oss << "\nOther geometric types are :";
435 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
436 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
440 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
441 if(_nodal_connec==0 || otherC->_nodal_connec==0)
443 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
446 if(_nodal_connec!=otherC->_nodal_connec)
447 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
449 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
452 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
453 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
455 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
458 if(_nodal_connec_index!=otherC->_nodal_connec_index)
459 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
461 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
468 * Checks if data arrays of this mesh (node coordinates, nodal
469 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
471 * \param [in] other - the mesh to compare with.
472 * \param [in] prec - precision value used to compare node coordinates.
473 * \return bool - \a true if the two meshes are same.
475 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
477 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
480 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
482 if(_mesh_dim!=otherC->_mesh_dim)
484 if(_types!=otherC->_types)
486 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
487 if(_nodal_connec==0 || otherC->_nodal_connec==0)
489 if(_nodal_connec!=otherC->_nodal_connec)
490 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
492 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
493 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
495 if(_nodal_connec_index!=otherC->_nodal_connec_index)
496 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
502 * Checks if \a this and \a other meshes are geometrically equivalent with high
503 * probability, else an exception is thrown. The meshes are considered equivalent if
504 * (1) meshes contain the same number of nodes and the same number of elements of the
505 * same types (2) three cells of the two meshes (first, last and middle) are based
506 * on coincident nodes (with a specified precision).
507 * \param [in] other - the mesh to compare with.
508 * \param [in] prec - the precision used to compare nodes of the two meshes.
509 * \throw If the two meshes do not match.
511 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
513 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
514 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
516 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
520 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
521 * cells each node belongs to.
522 * \warning For speed reasons, this method does not check if node ids in the nodal
523 * connectivity correspond to the size of node coordinates array.
524 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
525 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
526 * dividing cell ids in \a revNodal into groups each referring to one
527 * node. Its every element (except the last one) is an index pointing to the
528 * first id of a group of cells. For example cells sharing the node #1 are
529 * described by following range of indices:
530 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
531 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
532 * Number of cells sharing the *i*-th node is
533 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
534 * \throw If the coordinates array is not set.
535 * \throw If the nodal connectivity of cells is not defined.
537 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
538 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
540 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
543 int nbOfNodes=getNumberOfNodes();
544 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
545 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
546 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
547 const int *conn=_nodal_connec->getConstPointer();
548 const int *connIndex=_nodal_connec_index->getConstPointer();
549 int nbOfCells=getNumberOfCells();
550 int nbOfEltsInRevNodal=0;
551 for(int eltId=0;eltId<nbOfCells;eltId++)
553 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
554 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
555 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
556 if(*iter>=0)//for polyhedrons
558 nbOfEltsInRevNodal++;
559 revNodalIndxPtr[(*iter)+1]++;
562 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
563 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
564 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
565 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
566 for(int eltId=0;eltId<nbOfCells;eltId++)
568 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
569 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
570 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
571 if(*iter>=0)//for polyhedrons
572 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
578 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
583 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
589 if(cm.getOrientationStatus(nb,conn1,conn2))
596 class MinusOneSonsGenerator
599 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
600 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
601 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
602 static const int DELTA=1;
604 const INTERP_KERNEL::CellModel& _cm;
607 class MinusOneSonsGeneratorBiQuadratic
610 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
611 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
612 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
613 static const int DELTA=1;
615 const INTERP_KERNEL::CellModel& _cm;
618 class MinusTwoSonsGenerator
621 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
622 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
623 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
624 static const int DELTA=2;
626 const INTERP_KERNEL::CellModel& _cm;
632 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
633 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
634 * describing correspondence between cells of \a this and the result meshes are
635 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
636 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
637 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
638 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
639 * \warning For speed reasons, this method does not check if node ids in the nodal
640 * connectivity correspond to the size of node coordinates array.
641 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
642 * to write this mesh to the MED file, its cells must be sorted using
643 * sortCellsInMEDFileFrmt().
644 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
645 * each cell of \a this mesh.
646 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
647 * dividing cell ids in \a desc into groups each referring to one
648 * cell of \a this mesh. Its every element (except the last one) is an index
649 * pointing to the first id of a group of cells. For example cells of the
650 * result mesh bounding the cell #1 of \a this mesh are described by following
652 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
653 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
654 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
655 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
656 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
657 * by each cell of the result mesh.
658 * \param [in,out] revDescIndx - the array, of length one more than number of cells
659 * in the result mesh,
660 * dividing cell ids in \a revDesc into groups each referring to one
661 * cell of the result mesh the same way as \a descIndx divides \a desc.
662 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
663 * delete this mesh using decrRef() as it is no more needed.
664 * \throw If the coordinates array is not set.
665 * \throw If the nodal connectivity of cells is node defined.
666 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
667 * revDescIndx == NULL.
669 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
670 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
671 * \sa buildDescendingConnectivity2()
673 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
675 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
679 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
680 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
681 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
682 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
683 * \sa MEDCouplingUMesh::buildDescendingConnectivity
685 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
688 if(getMeshDimension()!=3)
689 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
690 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
694 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
695 * this->getMeshDimension(), that bound cells of \a this mesh. In
696 * addition arrays describing correspondence between cells of \a this and the result
697 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
698 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
699 * mesh. This method differs from buildDescendingConnectivity() in that apart
700 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
701 * result meshes. So a positive id means that order of nodes in corresponding cells
702 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
703 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
704 * i.e. cell ids are one-based.
705 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
706 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
707 * \warning For speed reasons, this method does not check if node ids in the nodal
708 * connectivity correspond to the size of node coordinates array.
709 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
710 * to write this mesh to the MED file, its cells must be sorted using
711 * sortCellsInMEDFileFrmt().
712 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
713 * each cell of \a this mesh.
714 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
715 * dividing cell ids in \a desc into groups each referring to one
716 * cell of \a this mesh. Its every element (except the last one) is an index
717 * pointing to the first id of a group of cells. For example cells of the
718 * result mesh bounding the cell #1 of \a this mesh are described by following
720 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
721 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
722 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
723 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
724 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
725 * by each cell of the result mesh.
726 * \param [in,out] revDescIndx - the array, of length one more than number of cells
727 * in the result mesh,
728 * dividing cell ids in \a revDesc into groups each referring to one
729 * cell of the result mesh the same way as \a descIndx divides \a desc.
730 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
731 * shares the node coordinates array with \a this mesh. The caller is to
732 * delete this mesh using decrRef() as it is no more needed.
733 * \throw If the coordinates array is not set.
734 * \throw If the nodal connectivity of cells is node defined.
735 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
736 * revDescIndx == NULL.
738 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
739 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
740 * \sa buildDescendingConnectivity()
742 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
744 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
748 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
749 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
750 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
751 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
753 * \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
754 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
755 * \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.
757 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
759 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
760 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
761 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
762 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
763 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
765 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
769 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
770 * 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,
771 * excluding a set of meshdim-1 cells in input descending connectivity.
772 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
773 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
774 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
776 * \param [in] desc descending connectivity array.
777 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
778 * \param [in] revDesc reverse descending connectivity array.
779 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
780 * \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
781 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
782 * \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.
784 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
785 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
787 if(!desc || !descIndx || !revDesc || !revDescIndx)
788 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
789 const int *descPtr=desc->getConstPointer();
790 const int *descIPtr=descIndx->getConstPointer();
791 const int *revDescPtr=revDesc->getConstPointer();
792 const int *revDescIPtr=revDescIndx->getConstPointer();
794 int nbCells=descIndx->getNumberOfTuples()-1;
795 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
796 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
797 int *out1Ptr=out1->getPointer();
799 out0->reserve(desc->getNumberOfTuples());
800 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
802 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
804 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
806 out0->insertAtTheEnd(s.begin(),s.end());
808 *out1Ptr=out0->getNumberOfTuples();
810 neighbors=out0.retn();
811 neighborsIndx=out1.retn();
817 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
818 * For speed reasons no check of this will be done.
820 template<class SonsGenerator>
821 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
823 if(!desc || !descIndx || !revDesc || !revDescIndx)
824 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
825 checkConnectivityFullyDefined();
826 int nbOfCells=getNumberOfCells();
827 int nbOfNodes=getNumberOfNodes();
828 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
829 int *revNodalIndxPtr=revNodalIndx->getPointer();
830 const int *conn=_nodal_connec->getConstPointer();
831 const int *connIndex=_nodal_connec_index->getConstPointer();
832 std::string name="Mesh constituent of "; name+=getName();
833 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
834 ret->setCoords(getCoords());
835 ret->allocateCells(2*nbOfCells);
836 descIndx->alloc(nbOfCells+1,1);
837 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
838 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
839 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
841 int pos=connIndex[eltId];
842 int posP1=connIndex[eltId+1];
843 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
844 SonsGenerator sg(cm);
845 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
846 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
847 for(unsigned i=0;i<nbOfSons;i++)
849 INTERP_KERNEL::NormalizedCellType cmsId;
850 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
851 for(unsigned k=0;k<nbOfNodesSon;k++)
853 revNodalIndxPtr[tmp[k]+1]++;
854 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
855 revDesc2->pushBackSilent(eltId);
857 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
859 int nbOfCellsM1=ret->getNumberOfCells();
860 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
861 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
862 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
863 int *revNodalPtr=revNodal->getPointer();
864 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
865 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
866 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
868 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
869 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
870 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
871 if(*iter>=0)//for polyhedrons
872 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
875 DataArrayInt *commonCells=0,*commonCellsI=0;
876 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
877 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
878 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
879 int newNbOfCellsM1=-1;
880 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
881 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
882 std::vector<bool> isImpacted(nbOfCellsM1,false);
883 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
884 for(int work2=work[0];work2!=work[1];work2++)
885 isImpacted[commonCellsPtr[work2]]=true;
886 const int *o2nM1Ptr=o2nM1->getConstPointer();
887 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
888 const int *n2oM1Ptr=n2oM1->getConstPointer();
889 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
890 ret2->copyTinyInfoFrom(this);
891 desc->alloc(descIndx->back(),1);
892 int *descPtr=desc->getPointer();
893 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
894 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
897 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
900 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
902 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
903 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
906 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
909 revDesc->reserve(newNbOfCellsM1);
910 revDescIndx->alloc(newNbOfCellsM1+1,1);
911 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
912 const int *revDesc2Ptr=revDesc2->getConstPointer();
913 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
915 int oldCellIdM1=n2oM1Ptr[i];
916 if(!isImpacted[oldCellIdM1])
918 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
919 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
923 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
924 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
925 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
933 struct MEDCouplingAccVisit
935 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
936 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
937 int _new_nb_of_nodes;
943 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
944 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
945 * array of cell ids. Pay attention that after conversion all algorithms work slower
946 * with \a this mesh than before conversion. <br> If an exception is thrown during the
947 * conversion due presence of invalid ids in the array of cells to convert, as a
948 * result \a this mesh contains some already converted elements. In this case the 2D
949 * mesh remains valid but 3D mesh becomes \b inconsistent!
950 * \warning This method can significantly modify the order of geometric types in \a this,
951 * hence, to write this mesh to the MED file, its cells must be sorted using
952 * sortCellsInMEDFileFrmt().
953 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
954 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
955 * cellIdsToConvertBg.
956 * \throw If the coordinates array is not set.
957 * \throw If the nodal connectivity of cells is node defined.
958 * \throw If dimension of \a this mesh is not either 2 or 3.
960 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
961 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
963 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
966 int dim=getMeshDimension();
968 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
969 int nbOfCells=getNumberOfCells();
972 const int *connIndex=_nodal_connec_index->getConstPointer();
973 int *conn=_nodal_connec->getPointer();
974 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
976 if(*iter>=0 && *iter<nbOfCells)
978 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
979 if(!cm.isQuadratic())
980 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
982 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
986 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
987 oss << " in range [0," << nbOfCells << ") !";
988 throw INTERP_KERNEL::Exception(oss.str().c_str());
994 int *connIndex=_nodal_connec_index->getPointer();
995 int connIndexLgth=_nodal_connec_index->getNbOfElems();
996 const int *connOld=_nodal_connec->getConstPointer();
997 int connOldLgth=_nodal_connec->getNbOfElems();
998 std::vector<int> connNew(connOld,connOld+connOldLgth);
999 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1001 if(*iter>=0 && *iter<nbOfCells)
1003 int pos=connIndex[*iter];
1004 int posP1=connIndex[(*iter)+1];
1005 int lgthOld=posP1-pos-1;
1006 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1007 connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1008 unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1009 int *tmp=new int[nbOfFaces*lgthOld];
1011 for(int j=0;j<(int)nbOfFaces;j++)
1013 INTERP_KERNEL::NormalizedCellType type;
1014 unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1018 std::size_t newLgth=std::distance(tmp,work)-1;
1019 std::size_t delta=newLgth-lgthOld;
1020 std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1021 connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1022 std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1027 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1028 oss << " in range [0," << nbOfCells << ") !";
1029 throw INTERP_KERNEL::Exception(oss.str().c_str());
1032 _nodal_connec->alloc((int)connNew.size(),1);
1033 int *newConnPtr=_nodal_connec->getPointer();
1034 std::copy(connNew.begin(),connNew.end(),newConnPtr);
1040 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1041 * polyhedrons (if \a this is a 3D mesh).
1042 * \warning As this method is purely for user-friendliness and no optimization is
1043 * done to avoid construction of a useless vector, this method can be costly
1045 * \throw If the coordinates array is not set.
1046 * \throw If the nodal connectivity of cells is node defined.
1047 * \throw If dimension of \a this mesh is not either 2 or 3.
1049 void MEDCouplingUMesh::convertAllToPoly()
1051 int nbOfCells=getNumberOfCells();
1052 std::vector<int> cellIds(nbOfCells);
1053 for(int i=0;i<nbOfCells;i++)
1055 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1059 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1060 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1061 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1062 * base facet of the volume and the second half of nodes describes an opposite facet
1063 * having the same number of nodes as the base one. This method converts such
1064 * connectivity to a valid polyhedral format where connectivity of each facet is
1065 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1066 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1067 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1068 * a correct orientation of the first facet of a polyhedron, else orientation of a
1069 * corrected cell is reverse.<br>
1070 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1071 * it releases the user from boring description of polyhedra connectivity in the valid
1073 * \throw If \a this->getMeshDimension() != 3.
1074 * \throw If \a this->getSpaceDimension() != 3.
1075 * \throw If the nodal connectivity of cells is not defined.
1076 * \throw If the coordinates array is not set.
1077 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1078 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1080 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1081 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1083 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
1085 checkFullyDefined();
1086 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1087 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1088 int nbOfCells=getNumberOfCells();
1089 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1090 newCi->alloc(nbOfCells+1,1);
1091 int *newci=newCi->getPointer();
1092 const int *ci=_nodal_connec_index->getConstPointer();
1093 const int *c=_nodal_connec->getConstPointer();
1095 for(int i=0;i<nbOfCells;i++)
1097 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1098 if(type==INTERP_KERNEL::NORM_POLYHED)
1100 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1102 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1103 throw INTERP_KERNEL::Exception(oss.str().c_str());
1105 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1108 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 !";
1109 throw INTERP_KERNEL::Exception(oss.str().c_str());
1112 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)
1115 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1117 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1118 newC->alloc(newci[nbOfCells],1);
1119 int *newc=newC->getPointer();
1120 for(int i=0;i<nbOfCells;i++)
1122 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1123 if(type==INTERP_KERNEL::NORM_POLYHED)
1125 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1126 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1128 for(std::size_t j=0;j<n1;j++)
1130 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1132 newc[n1+5*j+1]=c[ci[i]+1+j];
1133 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1134 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1135 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1140 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1142 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1143 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1148 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1149 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1150 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1151 * to write this mesh to the MED file, its cells must be sorted using
1152 * sortCellsInMEDFileFrmt().
1153 * \return \c true if at least one cell has been converted, \c false else. In the
1154 * last case the nodal connectivity remains unchanged.
1155 * \throw If the coordinates array is not set.
1156 * \throw If the nodal connectivity of cells is not defined.
1157 * \throw If \a this->getMeshDimension() < 0.
1159 bool MEDCouplingUMesh::unPolyze()
1161 checkFullyDefined();
1162 int mdim=getMeshDimension();
1164 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1167 int nbOfCells=getNumberOfCells();
1170 int initMeshLgth=getMeshLength();
1171 int *conn=_nodal_connec->getPointer();
1172 int *index=_nodal_connec_index->getPointer();
1177 for(int i=0;i<nbOfCells;i++)
1179 lgthOfCurCell=index[i+1]-posOfCurCell;
1180 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1181 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1182 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1186 switch(cm.getDimension())
1190 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1191 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1192 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1197 int nbOfFaces,lgthOfPolyhConn;
1198 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1199 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1204 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1208 ret=ret || (newType!=type);
1209 conn[newPos]=newType;
1211 posOfCurCell=index[i+1];
1216 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1217 newPos+=lgthOfCurCell;
1218 posOfCurCell+=lgthOfCurCell;
1222 if(newPos!=initMeshLgth)
1223 _nodal_connec->reAlloc(newPos);
1230 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1231 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1232 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1234 * \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
1237 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1239 checkFullyDefined();
1240 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1241 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1242 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1243 coords->recenterForMaxPrecision(eps);
1245 int nbOfCells=getNumberOfCells();
1246 const int *conn=_nodal_connec->getConstPointer();
1247 const int *index=_nodal_connec_index->getConstPointer();
1248 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1249 connINew->alloc(nbOfCells+1,1);
1250 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1251 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1253 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1255 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1257 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1261 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1262 *connINewPtr=connNew->getNumberOfTuples();
1265 setConnectivity(connNew,connINew,false);
1269 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1270 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1271 * the format of returned DataArrayInt instance.
1273 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1274 * \sa MEDCouplingUMesh::getNodeIdsInUse
1276 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1278 checkConnectivityFullyDefined();
1279 int nbOfCells=getNumberOfCells();
1280 const int *connIndex=_nodal_connec_index->getConstPointer();
1281 const int *conn=_nodal_connec->getConstPointer();
1282 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1283 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1284 std::vector<bool> retS(maxElt,false);
1285 for(int i=0;i<nbOfCells;i++)
1286 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1290 for(int i=0;i<maxElt;i++)
1293 DataArrayInt *ret=DataArrayInt::New();
1295 int *retPtr=ret->getPointer();
1296 for(int i=0;i<maxElt;i++)
1303 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1304 * \sa MEDCouplingUMesh::getNodeIdsInUse
1306 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1308 int nbOfNodes=(int)nodeIdsInUse.size();
1309 int nbOfCells=getNumberOfCells();
1310 const int *connIndex=_nodal_connec_index->getConstPointer();
1311 const int *conn=_nodal_connec->getConstPointer();
1312 for(int i=0;i<nbOfCells;i++)
1313 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1316 if(conn[j]<nbOfNodes)
1317 nodeIdsInUse[conn[j]]=true;
1320 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1321 throw INTERP_KERNEL::Exception(oss.str().c_str());
1327 * Finds nodes not used in any cell and returns an array giving a new id to every node
1328 * by excluding the unused nodes, for which the array holds -1. The result array is
1329 * a mapping in "Old to New" mode.
1330 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1331 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1332 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1333 * if the node is unused or a new id else. The caller is to delete this
1334 * array using decrRef() as it is no more needed.
1335 * \throw If the coordinates array is not set.
1336 * \throw If the nodal connectivity of cells is not defined.
1337 * \throw If the nodal connectivity includes an invalid id.
1339 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1340 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1341 * \sa computeNodeIdsAlg()
1343 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1346 int nbOfNodes=getNumberOfNodes();
1347 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1348 ret->alloc(nbOfNodes,1);
1349 int *traducer=ret->getPointer();
1350 std::fill(traducer,traducer+nbOfNodes,-1);
1351 int nbOfCells=getNumberOfCells();
1352 const int *connIndex=_nodal_connec_index->getConstPointer();
1353 const int *conn=_nodal_connec->getConstPointer();
1354 for(int i=0;i<nbOfCells;i++)
1355 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1358 if(conn[j]<nbOfNodes)
1359 traducer[conn[j]]=1;
1362 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1363 throw INTERP_KERNEL::Exception(oss.str().c_str());
1366 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1367 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1372 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1373 * For each cell in \b this the number of nodes constituting cell is computed.
1374 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1375 * So for pohyhedrons some nodes can be counted several times in the returned result.
1377 * \return a newly allocated array
1379 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1381 checkConnectivityFullyDefined();
1382 int nbOfCells=getNumberOfCells();
1383 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1384 ret->alloc(nbOfCells,1);
1385 int *retPtr=ret->getPointer();
1386 const int *conn=getNodalConnectivity()->getConstPointer();
1387 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1388 for(int i=0;i<nbOfCells;i++,retPtr++)
1390 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1391 *retPtr=connI[i+1]-connI[i]-1;
1393 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1399 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1400 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1402 * \return a newly allocated array
1404 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception)
1406 checkConnectivityFullyDefined();
1407 int nbOfCells=getNumberOfCells();
1408 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1409 ret->alloc(nbOfCells,1);
1410 int *retPtr=ret->getPointer();
1411 const int *conn=getNodalConnectivity()->getConstPointer();
1412 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1413 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1415 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1416 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1422 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1423 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1424 * array mean that the corresponding old node is no more used.
1425 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1426 * this->getNumberOfNodes() before call of this method. The caller is to
1427 * delete this array using decrRef() as it is no more needed.
1428 * \throw If the coordinates array is not set.
1429 * \throw If the nodal connectivity of cells is not defined.
1430 * \throw If the nodal connectivity includes an invalid id.
1432 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1433 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1435 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1437 int newNbOfNodes=-1;
1438 DataArrayInt *traducer=getNodeIdsInUse(newNbOfNodes);
1439 renumberNodes(traducer->getConstPointer(),newNbOfNodes);
1444 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1445 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1447 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1452 return AreCellsEqual0(conn,connI,cell1,cell2);
1454 return AreCellsEqual1(conn,connI,cell1,cell2);
1456 return AreCellsEqual2(conn,connI,cell1,cell2);
1458 return AreCellsEqual3(conn,connI,cell1,cell2);
1460 return AreCellsEqual7(conn,connI,cell1,cell2);
1462 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1466 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1468 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1470 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1471 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1476 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1478 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1480 int sz=connI[cell1+1]-connI[cell1];
1481 if(sz==connI[cell2+1]-connI[cell2])
1483 if(conn[connI[cell1]]==conn[connI[cell2]])
1485 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1486 unsigned dim=cm.getDimension();
1492 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1493 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1494 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1495 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1496 return work!=tmp+sz1?1:0;
1499 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1502 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1509 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1511 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1513 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1515 if(conn[connI[cell1]]==conn[connI[cell2]])
1517 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1518 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1526 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1528 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1530 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1532 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1533 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1540 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1542 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1544 int sz=connI[cell1+1]-connI[cell1];
1545 if(sz==connI[cell2+1]-connI[cell2])
1547 if(conn[connI[cell1]]==conn[connI[cell2]])
1549 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1550 unsigned dim=cm.getDimension();
1556 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1557 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1558 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1559 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1564 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1565 std::reverse_iterator<int *> it2((int *)tmp);
1566 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1572 return work!=tmp+sz1?1:0;
1575 {//case of SEG2 and SEG3
1576 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1578 if(!cm.isQuadratic())
1580 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1581 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1582 if(std::equal(it1,it2,conn+connI[cell2]+1))
1588 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])
1595 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1602 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1603 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1604 * and result remains unchanged.
1605 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1606 * If in 'candidates' pool -1 value is considered as an empty value.
1607 * WARNING this method returns only ONE set of result !
1609 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1611 if(candidates.size()<1)
1614 std::vector<int>::const_iterator iter=candidates.begin();
1615 int start=(*iter++);
1616 for(;iter!=candidates.end();iter++)
1618 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1623 result->pushBackSilent(start);
1627 result->pushBackSilent(*iter);
1629 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1636 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1637 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1639 * \param [in] compType input specifying the technique used to compare cells each other.
1640 * - 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.
1641 * - 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)
1642 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1643 * - 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
1644 * can be used for users not sensitive to orientation of cell
1645 * \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.
1646 * \param [out] commonCells
1647 * \param [out] commonCellsI
1648 * \return the correspondance array old to new in a newly allocated array.
1651 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1653 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1654 getReverseNodalConnectivity(revNodal,revNodalI);
1655 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1658 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1659 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1661 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1662 int nbOfCells=nodalI->getNumberOfTuples()-1;
1663 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1664 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1665 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1666 std::vector<bool> isFetched(nbOfCells,false);
1669 for(int i=0;i<nbOfCells;i++)
1673 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1674 std::vector<int> v,v2;
1675 if(connOfNode!=connPtr+connIPtr[i+1])
1677 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1678 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1681 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1685 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1686 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1687 v2.resize(std::distance(v2.begin(),it));
1691 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1693 int pos=commonCellsI->back();
1694 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1695 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1696 isFetched[*it]=true;
1704 for(int i=startCellId;i<nbOfCells;i++)
1708 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1709 std::vector<int> v,v2;
1710 if(connOfNode!=connPtr+connIPtr[i+1])
1712 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1715 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1719 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1720 v2.resize(std::distance(v2.begin(),it));
1724 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1726 int pos=commonCellsI->back();
1727 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1728 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1729 isFetched[*it]=true;
1735 commonCellsArr=commonCells.retn();
1736 commonCellsIArr=commonCellsI.retn();
1740 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1741 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1742 * than \a other->getNumberOfCells() in the returned array means that there is no
1743 * corresponding cell in \a this mesh.
1744 * It is expected that \a this and \a other meshes share the same node coordinates
1745 * array, if it is not so an exception is thrown.
1746 * \param [in] other - the mesh to compare with.
1747 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1748 * valid values [0,1,2], see zipConnectivityTraducer().
1749 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1750 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1751 * values. The caller is to delete this array using
1752 * decrRef() as it is no more needed.
1753 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1756 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1757 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1758 * \sa checkDeepEquivalOnSameNodesWith()
1759 * \sa checkGeoEquivalWith()
1761 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1763 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1764 int nbOfCells=getNumberOfCells();
1765 static const int possibleCompType[]={0,1,2};
1766 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1768 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1769 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1771 throw INTERP_KERNEL::Exception(oss.str().c_str());
1773 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1774 arr=o2n->substr(nbOfCells);
1775 arr->setName(other->getName());
1777 if(other->getNumberOfCells()==0)
1779 return arr->getMaxValue(tmp)<nbOfCells;
1783 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1784 * This method tries to determine if \b other is fully included in \b this.
1785 * The main difference is that this method is not expected to throw exception.
1786 * This method has two outputs :
1788 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1789 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1791 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1793 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1794 DataArrayInt *commonCells=0,*commonCellsI=0;
1795 int thisNbCells=getNumberOfCells();
1796 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1797 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1798 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1799 int otherNbCells=other->getNumberOfCells();
1800 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1801 arr2->alloc(otherNbCells,1);
1802 arr2->fillWithZero();
1803 int *arr2Ptr=arr2->getPointer();
1804 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1805 for(int i=0;i<nbOfCommon;i++)
1807 int start=commonCellsPtr[commonCellsIPtr[i]];
1808 if(start<thisNbCells)
1810 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1812 int sig=commonCellsPtr[j]>0?1:-1;
1813 int val=std::abs(commonCellsPtr[j])-1;
1814 if(val>=thisNbCells)
1815 arr2Ptr[val-thisNbCells]=sig*(start+1);
1819 arr2->setName(other->getName());
1820 if(arr2->presenceOfValue(0))
1827 * Merges nodes equal within \a precision and returns an array describing the
1828 * permutation used to remove duplicate nodes.
1829 * \param [in] precision - minimal absolute distance between two nodes at which they are
1830 * considered not coincident.
1831 * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1832 * \param [out] newNbOfNodes - number of nodes remaining after the removal.
1833 * \return DataArrayInt * - the permutation array in "Old to New" mode. For more
1834 * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1835 * is to delete this array using decrRef() as it is no more needed.
1836 * \throw If the coordinates array is not set.
1837 * \throw If the nodal connectivity of cells is not defined.
1839 * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1840 * \ref py_mcumesh_mergeNodes "Here is a Python example".
1842 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
1844 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1846 renumberNodes(ret->begin(),newNbOfNodes);
1852 * Merges nodes equal within \a precision and returns an array describing the
1853 * permutation used to remove duplicate nodes. In contrast to mergeNodes(), location
1854 * of merged nodes is changed to be at their barycenter.
1855 * \param [in] precision - minimal absolute distance between two nodes at which they are
1856 * considered not coincident.
1857 * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1858 * \param [out] newNbOfNodes - number of nodes remaining after the removal.
1859 * \return DataArrayInt * - the permutation array in "Old to New" mode. For more
1860 * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1861 * is to delete this array using decrRef() as it is no more needed.
1862 * \throw If the coordinates array is not set.
1863 * \throw If the nodal connectivity of cells is not defined.
1865 * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1866 * \ref py_mcumesh_mergeNodes "Here is a Python example".
1868 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
1870 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1872 renumberNodes2(ret->getConstPointer(),newNbOfNodes);
1876 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1879 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1880 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1882 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1883 std::vector<const MEDCouplingUMesh *> ms(2);
1886 return MergeUMeshesOnSameCoords(ms);
1890 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1891 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1892 * cellIds is not given explicitely but by a range python like.
1894 * \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.
1895 * \return a newly allocated
1897 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1898 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1900 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1902 if(getMeshDimension()!=-1)
1903 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1906 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1908 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1910 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1912 return const_cast<MEDCouplingUMesh *>(this);
1917 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1918 * The result mesh shares or not the node coordinates array with \a this mesh depending
1919 * on \a keepCoords parameter.
1920 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1921 * to write this mesh to the MED file, its cells must be sorted using
1922 * sortCellsInMEDFileFrmt().
1923 * \param [in] begin - an array of cell ids to include to the new mesh.
1924 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
1925 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1926 * array of \a this mesh, else "free" nodes are removed from the result mesh
1927 * by calling zipCoords().
1928 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1929 * to delete this mesh using decrRef() as it is no more needed.
1930 * \throw If the coordinates array is not set.
1931 * \throw If the nodal connectivity of cells is not defined.
1932 * \throw If any cell id in the array \a begin is not valid.
1934 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1935 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
1937 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1939 if(getMeshDimension()!=-1)
1940 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1944 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1946 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1948 return const_cast<MEDCouplingUMesh *>(this);
1953 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1955 * 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.
1956 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1957 * The number of cells of \b this will remain the same with this method.
1959 * \param [in] begin begin of cell ids (included) of cells in this to assign
1960 * \param [in] end end of cell ids (excluded) of cells in this to assign
1961 * \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 ).
1962 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1964 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1966 checkConnectivityFullyDefined();
1967 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1968 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1969 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1970 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1972 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1973 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1974 throw INTERP_KERNEL::Exception(oss.str().c_str());
1976 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1977 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1979 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1980 throw INTERP_KERNEL::Exception(oss.str().c_str());
1982 int nbOfCells=getNumberOfCells();
1983 bool easyAssign=true;
1984 const int *connI=_nodal_connec_index->getConstPointer();
1985 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1986 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1988 if(*it>=0 && *it<nbOfCells)
1990 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1994 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1995 throw INTERP_KERNEL::Exception(oss.str().c_str());
2000 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2005 DataArrayInt *arrOut=0,*arrIOut=0;
2006 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2008 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2009 setConnectivity(arrOut,arrIOut,true);
2013 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2015 checkConnectivityFullyDefined();
2016 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2017 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2018 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2019 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2021 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2022 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2023 throw INTERP_KERNEL::Exception(oss.str().c_str());
2025 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2026 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2028 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2029 throw INTERP_KERNEL::Exception(oss.str().c_str());
2031 int nbOfCells=getNumberOfCells();
2032 bool easyAssign=true;
2033 const int *connI=_nodal_connec_index->getConstPointer();
2034 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2036 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2038 if(it>=0 && it<nbOfCells)
2040 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2044 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2045 throw INTERP_KERNEL::Exception(oss.str().c_str());
2050 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2055 DataArrayInt *arrOut=0,*arrIOut=0;
2056 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2058 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2059 setConnectivity(arrOut,arrIOut,true);
2064 * Finds cells whose all nodes are in a given array of node ids.
2065 * \param [in] partBg - the array of node ids.
2066 * \param [in] partEnd - a pointer to a (last+1)-th element of \a partBg.
2067 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2068 * cells. The caller is to delete this array using decrRef() as it is no
2070 * \throw If the coordinates array is not set.
2071 * \throw If the nodal connectivity of cells is not defined.
2072 * \throw If any cell id in \a partBg is not valid.
2074 * \ref cpp_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a C++ example".<br>
2075 * \ref py_mcumesh_getCellIdsFullyIncludedInNodeIds "Here is a Python example".
2077 DataArrayInt *MEDCouplingUMesh::getCellIdsFullyIncludedInNodeIds(const int *partBg, const int *partEnd) const
2079 DataArrayInt *cellIdsKept=0;
2080 fillCellIdsToKeepFromNodeIds(partBg,partEnd,true,cellIdsKept);
2081 cellIdsKept->setName(getName());
2086 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2087 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2088 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2089 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2091 * \param [in] begin input start of array of node ids.
2092 * \param [in] end input end of array of node ids.
2093 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2094 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2096 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2098 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2099 checkConnectivityFullyDefined();
2101 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2102 std::vector<bool> fastFinder(sz,false);
2103 for(const int *work=begin;work!=end;work++)
2104 if(*work>=0 && *work<sz)
2105 fastFinder[*work]=true;
2106 int nbOfCells=getNumberOfCells();
2107 const int *conn=getNodalConnectivity()->getConstPointer();
2108 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2109 for(int i=0;i<nbOfCells;i++)
2111 int ref=0,nbOfHit=0;
2112 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2116 if(fastFinder[*work2])
2119 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2120 cellIdsKept->pushBackSilent(i);
2122 cellIdsKeptArr=cellIdsKept.retn();
2126 * Finds cells whose all or some nodes are in a given array of node ids.
2127 * \param [in] begin - the array of node ids.
2128 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2129 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2130 * array \a begin are returned only, else cells whose any node is in the
2131 * array \a begin are returned.
2132 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2133 * cells. The caller is to delete this array using decrRef() as it is no more
2135 * \throw If the coordinates array is not set.
2136 * \throw If the nodal connectivity of cells is not defined.
2137 * \throw If any cell id in \a begin is not valid.
2139 * \ref cpp_mcumesh_getCellIdsLyingOnNodes "Here is a C++ example".<br>
2140 * \ref py_mcumesh_getCellIdsLyingOnNodes "Here is a Python example".
2142 DataArrayInt *MEDCouplingUMesh::getCellIdsLyingOnNodes(const int *begin, const int *end, bool fullyIn) const
2144 DataArrayInt *cellIdsKept=0;
2145 fillCellIdsToKeepFromNodeIds(begin,end,fullyIn,cellIdsKept);
2146 cellIdsKept->setName(getName());
2151 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2152 * this->getMeshDimension(), that bound some cells of \a this mesh.
2153 * The cells of lower dimension to include to the result mesh are selected basing on
2154 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2155 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2156 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2157 * created mesh shares the node coordinates array with \a this mesh.
2158 * \param [in] begin - the array of node ids.
2159 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2160 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2161 * array \a begin are added, else cells whose any node is in the
2162 * array \a begin are added.
2163 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2164 * to delete this mesh using decrRef() as it is no more needed.
2165 * \throw If the coordinates array is not set.
2166 * \throw If the nodal connectivity of cells is not defined.
2167 * \throw If any node id in \a begin is not valid.
2169 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2170 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2172 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2174 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2175 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2176 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2177 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2178 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2182 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2183 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2184 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2185 * array of \a this mesh, else "free" nodes are removed from the result mesh
2186 * by calling zipCoords().
2187 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2188 * to delete this mesh using decrRef() as it is no more needed.
2189 * \throw If the coordinates array is not set.
2190 * \throw If the nodal connectivity of cells is not defined.
2192 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2193 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2195 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2197 DataArrayInt *desc=DataArrayInt::New();
2198 DataArrayInt *descIndx=DataArrayInt::New();
2199 DataArrayInt *revDesc=DataArrayInt::New();
2200 DataArrayInt *revDescIndx=DataArrayInt::New();
2202 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2205 descIndx->decrRef();
2206 int nbOfCells=meshDM1->getNumberOfCells();
2207 const int *revDescIndxC=revDescIndx->getConstPointer();
2208 std::vector<int> boundaryCells;
2209 for(int i=0;i<nbOfCells;i++)
2210 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2211 boundaryCells.push_back(i);
2212 revDescIndx->decrRef();
2213 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2218 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2219 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2220 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2222 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2224 checkFullyDefined();
2225 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2226 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2227 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2228 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2230 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2231 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2233 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2234 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2235 const int *revDescPtr=revDesc->getConstPointer();
2236 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2237 int nbOfCells=getNumberOfCells();
2238 std::vector<bool> ret1(nbOfCells,false);
2240 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2241 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2242 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2244 DataArrayInt *ret2=DataArrayInt::New();
2246 int *ret2Ptr=ret2->getPointer();
2248 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2251 ret2->setName("BoundaryCells");
2256 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2257 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2258 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2259 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2261 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2262 * This method method returns cells ids set s = s1 + s2 where :
2264 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2265 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2267 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2268 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2270 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2271 * \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
2272 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2274 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2276 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2277 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2278 checkConnectivityFullyDefined();
2279 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2280 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2281 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2282 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2283 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2284 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2285 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2286 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2287 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2288 DataArrayInt *idsOtherInConsti=0;
2289 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2290 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2292 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2294 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2295 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2296 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2297 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2298 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2299 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2300 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2301 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2302 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2303 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2304 neighThisPartAuto=0;
2305 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2306 const int li[2]={0,1};
2307 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2308 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2309 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2312 cellIdsRk0=s0arr.retn();
2313 cellIdsRk1=s_renum1.retn();
2317 * 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
2318 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2320 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2322 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2324 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2325 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2326 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2327 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2329 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2330 revDesc=0; desc=0; descIndx=0;
2331 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2332 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2333 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2337 * Finds nodes lying on the boundary of \a this mesh.
2338 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2339 * nodes. The caller is to delete this array using decrRef() as it is no
2341 * \throw If the coordinates array is not set.
2342 * \throw If the nodal connectivity of cells is node defined.
2344 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2345 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2347 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2349 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2350 return skin->computeFetchedNodeIds();
2353 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2356 return const_cast<MEDCouplingUMesh *>(this);
2360 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2361 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2362 * 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.
2363 * 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.
2364 * 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.
2366 * \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
2367 * parameter is altered during the call.
2368 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2369 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2370 * \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.
2372 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2374 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2375 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2377 checkFullyDefined();
2378 otherDimM1OnSameCoords.checkFullyDefined();
2379 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2380 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2381 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2382 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2383 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2384 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2385 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2386 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2387 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2388 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2389 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2390 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2391 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2392 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2394 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2395 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2396 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2397 DataArrayInt *idsTmp=0;
2398 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2399 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2401 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2402 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2403 DataArrayInt *tmp0=0,*tmp1=0;
2404 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2405 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2406 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2407 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2408 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2409 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2410 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2412 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2413 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2414 nodeIdsToDuplicate=s3.retn();
2418 * This method operates a modification of the connectivity and coords in \b this.
2419 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2420 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2421 * 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
2422 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2423 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2425 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2427 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2428 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2430 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2432 int nbOfNodes=getNumberOfNodes();
2433 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2434 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2438 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2439 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2440 * This method is a generalization of shiftNodeNumbersInConn().
2441 * \warning This method performs no check of validity of new ids. **Use it with care !**
2442 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2443 * this->getNumberOfNodes(), in "Old to New" mode.
2444 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2445 * \throw If the nodal connectivity of cells is not defined.
2447 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2448 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2450 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2452 checkConnectivityFullyDefined();
2453 int *conn=getNodalConnectivity()->getPointer();
2454 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2455 int nbOfCells=getNumberOfCells();
2456 for(int i=0;i<nbOfCells;i++)
2457 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2459 int& node=conn[iconn];
2460 if(node>=0)//avoid polyhedron separator
2462 node=newNodeNumbersO2N[node];
2465 _nodal_connec->declareAsNew();
2470 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2471 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2472 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2474 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2476 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2478 checkConnectivityFullyDefined();
2479 int *conn=getNodalConnectivity()->getPointer();
2480 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2481 int nbOfCells=getNumberOfCells();
2482 for(int i=0;i<nbOfCells;i++)
2483 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2485 int& node=conn[iconn];
2486 if(node>=0)//avoid polyhedron separator
2491 _nodal_connec->declareAsNew();
2496 * This method operates a modification of the connectivity in \b this.
2497 * 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.
2498 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2499 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2500 * 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
2501 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2502 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2504 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2505 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2507 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2508 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2509 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2511 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2513 checkConnectivityFullyDefined();
2514 std::map<int,int> m;
2516 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2518 int *conn=getNodalConnectivity()->getPointer();
2519 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2520 int nbOfCells=getNumberOfCells();
2521 for(int i=0;i<nbOfCells;i++)
2522 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2524 int& node=conn[iconn];
2525 if(node>=0)//avoid polyhedron separator
2527 std::map<int,int>::iterator it=m.find(node);
2536 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2538 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2539 * After the call of this method the number of cells remains the same as before.
2541 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2542 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2543 * be strictly in [0;this->getNumberOfCells()).
2545 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2546 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2547 * should be contained in[0;this->getNumberOfCells()).
2549 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2551 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2553 checkConnectivityFullyDefined();
2554 int nbCells=getNumberOfCells();
2555 const int *array=old2NewBg;
2557 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2559 const int *conn=_nodal_connec->getConstPointer();
2560 const int *connI=_nodal_connec_index->getConstPointer();
2561 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2562 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2563 const int *n2oPtr=n2o->begin();
2564 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2565 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2566 newConn->copyStringInfoFrom(*_nodal_connec);
2567 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2568 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2569 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2571 int *newC=newConn->getPointer();
2572 int *newCI=newConnI->getPointer();
2575 for(int i=0;i<nbCells;i++)
2578 int nbOfElts=connI[pos+1]-connI[pos];
2579 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2584 setConnectivity(newConn,newConnI);
2586 free(const_cast<int *>(array));
2590 * Finds cells whose bounding boxes intersect a given bounding box.
2591 * \param [in] bbox - an array defining the bounding box via coordinates of its
2592 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2594 * \param [in] eps - a factor used to increase size of the bounding box of cell
2595 * before comparing it with \a bbox. This factor is multiplied by the maximal
2596 * extent of the bounding box of cell to produce an addition to this bounding box.
2597 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2598 * cells. The caller is to delete this array using decrRef() as it is no more
2600 * \throw If the coordinates array is not set.
2601 * \throw If the nodal connectivity of cells is not defined.
2603 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2604 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2606 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2608 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2609 if(getMeshDimension()==-1)
2611 elems->pushBackSilent(0);
2612 return elems.retn();
2614 int dim=getSpaceDimension();
2615 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2616 const int* conn = getNodalConnectivity()->getConstPointer();
2617 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2618 const double* coords = getCoords()->getConstPointer();
2619 int nbOfCells=getNumberOfCells();
2620 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2622 for (int i=0; i<dim; i++)
2624 elem_bb[i*2]=std::numeric_limits<double>::max();
2625 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2628 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2630 int node= conn[inode];
2631 if(node>=0)//avoid polyhedron separator
2633 for (int idim=0; idim<dim; idim++)
2635 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2637 elem_bb[idim*2] = coords[node*dim+idim] ;
2639 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2641 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2646 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2647 elems->pushBackSilent(ielem);
2649 return elems.retn();
2653 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2654 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2655 * added in 'elems' parameter.
2657 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2659 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2660 if(getMeshDimension()==-1)
2662 elems->pushBackSilent(0);
2663 return elems.retn();
2665 int dim=getSpaceDimension();
2666 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2667 const int* conn = getNodalConnectivity()->getConstPointer();
2668 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2669 const double* coords = getCoords()->getConstPointer();
2670 int nbOfCells=getNumberOfCells();
2671 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2673 for (int i=0; i<dim; i++)
2675 elem_bb[i*2]=std::numeric_limits<double>::max();
2676 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2679 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2681 int node= conn[inode];
2682 if(node>=0)//avoid polyhedron separator
2684 for (int idim=0; idim<dim; idim++)
2686 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2688 elem_bb[idim*2] = coords[node*dim+idim] ;
2690 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2692 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2697 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2698 elems->pushBackSilent(ielem);
2700 return elems.retn();
2704 * Returns a type of a cell by its id.
2705 * \param [in] cellId - the id of the cell of interest.
2706 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2707 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2709 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2711 const int *ptI=_nodal_connec_index->getConstPointer();
2712 const int *pt=_nodal_connec->getConstPointer();
2713 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2714 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2717 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2718 throw INTERP_KERNEL::Exception(oss.str().c_str());
2723 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2724 * This method does not throw exception if geometric type \a type is not in \a this.
2725 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2726 * The coordinates array is not considered here.
2728 * \param [in] type the geometric type
2729 * \return cell ids in this having geometric type \a type.
2731 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2734 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2736 checkConnectivityFullyDefined();
2737 int nbCells=getNumberOfCells();
2738 int mdim=getMeshDimension();
2739 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2740 if(mdim!=(int)cm.getDimension())
2741 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2742 const int *ptI=_nodal_connec_index->getConstPointer();
2743 const int *pt=_nodal_connec->getConstPointer();
2744 for(int i=0;i<nbCells;i++)
2746 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2747 ret->pushBackSilent(i);
2753 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2755 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2757 const int *ptI=_nodal_connec_index->getConstPointer();
2758 const int *pt=_nodal_connec->getConstPointer();
2759 int nbOfCells=getNumberOfCells();
2761 for(int i=0;i<nbOfCells;i++)
2762 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2768 * Returns the nodal connectivity of a given cell.
2769 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2770 * all returned node ids can be used in getCoordinatesOfNode().
2771 * \param [in] cellId - an id of the cell of interest.
2772 * \param [in,out] conn - a vector where the node ids are appended. It is not
2773 * cleared before the appending.
2774 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2776 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2778 const int *ptI=_nodal_connec_index->getConstPointer();
2779 const int *pt=_nodal_connec->getConstPointer();
2780 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2785 std::string MEDCouplingUMesh::simpleRepr() const
2787 static const char msg0[]="No coordinates specified !";
2788 std::ostringstream ret;
2789 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2790 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2792 double tt=getTime(tmpp1,tmpp2);
2793 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2794 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2796 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2798 { ret << " Mesh dimension has not been set or is invalid !"; }
2801 const int spaceDim=getSpaceDimension();
2802 ret << spaceDim << "\nInfo attached on space dimension : ";
2803 for(int i=0;i<spaceDim;i++)
2804 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2808 ret << msg0 << "\n";
2809 ret << "Number of nodes : ";
2811 ret << getNumberOfNodes() << "\n";
2813 ret << msg0 << "\n";
2814 ret << "Number of cells : ";
2815 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2816 ret << getNumberOfCells() << "\n";
2818 ret << "No connectivity specified !" << "\n";
2819 ret << "Cell types present : ";
2820 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2822 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2823 ret << cm.getRepr() << " ";
2829 std::string MEDCouplingUMesh::advancedRepr() const
2831 std::ostringstream ret;
2832 ret << simpleRepr();
2833 ret << "\nCoordinates array : \n___________________\n\n";
2835 _coords->reprWithoutNameStream(ret);
2837 ret << "No array set !\n";
2838 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2839 reprConnectivityOfThisLL(ret);
2844 * This method returns a C++ code that is a dump of \a this.
2845 * This method will throw if this is not fully defined.
2847 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2849 static const char coordsName[]="coords";
2850 static const char connName[]="conn";
2851 static const char connIName[]="connI";
2852 checkFullyDefined();
2853 std::ostringstream ret; ret << "// coordinates" << std::endl;
2854 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2855 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2856 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2857 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2858 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2859 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2860 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2864 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2866 std::ostringstream ret;
2867 reprConnectivityOfThisLL(ret);
2872 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2873 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2874 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2877 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2878 * 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
2879 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2881 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2883 int mdim=getMeshDimension();
2885 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2886 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2887 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2888 bool needToCpyCT=true;
2891 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2899 if(!_nodal_connec_index)
2901 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2906 tmp2=_nodal_connec_index;
2909 ret->setConnectivity(tmp1,tmp2,false);
2914 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2915 ret->setCoords(coords);
2918 ret->setCoords(_coords);
2922 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2924 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2926 int nbOfCells=getNumberOfCells();
2927 const int *c=_nodal_connec->getConstPointer();
2928 const int *ci=_nodal_connec_index->getConstPointer();
2929 for(int i=0;i<nbOfCells;i++)
2931 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2932 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2933 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2938 stream << "Connectivity not defined !\n";
2941 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2943 const int *ptI=_nodal_connec_index->getConstPointer();
2944 const int *pt=_nodal_connec->getConstPointer();
2945 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2946 return ptI[cellId+1]-ptI[cellId]-1;
2948 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2952 * Returns types of cells of the specified part of \a this mesh.
2953 * This method avoids computing sub-mesh explicitely to get its types.
2954 * \param [in] begin - an array of cell ids of interest.
2955 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2956 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2957 * describing the cell types.
2958 * \throw If the coordinates array is not set.
2959 * \throw If the nodal connectivity of cells is not defined.
2962 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2964 checkFullyDefined();
2965 std::set<INTERP_KERNEL::NormalizedCellType> ret;
2966 const int *conn=_nodal_connec->getConstPointer();
2967 const int *connIndex=_nodal_connec_index->getConstPointer();
2968 for(const int *w=begin;w!=end;w++)
2969 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2974 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2975 * a set of types of cells constituting \a this mesh.
2976 * This method is for advanced users having prepared their connectivity before. For
2977 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2978 * \param [in] conn - the nodal connectivity array.
2979 * \param [in] connIndex - the nodal connectivity index array.
2980 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2983 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2985 DataArrayInt::SetArrayIn(conn,_nodal_connec);
2986 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2987 if(isComputingTypes)
2993 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2994 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2996 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2997 _nodal_connec(0),_nodal_connec_index(0),
2998 _types(other._types)
3000 if(other._nodal_connec)
3001 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
3002 if(other._nodal_connec_index)
3003 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
3006 MEDCouplingUMesh::~MEDCouplingUMesh()
3009 _nodal_connec->decrRef();
3010 if(_nodal_connec_index)
3011 _nodal_connec_index->decrRef();
3015 * Recomputes a set of cell types of \a this mesh. For more info see
3016 * \ref MEDCouplingUMeshNodalConnectivity.
3018 void MEDCouplingUMesh::computeTypes()
3020 if(_nodal_connec && _nodal_connec_index)
3023 const int *conn=_nodal_connec->getConstPointer();
3024 const int *connIndex=_nodal_connec_index->getConstPointer();
3025 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
3027 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
3028 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
3033 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
3035 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
3037 if(!_nodal_connec_index || !_nodal_connec || !_coords)
3038 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
3042 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
3044 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
3046 if(!_nodal_connec_index || !_nodal_connec)
3047 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3051 * Returns a number of cells constituting \a this mesh.
3052 * \return int - the number of cells in \a this mesh.
3053 * \throw If the nodal connectivity of cells is not defined.
3055 int MEDCouplingUMesh::getNumberOfCells() const
3057 if(_nodal_connec_index)
3058 return _nodal_connec_index->getNumberOfTuples()-1;
3063 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3067 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3068 * mesh. For more info see \ref MEDCouplingMeshesPage.
3069 * \return int - the dimension of \a this mesh.
3070 * \throw If the mesh dimension is not defined using setMeshDimension().
3072 int MEDCouplingUMesh::getMeshDimension() const
3075 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3080 * Returns a length of the nodal connectivity array.
3081 * This method is for test reason. Normally the integer returned is not useable by
3082 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3083 * \return int - the length of the nodal connectivity array.
3085 int MEDCouplingUMesh::getMeshLength() const
3087 return _nodal_connec->getNbOfElems();
3091 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3093 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3095 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3096 tinyInfo.push_back(getMeshDimension());
3097 tinyInfo.push_back(getNumberOfCells());
3099 tinyInfo.push_back(getMeshLength());
3101 tinyInfo.push_back(-1);
3105 * First step of unserialization process.
3107 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3109 return tinyInfo[6]<=0;
3113 * Second step of serialization process.
3114 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3116 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3118 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3120 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3124 * Third and final step of serialization process.
3126 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3128 MEDCouplingPointSet::serialize(a1,a2);
3129 if(getMeshDimension()>-1)
3131 a1=DataArrayInt::New();
3132 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3133 int *ptA1=a1->getPointer();
3134 const int *conn=getNodalConnectivity()->getConstPointer();
3135 const int *index=getNodalConnectivityIndex()->getConstPointer();
3136 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3137 std::copy(conn,conn+getMeshLength(),ptA1);
3144 * Second and final unserialization process.
3145 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3147 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3149 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3150 setMeshDimension(tinyInfo[5]);
3154 const int *recvBuffer=a1->getConstPointer();
3155 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3156 myConnecIndex->alloc(tinyInfo[6]+1,1);
3157 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3158 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3159 myConnec->alloc(tinyInfo[7],1);
3160 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3161 setConnectivity(myConnec, myConnecIndex);
3166 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3167 * CellIds are given using range specified by a start an end and step.
3169 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3171 checkFullyDefined();
3172 int ncell=getNumberOfCells();
3173 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3174 ret->_mesh_dim=_mesh_dim;
3175 ret->setCoords(_coords);
3176 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3177 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3178 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3180 const int *conn=_nodal_connec->getConstPointer();
3181 const int *connIndex=_nodal_connec_index->getConstPointer();
3182 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3184 if(work>=0 && work<ncell)
3186 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3190 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3191 throw INTERP_KERNEL::Exception(oss.str().c_str());
3194 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3195 int *newConnPtr=newConn->getPointer();
3196 std::set<INTERP_KERNEL::NormalizedCellType> types;
3198 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3200 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3201 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3203 ret->setConnectivity(newConn,newConnI,false);
3205 ret->copyTinyInfoFrom(this);
3210 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3211 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3212 * The return newly allocated mesh will share the same coordinates as \a this.
3214 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3216 checkFullyDefined();
3217 int ncell=getNumberOfCells();
3218 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3219 ret->_mesh_dim=_mesh_dim;
3220 ret->setCoords(_coords);
3221 std::size_t nbOfElemsRet=std::distance(begin,end);
3222 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3224 const int *conn=_nodal_connec->getConstPointer();
3225 const int *connIndex=_nodal_connec_index->getConstPointer();
3227 for(const int *work=begin;work!=end;work++,newNbring++)
3229 if(*work>=0 && *work<ncell)
3230 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3234 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3235 throw INTERP_KERNEL::Exception(oss.str().c_str());
3238 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3239 int *connRetWork=connRet;
3240 std::set<INTERP_KERNEL::NormalizedCellType> types;
3241 for(const int *work=begin;work!=end;work++)
3243 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3244 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3246 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3247 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3248 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3249 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3250 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3252 ret->copyTinyInfoFrom(this);
3257 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3259 * For 1D cells, the returned field contains lengths.<br>
3260 * For 2D cells, the returned field contains areas.<br>
3261 * For 3D cells, the returned field contains volumes.
3262 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3263 * orientation, i.e. the volume is always positive.
3264 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3265 * and one time . The caller is to delete this field using decrRef() as it is no
3268 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3270 std::string name="MeasureOfMesh_";
3272 int nbelem=getNumberOfCells();
3273 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3274 field->setName(name.c_str());
3275 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3276 array->alloc(nbelem,1);
3277 double *area_vol=array->getPointer();
3278 field->setArray(array) ; array=0;
3279 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3280 field->synchronizeTimeWithMesh();
3281 if(getMeshDimension()!=-1)
3284 INTERP_KERNEL::NormalizedCellType type;
3285 int dim_space=getSpaceDimension();
3286 const double *coords=getCoords()->getConstPointer();
3287 const int *connec=getNodalConnectivity()->getConstPointer();
3288 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3289 for(int iel=0;iel<nbelem;iel++)
3291 ipt=connec_index[iel];
3292 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3293 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);
3296 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3300 area_vol[0]=std::numeric_limits<double>::max();
3302 return field.retn();
3306 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3308 * For 1D cells, the returned array contains lengths.<br>
3309 * For 2D cells, the returned array contains areas.<br>
3310 * For 3D cells, the returned array contains volumes.
3311 * This method avoids building explicitly a part of \a this mesh to perform the work.
3312 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3313 * orientation, i.e. the volume is always positive.
3314 * \param [in] begin - an array of cell ids of interest.
3315 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3316 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3317 * delete this array using decrRef() as it is no more needed.
3319 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3320 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3321 * \sa getMeasureField()
3323 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3325 std::string name="PartMeasureOfMesh_";
3327 int nbelem=(int)std::distance(begin,end);
3328 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3329 array->setName(name.c_str());
3330 array->alloc(nbelem,1);
3331 double *area_vol=array->getPointer();
3332 if(getMeshDimension()!=-1)
3335 INTERP_KERNEL::NormalizedCellType type;
3336 int dim_space=getSpaceDimension();
3337 const double *coords=getCoords()->getConstPointer();
3338 const int *connec=getNodalConnectivity()->getConstPointer();
3339 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3340 for(const int *iel=begin;iel!=end;iel++)
3342 ipt=connec_index[*iel];
3343 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3344 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3347 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3351 area_vol[0]=std::numeric_limits<double>::max();
3353 return array.retn();
3357 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3358 * \a this one. The returned field contains the dual cell volume for each corresponding
3359 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3360 * the dual mesh in P1 sens of \a this.<br>
3361 * For 1D cells, the returned field contains lengths.<br>
3362 * For 2D cells, the returned field contains areas.<br>
3363 * For 3D cells, the returned field contains volumes.
3364 * This method is useful to check "P1*" conservative interpolators.
3365 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3366 * orientation, i.e. the volume is always positive.
3367 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3368 * nodes and one time. The caller is to delete this array using decrRef() as
3369 * it is no more needed.
3371 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3373 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3374 std::string name="MeasureOnNodeOfMesh_";
3376 int nbNodes=getNumberOfNodes();
3377 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3378 double cst=1./((double)getMeshDimension()+1.);
3379 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3380 array->alloc(nbNodes,1);
3381 double *valsToFill=array->getPointer();
3382 std::fill(valsToFill,valsToFill+nbNodes,0.);
3383 const double *values=tmp->getArray()->getConstPointer();
3384 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3385 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3386 getReverseNodalConnectivity(da,daInd);
3387 const int *daPtr=da->getConstPointer();
3388 const int *daIPtr=daInd->getConstPointer();
3389 for(int i=0;i<nbNodes;i++)
3390 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3391 valsToFill[i]+=cst*values[*cell];
3393 ret->setArray(array);
3398 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3399 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3400 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3401 * and are normalized.
3402 * <br> \a this can be either
3403 * - a 2D mesh in 2D or 3D space or
3404 * - an 1D mesh in 2D space.
3406 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3407 * cells and one time. The caller is to delete this field using decrRef() as
3408 * it is no more needed.
3409 * \throw If the nodal connectivity of cells is not defined.
3410 * \throw If the coordinates array is not set.
3411 * \throw If the mesh dimension is not set.
3412 * \throw If the mesh and space dimension is not as specified above.
3414 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3416 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3417 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3418 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3419 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3420 int nbOfCells=getNumberOfCells();
3421 int nbComp=getMeshDimension()+1;
3422 array->alloc(nbOfCells,nbComp);
3423 double *vals=array->getPointer();
3424 const int *connI=_nodal_connec_index->getConstPointer();
3425 const int *conn=_nodal_connec->getConstPointer();
3426 const double *coords=_coords->getConstPointer();
3427 if(getMeshDimension()==2)
3429 if(getSpaceDimension()==3)
3431 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3432 const double *locPtr=loc->getConstPointer();
3433 for(int i=0;i<nbOfCells;i++,vals+=3)
3435 int offset=connI[i];
3436 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3437 double n=INTERP_KERNEL::norm<3>(vals);
3438 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3443 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3444 const double *isAbsPtr=isAbs->getArray()->begin();
3445 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3446 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3449 else//meshdimension==1
3452 for(int i=0;i<nbOfCells;i++)
3454 int offset=connI[i];
3455 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3456 double n=INTERP_KERNEL::norm<2>(tmp);
3457 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3462 ret->setArray(array);
3464 ret->synchronizeTimeWithSupport();
3469 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3470 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3471 * and are normalized.
3472 * <br> \a this can be either
3473 * - a 2D mesh in 2D or 3D space or
3474 * - an 1D mesh in 2D space.
3476 * This method avoids building explicitly a part of \a this mesh to perform the work.
3477 * \param [in] begin - an array of cell ids of interest.
3478 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3479 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3480 * cells and one time. The caller is to delete this field using decrRef() as
3481 * it is no more needed.
3482 * \throw If the nodal connectivity of cells is not defined.
3483 * \throw If the coordinates array is not set.
3484 * \throw If the mesh dimension is not set.
3485 * \throw If the mesh and space dimension is not as specified above.
3486 * \sa buildOrthogonalField()
3488 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3489 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3491 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3493 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3494 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3495 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3496 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3497 std::size_t nbelems=std::distance(begin,end);
3498 int nbComp=getMeshDimension()+1;
3499 array->alloc((int)nbelems,nbComp);
3500 double *vals=array->getPointer();
3501 const int *connI=_nodal_connec_index->getConstPointer();
3502 const int *conn=_nodal_connec->getConstPointer();
3503 const double *coords=_coords->getConstPointer();
3504 if(getMeshDimension()==2)
3506 if(getSpaceDimension()==3)
3508 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3509 const double *locPtr=loc->getConstPointer();
3510 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3512 int offset=connI[*i];
3513 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3514 double n=INTERP_KERNEL::norm<3>(vals);
3515 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3520 for(std::size_t i=0;i<nbelems;i++)
3521 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3524 else//meshdimension==1
3527 for(const int *i=begin;i!=end;i++)
3529 int offset=connI[*i];
3530 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3531 double n=INTERP_KERNEL::norm<2>(tmp);
3532 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3537 ret->setArray(array);
3539 ret->synchronizeTimeWithSupport();
3544 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3545 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3546 * and are \b not normalized.
3547 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3548 * cells and one time. The caller is to delete this field using decrRef() as
3549 * it is no more needed.
3550 * \throw If the nodal connectivity of cells is not defined.
3551 * \throw If the coordinates array is not set.
3552 * \throw If \a this->getMeshDimension() != 1.
3553 * \throw If \a this mesh includes cells of type other than SEG2.
3555 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3557 if(getMeshDimension()!=1)
3558 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3559 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3560 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3561 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3562 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3563 int nbOfCells=getNumberOfCells();
3564 int spaceDim=getSpaceDimension();
3565 array->alloc(nbOfCells,spaceDim);
3566 double *pt=array->getPointer();
3567 const double *coo=getCoords()->getConstPointer();
3568 std::vector<int> conn;
3570 for(int i=0;i<nbOfCells;i++)
3573 getNodeIdsOfCell(i,conn);
3574 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3576 ret->setArray(array);
3578 ret->synchronizeTimeWithSupport();
3583 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3584 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3585 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3586 * from. If a result face is shared by two 3D cells, then the face in included twice in
3588 * \param [in] origin - 3 components of a point defining location of the plane.
3589 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3590 * must be greater than 1e-6.
3591 * \param [in] eps - half-thickness of the plane.
3592 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3593 * producing correspondent 2D cells. The caller is to delete this array
3594 * using decrRef() as it is no more needed.
3595 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3596 * not share the node coordinates array with \a this mesh. The caller is to
3597 * delete this mesh using decrRef() as it is no more needed.
3598 * \throw If the coordinates array is not set.
3599 * \throw If the nodal connectivity of cells is not defined.
3600 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3601 * \throw If magnitude of \a vec is less than 1e-6.
3602 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3603 * \throw If \a this includes quadratic cells.
3605 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3607 checkFullyDefined();
3608 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3609 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3610 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3611 if(candidates->empty())
3612 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3613 std::vector<int> nodes;
3614 DataArrayInt *cellIds1D=0;
3615 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3616 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3617 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3618 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3619 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3620 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3621 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3622 revDesc2=0; revDescIndx2=0;
3623 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3624 revDesc1=0; revDescIndx1=0;
3625 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3626 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3628 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3629 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3631 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3632 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3633 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3634 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3635 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3636 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3637 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3638 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3639 if(cellIds2->empty())
3640 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3641 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3642 ret->setCoords(mDesc1->getCoords());
3643 ret->setConnectivity(conn,connI,true);
3644 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3649 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3650 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
3651 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3653 * \param [in] origin - 3 components of a point defining location of the plane.
3654 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3655 * must be greater than 1e-6.
3656 * \param [in] eps - half-thickness of the plane.
3657 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3658 * producing correspondent segments. The caller is to delete this array
3659 * using decrRef() as it is no more needed.
3660 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3661 * mesh in 3D space. This mesh does not share the node coordinates array with
3662 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3664 * \throw If the coordinates array is not set.
3665 * \throw If the nodal connectivity of cells is not defined.
3666 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3667 * \throw If magnitude of \a vec is less than 1e-6.
3668 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3669 * \throw If \a this includes quadratic cells.
3671 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3673 checkFullyDefined();
3674 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3675 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3676 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3677 if(candidates->empty())
3678 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3679 std::vector<int> nodes;
3680 DataArrayInt *cellIds1D=0;
3681 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3682 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3683 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3684 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3685 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3686 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3687 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3688 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3689 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3691 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3692 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3694 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3695 int ncellsSub=subMesh->getNumberOfCells();
3696 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3697 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3698 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3699 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3700 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3702 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3703 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3704 for(int i=0;i<ncellsSub;i++)
3706 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3708 if(cut3DSurf[i].first!=-2)
3710 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3711 connI->pushBackSilent(conn->getNumberOfTuples());
3712 cellIds2->pushBackSilent(i);
3716 int cellId3DSurf=cut3DSurf[i].second;
3717 int offset=nodalI[cellId3DSurf]+1;
3718 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3719 for(int j=0;j<nbOfEdges;j++)
3721 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3722 connI->pushBackSilent(conn->getNumberOfTuples());
3723 cellIds2->pushBackSilent(cellId3DSurf);
3728 if(cellIds2->empty())
3729 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3730 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3731 ret->setCoords(mDesc1->getCoords());
3732 ret->setConnectivity(conn,connI,true);
3733 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3738 * Finds cells whose bounding boxes intersect a given plane.
3739 * \param [in] origin - 3 components of a point defining location of the plane.
3740 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3741 * must be greater than 1e-6.
3742 * \param [in] eps - half-thickness of the plane.
3743 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3744 * cells. The caller is to delete this array using decrRef() as it is no more
3746 * \throw If the coordinates array is not set.
3747 * \throw If the nodal connectivity of cells is not defined.
3748 * \throw If \a this->getSpaceDimension() != 3.
3749 * \throw If magnitude of \a vec is less than 1e-6.
3750 * \sa buildSlice3D()
3752 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3754 checkFullyDefined();
3755 if(getSpaceDimension()!=3)
3756 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3757 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3759 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3761 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3762 double angle=acos(vec[2]/normm);
3763 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3767 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3768 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3769 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3771 mw->getBoundingBox(bbox);
3772 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3773 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3777 getBoundingBox(bbox);
3778 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3779 cellIds=getCellsInBoundingBox(bbox,eps);
3781 return cellIds.retn();
3785 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3786 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3787 * No consideration of coordinate is done by this method.
3788 * 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)
3789 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3791 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3793 if(getMeshDimension()!=1)
3794 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3795 int nbCells=getNumberOfCells();
3797 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3798 const int *connI=_nodal_connec_index->getConstPointer();
3799 const int *conn=_nodal_connec->getConstPointer();
3800 int ref=conn[connI[0]+2];
3801 for(int i=1;i<nbCells;i++)
3803 if(conn[connI[i]+1]!=ref)
3805 ref=conn[connI[i]+2];
3811 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3812 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3813 * \param pt reference point of the line
3814 * \param v normalized director vector of the line
3815 * \param eps max precision before throwing an exception
3816 * \param res output of size this->getNumberOfCells
3818 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3820 if(getMeshDimension()!=1)
3821 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3822 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3823 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3824 if(getSpaceDimension()!=3)
3825 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3826 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3827 const double *fPtr=f->getArray()->getConstPointer();
3829 for(int i=0;i<getNumberOfCells();i++)
3831 const double *tmp1=fPtr+3*i;
3832 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3833 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3834 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3835 double n1=INTERP_KERNEL::norm<3>(tmp);
3836 n1/=INTERP_KERNEL::norm<3>(tmp1);
3838 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3840 const double *coo=getCoords()->getConstPointer();
3841 for(int i=0;i<getNumberOfNodes();i++)
3843 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3844 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3845 res[i]=std::accumulate(tmp,tmp+3,0.);
3850 * 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.
3851 * \a this is expected to be a mesh so that its space dimension is equal to its
3852 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3853 * 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).
3855 * 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
3856 * 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).
3857 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3859 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3860 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3862 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3863 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3864 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3865 * \return the positive value of the distance.
3866 * \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
3868 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3870 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
3872 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3873 if(meshDim!=spaceDim-1)
3874 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3875 if(meshDim!=2 && meshDim!=1)
3876 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3877 checkFullyDefined();
3878 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3879 { 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()); }
3880 DataArrayInt *ret1=0;
3881 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3882 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3883 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3884 cellId=*ret1Safe->begin();
3885 return *ret0->begin();
3889 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3890 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
3891 * 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
3892 * 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).
3893 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3895 * \a this is expected to be a mesh so that its space dimension is equal to its
3896 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3897 * 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).
3899 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3900 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3902 * \param [in] pts the list of points in which each tuple represents a point
3903 * \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.
3904 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3905 * \throw if number of components of \a pts is not equal to the space dimension.
3906 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3907 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3909 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
3912 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3913 pts->checkAllocated();
3914 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3915 if(meshDim!=spaceDim-1)
3916 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3917 if(meshDim!=2 && meshDim!=1)
3918 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3919 if(pts->getNumberOfComponents()!=spaceDim)
3921 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3922 throw INTERP_KERNEL::Exception(oss.str().c_str());
3924 checkFullyDefined();
3925 int nbCells=getNumberOfCells();
3927 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3928 int nbOfPts=pts->getNumberOfTuples();
3929 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3930 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3931 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3932 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3933 std::vector<double> bbox;
3934 getBoundingBoxForBBTree(bbox);
3939 BBTreeDst<3> myTree(&bbox[0],0,0,nbCells);
3940 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3942 double x=std::numeric_limits<double>::max();
3943 std::vector<int> elems;
3944 myTree.getMinDistanceOfMax(ptsPtr,x);
3945 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3946 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3952 BBTreeDst<2> myTree(&bbox[0],0,0,nbCells);
3953 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3955 double x=std::numeric_limits<double>::max();
3956 std::vector<int> elems;
3957 myTree.getMinDistanceOfMax(ptsPtr,x);
3958 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3959 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3964 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3966 cellIds=ret1.retn();
3971 * \param [in] pt the start pointer (included) of the coordinates of the point
3972 * \param [in] cellIdsBg the start pointer (included) of cellIds
3973 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3974 * \param [in] nc nodal connectivity
3975 * \param [in] ncI nodal connectivity index
3976 * \param [in,out] ret0 the min distance between \a this and the external input point
3977 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3978 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3980 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) throw(INTERP_KERNEL::Exception)
3983 ret0=std::numeric_limits<double>::max();
3984 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3986 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3988 case INTERP_KERNEL::NORM_TRI3:
3990 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3992 { ret0=tmp; cellId=*zeCell; }
3995 case INTERP_KERNEL::NORM_QUAD4:
3996 case INTERP_KERNEL::NORM_POLYGON:
3998 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
4000 { ret0=tmp; cellId=*zeCell; }
4004 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
4010 * \param [in] pt the start pointer (included) of the coordinates of the point
4011 * \param [in] cellIdsBg the start pointer (included) of cellIds
4012 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
4013 * \param [in] nc nodal connectivity
4014 * \param [in] ncI nodal connectivity index
4015 * \param [in,out] ret0 the min distance between \a this and the external input point
4016 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
4017 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
4019 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) throw(INTERP_KERNEL::Exception)
4022 ret0=std::numeric_limits<double>::max();
4023 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
4025 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
4027 case INTERP_KERNEL::NORM_SEG2:
4029 std::size_t uselessEntry=0;
4030 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
4033 { ret0=tmp; cellId=*zeCell; }
4037 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
4043 * Finds cells in contact with a ball (i.e. a point with precision).
4044 * \warning This method is suitable if the caller intends to evaluate only one
4045 * point, for more points getCellsContainingPoints() is recommended as it is
4047 * \param [in] pos - array of coordinates of the ball central point.
4048 * \param [in] eps - ball radius.
4049 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4050 * if there are no such cells.
4051 * \throw If the coordinates array is not set.
4052 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4054 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4056 std::vector<int> elts;
4057 getCellsContainingPoint(pos,eps,elts);
4060 return elts.front();
4064 * Finds cells in contact with a ball (i.e. a point with precision).
4065 * \warning This method is suitable if the caller intends to evaluate only one
4066 * point, for more points getCellsContainingPoints() is recommended as it is
4068 * \param [in] pos - array of coordinates of the ball central point.
4069 * \param [in] eps - ball radius.
4070 * \param [in,out] elts - vector returning ids of the found cells. It is cleared
4071 * before inserting ids.
4072 * \throw If the coordinates array is not set.
4073 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4075 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4076 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4078 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4080 std::vector<int> eltsIndex;
4081 getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
4086 namespace ParaMEDMEM
4088 template<const int SPACEDIMM>
4092 static const int MY_SPACEDIM=SPACEDIMM;
4093 static const int MY_MESHDIM=8;
4094 typedef int MyConnType;
4095 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4097 // useless, but for windows compilation ...
4098 const double* getCoordinatesPtr() const { return 0; }
4099 const int* getConnectivityPtr() const { return 0; }
4100 const int* getConnectivityIndexPtr() const { return 0; }
4101 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4105 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4107 INTERP_KERNEL::Edge *ret=0;
4110 case INTERP_KERNEL::NORM_SEG2:
4112 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4115 case INTERP_KERNEL::NORM_SEG3:
4117 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4118 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4119 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4120 bool colinearity=inters.areColinears();
4121 delete e1; delete e2;
4123 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4125 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4126 mapp2[bg[2]].second=false;
4130 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4136 * This method creates a sub mesh in Geometric2D DS. The sub mesh is composed be the sub set of cells in 'candidates' and the global mesh 'mDesc'.
4137 * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4138 * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4140 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4143 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.
4144 const double *coo=mDesc->getCoords()->getConstPointer();
4145 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4146 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4148 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4149 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4150 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4152 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4153 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4155 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4156 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4158 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4159 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4161 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4163 if((*it2).second.second)
4164 mapp[(*it2).second.first]=(*it2).first;
4165 ((*it2).second.first)->decrRef();
4170 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4174 int locId=nodeId-offset2;
4175 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4179 int locId=nodeId-offset1;
4180 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4182 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4185 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4186 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4187 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4189 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4191 int eltId1=abs(*desc1)-1;
4192 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4194 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4195 if(it==mappRev.end())
4197 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4208 template<int SPACEDIM>
4209 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4210 double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4212 std::vector<double> bbox;
4213 eltsIndex.resize(nbOfPoints+1);
4216 getBoundingBoxForBBTree(bbox);
4217 int nbOfCells=getNumberOfCells();
4218 const int *conn=_nodal_connec->getConstPointer();
4219 const int *connI=_nodal_connec_index->getConstPointer();
4220 double bb[2*SPACEDIM];
4221 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4222 for(int i=0;i<nbOfPoints;i++)
4224 eltsIndex[i+1]=eltsIndex[i];
4225 for(int j=0;j<SPACEDIM;j++)
4227 bb[2*j]=pos[SPACEDIM*i+j];
4228 bb[2*j+1]=pos[SPACEDIM*i+j];
4230 std::vector<int> candidates;
4231 myTree.getIntersectingElems(bb,candidates);
4232 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4234 int sz=connI[(*iter)+1]-connI[*iter]-1;
4235 if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4236 (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4237 coords,conn+connI[*iter]+1,sz,eps))
4240 elts.push_back(*iter);
4246 * Finds cells in contact with several balls (i.e. points with precision).
4247 * This method is an extension of getCellContainingPoint() and
4248 * getCellsContainingPoint() for the case of multiple points.
4249 * \param [in] pos - an array of coordinates of points in full interlace mode :
4250 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4251 * this->getSpaceDimension() * \a nbOfPoints
4252 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4253 * \param [in] eps - radius of balls (i.e. the precision).
4254 * \param [in,out] elts - vector returning ids of found cells.
4255 * \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4256 * dividing cell ids in \a elts into groups each referring to one
4257 * point. Its every element (except the last one) is an index pointing to the
4258 * first id of a group of cells. For example cells in contact with the *i*-th
4259 * point are described by following range of indices:
4260 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4261 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4262 * Number of cells in contact with the *i*-th point is
4263 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4264 * \throw If the coordinates array is not set.
4265 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4267 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4268 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4270 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4271 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4273 int spaceDim=getSpaceDimension();
4274 int mDim=getMeshDimension();
4279 const double *coords=_coords->getConstPointer();
4280 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4287 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4289 else if(spaceDim==2)
4293 const double *coords=_coords->getConstPointer();
4294 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4297 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4299 else if(spaceDim==1)
4303 const double *coords=_coords->getConstPointer();
4304 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4307 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4310 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4314 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4315 * least two its edges intersect each other anywhere except their extremities. An
4316 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4317 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4318 * cleared before filling in.
4319 * \param [in] eps - precision.
4320 * \throw If \a this->getMeshDimension() != 2.
4321 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4323 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4325 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4326 if(getMeshDimension()!=2)
4327 throw INTERP_KERNEL::Exception(msg);
4328 int spaceDim=getSpaceDimension();
4329 if(spaceDim!=2 && spaceDim!=3)
4330 throw INTERP_KERNEL::Exception(msg);
4331 const int *conn=_nodal_connec->getConstPointer();
4332 const int *connI=_nodal_connec_index->getConstPointer();
4333 int nbOfCells=getNumberOfCells();
4334 std::vector<double> cell2DinS2;
4335 for(int i=0;i<nbOfCells;i++)
4337 int offset=connI[i];
4338 int nbOfNodesForCell=connI[i+1]-offset-1;
4339 if(nbOfNodesForCell<=3)
4341 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4342 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4343 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4350 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4352 * 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.
4353 * 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.
4355 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4356 * This convex envelop is computed using Jarvis march algorithm.
4357 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4358 * 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)
4359 * 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.
4361 * \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.
4363 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4365 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4366 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4367 checkFullyDefined();
4368 const double *coords=getCoords()->getConstPointer();
4369 int nbOfCells=getNumberOfCells();
4370 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4371 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4372 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4373 int *workIndexOut=nodalConnecIndexOut->getPointer();
4375 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4376 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4377 std::set<INTERP_KERNEL::NormalizedCellType> types;
4378 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4379 isChanged->alloc(0,1);
4380 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4382 int pos=nodalConnecOut->getNumberOfTuples();
4383 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4384 isChanged->pushBackSilent(i);
4385 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4386 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4388 if(isChanged->empty())
4390 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4392 return isChanged.retn();
4396 * This method is \b NOT const because it can modify \a this.
4397 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4398 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4399 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4400 * \b 1 for translation and rotation around point of 'mesh1D'.
4401 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4403 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4405 checkFullyDefined();
4406 mesh1D->checkFullyDefined();
4407 if(!mesh1D->isContiguous1D())
4408 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4409 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4410 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4411 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4412 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4413 if(mesh1D->getMeshDimension()!=1)
4414 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4416 if(isPresenceOfQuadratic())
4418 if(mesh1D->isFullyQuadratic())
4421 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4424 int oldNbOfNodes=getNumberOfNodes();
4425 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4430 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4435 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4439 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4441 setCoords(newCoords);
4442 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4448 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4449 * If it is not the case an exception will be thrown.
4450 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4451 * intersection of plane defined by ('origin','vec').
4452 * This method has one in/out parameter : 'cut3DCurve'.
4453 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4454 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4455 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4456 * This method will throw an exception if \a this contains a non linear segment.
4458 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4460 checkFullyDefined();
4461 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4462 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4463 int ncells=getNumberOfCells();
4464 int nnodes=getNumberOfNodes();
4465 double vec2[3],vec3[3],vec4[3];
4466 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4468 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4469 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4470 const int *conn=_nodal_connec->getConstPointer();
4471 const int *connI=_nodal_connec_index->getConstPointer();
4472 const double *coo=_coords->getConstPointer();
4473 std::vector<double> addCoo;
4474 for(int i=0;i<ncells;i++)
4476 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4478 if(cut3DCurve[i]==-2)
4480 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4481 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];
4482 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4483 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4484 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4486 const double *st2=coo+3*st;
4487 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4488 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]));
4489 if(pos>eps && pos<1-eps)
4491 int nNode=((int)addCoo.size())/3;
4492 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4493 addCoo.insert(addCoo.end(),vec4,vec4+3);
4494 cut3DCurve[i]=nnodes+nNode;
4500 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4504 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4505 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4506 coo2->alloc(newNbOfNodes,3);
4507 double *tmp=coo2->getPointer();
4508 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4509 std::copy(addCoo.begin(),addCoo.end(),tmp);
4510 DataArrayDouble::SetArrayIn(coo2,_coords);
4515 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4516 * \param mesh1D is the input 1D mesh used for translation computation.
4517 * \return newCoords new coords filled by this method.
4519 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4521 int oldNbOfNodes=getNumberOfNodes();
4522 int nbOf1DCells=mesh1D->getNumberOfCells();
4523 int spaceDim=getSpaceDimension();
4524 DataArrayDouble *ret=DataArrayDouble::New();
4525 std::vector<bool> isQuads;
4526 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4527 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4528 double *retPtr=ret->getPointer();
4529 const double *coords=getCoords()->getConstPointer();
4530 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4532 std::vector<double> c;
4536 for(int i=0;i<nbOf1DCells;i++)
4539 mesh1D->getNodeIdsOfCell(i,v);
4541 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4542 mesh1D->getCoordinatesOfNode(v[0],c);
4543 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4544 for(int j=0;j<oldNbOfNodes;j++)
4545 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4549 mesh1D->getCoordinatesOfNode(v[1],c);
4550 mesh1D->getCoordinatesOfNode(v[0],c);
4551 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4552 for(int j=0;j<oldNbOfNodes;j++)
4553 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4556 ret->copyStringInfoFrom(*getCoords());
4561 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4562 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4563 * \return newCoords new coords filled by this method.
4565 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4567 if(mesh1D->getSpaceDimension()==2)
4568 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4569 if(mesh1D->getSpaceDimension()==3)
4570 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4571 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4575 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4576 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4577 * \return newCoords new coords filled by this method.
4579 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4582 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4583 int oldNbOfNodes=getNumberOfNodes();
4584 int nbOf1DCells=mesh1D->getNumberOfCells();
4586 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4587 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4588 int nbOfLevsInVec=nbOf1DCells+1;
4589 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4590 double *retPtr=ret->getPointer();
4591 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4592 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4593 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4594 tmp->setCoords(tmp2);
4595 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4596 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4597 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4598 for(int i=1;i<nbOfLevsInVec;i++)
4600 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4601 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4602 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4603 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4604 tmp->translate(vec);
4605 double tmp3[2],radius,alpha,alpha0;
4606 const double *p0=i+1<nbOfLevsInVec?begin:third;
4607 const double *p1=i+1<nbOfLevsInVec?end:begin;
4608 const double *p2=i+1<nbOfLevsInVec?third:end;
4609 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4610 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]);
4611 double angle=acos(cosangle/(radius*radius));
4612 tmp->rotate(end,0,angle);
4613 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4619 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4620 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4621 * \return newCoords new coords filled by this method.
4623 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4626 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4627 int oldNbOfNodes=getNumberOfNodes();
4628 int nbOf1DCells=mesh1D->getNumberOfCells();
4630 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4631 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4632 int nbOfLevsInVec=nbOf1DCells+1;
4633 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4634 double *retPtr=ret->getPointer();
4635 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4636 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4637 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4638 tmp->setCoords(tmp2);
4639 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4640 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4641 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4642 for(int i=1;i<nbOfLevsInVec;i++)
4644 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4645 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4646 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4647 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4648 tmp->translate(vec);
4649 double tmp3[2],radius,alpha,alpha0;
4650 const double *p0=i+1<nbOfLevsInVec?begin:third;
4651 const double *p1=i+1<nbOfLevsInVec?end:begin;
4652 const double *p2=i+1<nbOfLevsInVec?third:end;
4653 double vecPlane[3]={
4654 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4655 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4656 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4658 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4661 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4662 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4663 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4665 double c2=cos(asin(s2));
4667 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4668 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4669 {-vec2[1]*s2, vec2[0]*s2, c2}
4671 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]};
4672 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]};
4673 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]};
4674 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4675 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]);
4676 double angle=acos(cosangle/(radius*radius));
4677 tmp->rotate(end,vecPlane,angle);
4680 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4686 * This method is private because not easy to use for end user. This method is const contrary to
4687 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4688 * the coords sorted slice by slice.
4689 * \param isQuad specifies presence of quadratic cells.
4691 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4693 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4694 int nbOf2DCells=getNumberOfCells();
4695 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4696 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4697 const int *conn=_nodal_connec->getConstPointer();
4698 const int *connI=_nodal_connec_index->getConstPointer();
4699 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4700 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4701 newConnI->alloc(nbOf3DCells+1,1);
4702 int *newConnIPtr=newConnI->getPointer();
4704 std::vector<int> newc;
4705 for(int j=0;j<nbOf2DCells;j++)
4707 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4708 *newConnIPtr++=(int)newc.size();
4710 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4711 int *newConnPtr=newConn->getPointer();
4712 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4713 newConnIPtr=newConnI->getPointer();
4714 for(int iz=0;iz<nbOf1DCells;iz++)
4717 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4718 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4720 int icell=(int)(iter-newc.begin());
4721 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4724 *newConnPtr=(*iter)+iz*deltaPerLev;
4729 *newConnPtr=(*iter);
4732 ret->setConnectivity(newConn,newConnI,true);
4733 ret->setCoords(getCoords());
4738 * Checks if \a this mesh is constituted by only quadratic cells.
4739 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4740 * \throw If the coordinates array is not set.
4741 * \throw If the nodal connectivity of cells is not defined.
4743 bool MEDCouplingUMesh::isFullyQuadratic() const
4745 checkFullyDefined();
4747 int nbOfCells=getNumberOfCells();
4748 for(int i=0;i<nbOfCells && ret;i++)
4750 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4751 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4752 ret=cm.isQuadratic();
4758 * Checks if \a this mesh includes any quadratic cell.
4759 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4760 * \throw If the coordinates array is not set.
4761 * \throw If the nodal connectivity of cells is not defined.
4763 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4765 checkFullyDefined();
4767 int nbOfCells=getNumberOfCells();
4768 for(int i=0;i<nbOfCells && !ret;i++)
4770 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4771 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4772 ret=cm.isQuadratic();
4778 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4779 * this mesh, it remains unchanged.
4780 * \throw If the coordinates array is not set.
4781 * \throw If the nodal connectivity of cells is not defined.
4783 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4785 checkFullyDefined();
4786 int nbOfCells=getNumberOfCells();
4788 const int *iciptr=_nodal_connec_index->getConstPointer();
4789 for(int i=0;i<nbOfCells;i++)
4791 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4792 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4793 if(cm.isQuadratic())
4795 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4796 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4797 if(!cml.isDynamic())
4798 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4800 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4805 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4806 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4807 const int *icptr=_nodal_connec->getConstPointer();
4808 newConn->alloc(getMeshLength()-delta,1);
4809 newConnI->alloc(nbOfCells+1,1);
4810 int *ocptr=newConn->getPointer();
4811 int *ociptr=newConnI->getPointer();
4814 for(int i=0;i<nbOfCells;i++,ociptr++)
4816 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4817 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4818 if(!cm.isQuadratic())
4820 _types.insert(type);
4821 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4822 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4826 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4827 _types.insert(typel);
4828 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4829 int newNbOfNodes=cml.getNumberOfNodes();
4831 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4832 *ocptr++=(int)typel;
4833 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4834 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4837 setConnectivity(newConn,newConnI,false);
4841 * This method converts all linear cell in \a this to quadratic one.
4842 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4843 * 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)
4844 * 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.
4845 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4846 * end of the existing coordinates.
4848 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4849 * corresponding quadratic cells. 1 is those creating the 'most' complex.
4850 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4852 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4854 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4856 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4858 DataArrayInt *conn=0,*connI=0;
4859 DataArrayDouble *coords=0;
4860 std::set<INTERP_KERNEL::NormalizedCellType> types;
4861 checkFullyDefined();
4862 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4863 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4864 int meshDim=getMeshDimension();
4865 switch(conversionType)
4871 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4872 connSafe=conn; connISafe=connI; coordsSafe=coords;
4875 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4876 connSafe=conn; connISafe=connI; coordsSafe=coords;
4879 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4880 connSafe=conn; connISafe=connI; coordsSafe=coords;
4883 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4891 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4892 connSafe=conn; connISafe=connI; coordsSafe=coords;
4895 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4896 connSafe=conn; connISafe=connI; coordsSafe=coords;
4899 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4900 connSafe=conn; connISafe=connI; coordsSafe=coords;
4903 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4908 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4910 setConnectivity(connSafe,connISafe,false);
4912 setCoords(coordsSafe);
4917 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4918 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4919 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4921 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4923 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4924 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4925 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4926 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4927 int nbOfCells=getNumberOfCells();
4928 int nbOfNodes=getNumberOfNodes();
4929 const int *cPtr=_nodal_connec->getConstPointer();
4930 const int *icPtr=_nodal_connec_index->getConstPointer();
4931 int lastVal=0,offset=nbOfNodes;
4932 for(int i=0;i<nbOfCells;i++,icPtr++)
4934 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4935 if(type==INTERP_KERNEL::NORM_SEG2)
4937 types.insert(INTERP_KERNEL::NORM_SEG3);
4938 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4939 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4940 newConn->pushBackSilent(offset++);
4942 newConnI->pushBackSilent(lastVal);
4943 ret->pushBackSilent(i);
4948 lastVal+=(icPtr[1]-icPtr[0]);
4949 newConnI->pushBackSilent(lastVal);
4950 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4953 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4954 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4958 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 throw(INTERP_KERNEL::Exception)
4960 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4961 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4962 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4964 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4965 DataArrayInt *conn1D=0,*conn1DI=0;
4966 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4967 DataArrayDouble *coordsTmp=0;
4968 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4969 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4970 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4971 const int *c1DPtr=conn1D->begin();
4972 const int *c1DIPtr=conn1DI->begin();
4973 int nbOfCells=getNumberOfCells();
4974 const int *cPtr=_nodal_connec->getConstPointer();
4975 const int *icPtr=_nodal_connec_index->getConstPointer();
4977 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4979 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4980 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4981 if(!cm.isQuadratic())
4983 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4984 types.insert(typ2); newConn->pushBackSilent(typ2);
4985 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4986 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4987 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4988 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4989 newConnI->pushBackSilent(lastVal);
4990 ret->pushBackSilent(i);
4995 lastVal+=(icPtr[1]-icPtr[0]);
4996 newConnI->pushBackSilent(lastVal);
4997 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5000 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
5005 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5006 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5007 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5009 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5012 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5013 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5014 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5017 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5019 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5020 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
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);
5026 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5027 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
5028 DataArrayInt *conn1D=0,*conn1DI=0;
5029 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
5030 DataArrayDouble *coordsTmp=0;
5031 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
5032 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5033 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5034 const int *c1DPtr=conn1D->begin();
5035 const int *c1DIPtr=conn1DI->begin();
5036 int nbOfCells=getNumberOfCells();
5037 const int *cPtr=_nodal_connec->getConstPointer();
5038 const int *icPtr=_nodal_connec_index->getConstPointer();
5039 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5040 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
5042 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5043 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5044 if(!cm.isQuadratic())
5046 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5047 types.insert(typ2); newConn->pushBackSilent(typ2);
5048 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5049 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5050 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5051 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5052 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5053 newConnI->pushBackSilent(lastVal);
5054 ret->pushBackSilent(i);
5059 lastVal+=(icPtr[1]-icPtr[0]);
5060 newConnI->pushBackSilent(lastVal);
5061 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5064 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5065 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5070 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5071 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5072 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5074 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5076 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5077 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5078 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5081 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5083 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5084 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5085 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5086 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5088 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5089 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5090 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5092 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5093 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5094 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5095 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5096 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5097 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5098 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5099 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5100 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5101 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5102 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5103 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5104 int nbOfCells=getNumberOfCells();
5105 const int *cPtr=_nodal_connec->getConstPointer();
5106 const int *icPtr=_nodal_connec_index->getConstPointer();
5107 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5108 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5110 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5111 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5112 if(!cm.isQuadratic())
5114 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5115 if(typ2==INTERP_KERNEL::NORM_ERROR)
5117 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5118 throw INTERP_KERNEL::Exception(oss.str().c_str());
5120 types.insert(typ2); newConn->pushBackSilent(typ2);
5121 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5122 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5123 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5124 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5126 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5127 int tmpPos=newConn->getNumberOfTuples();
5128 newConn->pushBackSilent(nodeId2);
5129 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5131 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5132 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5133 newConnI->pushBackSilent(lastVal);
5134 ret->pushBackSilent(i);
5139 lastVal+=(icPtr[1]-icPtr[0]);
5140 newConnI->pushBackSilent(lastVal);
5141 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5144 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5145 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5146 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5147 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5148 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5149 int *c=newConn->getPointer();
5150 const int *cI(newConnI->begin());
5151 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5152 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5153 offset=coordsTmp2Safe->getNumberOfTuples();
5154 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5155 c[cI[(*elt)+1]-1]+=offset;
5156 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5161 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5162 * so that the number of cells remains the same. Quadratic faces are converted to
5163 * polygons. This method works only for 2D meshes in
5164 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5165 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5166 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5167 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5168 * a polylinized edge constituting the input polygon.
5169 * \throw If the coordinates array is not set.
5170 * \throw If the nodal connectivity of cells is not defined.
5171 * \throw If \a this->getMeshDimension() != 2.
5172 * \throw If \a this->getSpaceDimension() != 2.
5174 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5176 checkFullyDefined();
5177 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5178 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5179 double epsa=fabs(eps);
5180 if(epsa<std::numeric_limits<double>::min())
5181 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 !");
5182 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5183 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5184 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5185 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5186 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5187 revDesc1=0; revDescIndx1=0;
5188 mDesc->tessellate2DCurve(eps);
5189 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5190 setCoords(mDesc->getCoords());
5194 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5195 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5196 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5197 * a sub-divided edge.
5198 * \throw If the coordinates array is not set.
5199 * \throw If the nodal connectivity of cells is not defined.
5200 * \throw If \a this->getMeshDimension() != 1.
5201 * \throw If \a this->getSpaceDimension() != 2.
5203 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5205 checkFullyDefined();
5206 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5207 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5208 double epsa=fabs(eps);
5209 if(epsa<std::numeric_limits<double>::min())
5210 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 !");
5211 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5212 int nbCells=getNumberOfCells();
5213 int nbNodes=getNumberOfNodes();
5214 const int *conn=_nodal_connec->getConstPointer();
5215 const int *connI=_nodal_connec_index->getConstPointer();
5216 const double *coords=_coords->getConstPointer();
5217 std::vector<double> addCoo;
5218 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5219 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5220 newConnI->alloc(nbCells+1,1);
5221 int *newConnIPtr=newConnI->getPointer();
5224 INTERP_KERNEL::Node *tmp2[3];
5225 std::set<INTERP_KERNEL::NormalizedCellType> types;
5226 for(int i=0;i<nbCells;i++,newConnIPtr++)
5228 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5229 if(cm.isQuadratic())
5230 {//assert(connI[i+1]-connI[i]-1==3)
5231 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5232 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5233 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5234 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5235 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5238 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5239 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5241 newConnIPtr[1]=(int)newConn.size();
5245 types.insert(INTERP_KERNEL::NORM_SEG2);
5246 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5247 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5248 newConnIPtr[1]=newConnIPtr[0]+3;
5253 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5254 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5255 newConnIPtr[1]=newConnIPtr[0]+3;
5258 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5261 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5262 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5263 newConnArr->alloc((int)newConn.size(),1);
5264 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5265 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5266 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5267 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5268 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5269 std::copy(addCoo.begin(),addCoo.end(),work);
5270 DataArrayDouble::SetArrayIn(newCoords,_coords);
5275 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5276 * In addition, returns an array mapping new cells to old ones. <br>
5277 * This method typically increases the number of cells in \a this mesh
5278 * but the number of nodes remains \b unchanged.
5279 * That's why the 3D splitting policies
5280 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5281 * \param [in] policy - specifies a pattern used for splitting.
5282 * The semantic of \a policy is:
5283 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5284 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5285 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5286 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5287 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5288 * an id of old cell producing it. The caller is to delete this array using
5289 * decrRef() as it is no more needed.
5290 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5291 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5292 * and \a this->getMeshDimension() != 3.
5293 * \throw If \a policy is not one of the four discussed above.
5294 * \throw If the nodal connectivity of cells is not defined.
5296 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5301 return simplexizePol0();
5303 return simplexizePol1();
5304 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5305 return simplexizePlanarFace5();
5306 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5307 return simplexizePlanarFace6();
5309 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)");
5314 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5315 * - 1D: INTERP_KERNEL::NORM_SEG2
5316 * - 2D: INTERP_KERNEL::NORM_TRI3
5317 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5319 * This method is useful for users that need to use P1 field services as
5320 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5321 * All these methods need mesh support containing only simplex cells.
5322 * \return bool - \c true if there are only simplex cells in \a this mesh.
5323 * \throw If the coordinates array is not set.
5324 * \throw If the nodal connectivity of cells is not defined.
5325 * \throw If \a this->getMeshDimension() < 1.
5327 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5329 checkFullyDefined();
5330 int mdim=getMeshDimension();
5331 if(mdim<1 || mdim>3)
5332 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5333 int nbCells=getNumberOfCells();
5334 const int *conn=_nodal_connec->getConstPointer();
5335 const int *connI=_nodal_connec_index->getConstPointer();
5336 for(int i=0;i<nbCells;i++)
5338 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5346 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5348 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5350 checkConnectivityFullyDefined();
5351 if(getMeshDimension()!=2)
5352 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5353 int nbOfCells=getNumberOfCells();
5354 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5355 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5356 ret->alloc(nbOfCells+nbOfCutCells,1);
5357 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5358 int *retPt=ret->getPointer();
5359 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5360 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5361 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5362 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5363 int *pt=newConn->getPointer();
5364 int *ptI=newConnI->getPointer();
5366 const int *oldc=_nodal_connec->getConstPointer();
5367 const int *ci=_nodal_connec_index->getConstPointer();
5368 for(int i=0;i<nbOfCells;i++,ci++)
5370 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5372 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5373 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5374 pt=std::copy(tmp,tmp+8,pt);
5383 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5384 ptI[1]=ptI[0]+ci[1]-ci[0];
5389 _nodal_connec->decrRef();
5390 _nodal_connec=newConn.retn();
5391 _nodal_connec_index->decrRef();
5392 _nodal_connec_index=newConnI.retn();
5399 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5401 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5403 checkConnectivityFullyDefined();
5404 if(getMeshDimension()!=2)
5405 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5406 int nbOfCells=getNumberOfCells();
5407 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5408 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5409 ret->alloc(nbOfCells+nbOfCutCells,1);
5410 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5411 int *retPt=ret->getPointer();
5412 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5413 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5414 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5415 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5416 int *pt=newConn->getPointer();
5417 int *ptI=newConnI->getPointer();
5419 const int *oldc=_nodal_connec->getConstPointer();
5420 const int *ci=_nodal_connec_index->getConstPointer();
5421 for(int i=0;i<nbOfCells;i++,ci++)
5423 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5425 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5426 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5427 pt=std::copy(tmp,tmp+8,pt);
5436 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5437 ptI[1]=ptI[0]+ci[1]-ci[0];
5442 _nodal_connec->decrRef();
5443 _nodal_connec=newConn.retn();
5444 _nodal_connec_index->decrRef();
5445 _nodal_connec_index=newConnI.retn();
5452 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5454 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5456 checkConnectivityFullyDefined();
5457 if(getMeshDimension()!=3)
5458 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5459 int nbOfCells=getNumberOfCells();
5460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5461 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5462 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5463 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5464 int *retPt=ret->getPointer();
5465 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5466 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5467 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5468 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5469 int *pt=newConn->getPointer();
5470 int *ptI=newConnI->getPointer();
5472 const int *oldc=_nodal_connec->getConstPointer();
5473 const int *ci=_nodal_connec_index->getConstPointer();
5474 for(int i=0;i<nbOfCells;i++,ci++)
5476 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5478 for(int j=0;j<5;j++,pt+=5,ptI++)
5480 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5481 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];
5488 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5489 ptI[1]=ptI[0]+ci[1]-ci[0];
5494 _nodal_connec->decrRef();
5495 _nodal_connec=newConn.retn();
5496 _nodal_connec_index->decrRef();
5497 _nodal_connec_index=newConnI.retn();
5504 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5506 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5508 checkConnectivityFullyDefined();
5509 if(getMeshDimension()!=3)
5510 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5511 int nbOfCells=getNumberOfCells();
5512 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5513 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5514 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5515 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5516 int *retPt=ret->getPointer();
5517 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5518 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5519 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5520 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5521 int *pt=newConn->getPointer();
5522 int *ptI=newConnI->getPointer();
5524 const int *oldc=_nodal_connec->getConstPointer();
5525 const int *ci=_nodal_connec_index->getConstPointer();
5526 for(int i=0;i<nbOfCells;i++,ci++)
5528 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5530 for(int j=0;j<6;j++,pt+=5,ptI++)
5532 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5533 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];
5540 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5541 ptI[1]=ptI[0]+ci[1]-ci[0];
5546 _nodal_connec->decrRef();
5547 _nodal_connec=newConn.retn();
5548 _nodal_connec_index->decrRef();
5549 _nodal_connec_index=newConnI.retn();
5556 * 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.
5557 * This method completly ignore coordinates.
5558 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5559 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5560 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5561 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5563 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5565 checkFullyDefined();
5566 if(getMeshDimension()!=2)
5567 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5568 int nbOfCells=getNumberOfCells();
5569 int *connI=_nodal_connec_index->getPointer();
5571 for(int i=0;i<nbOfCells;i++,connI++)
5573 int offset=descIndex[i];
5574 int nbOfEdges=descIndex[i+1]-offset;
5576 bool ddirect=desc[offset+nbOfEdges-1]>0;
5577 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5578 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5579 for(int j=0;j<nbOfEdges;j++)
5581 bool direct=desc[offset+j]>0;
5582 int edgeId=std::abs(desc[offset+j])-1;
5583 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5585 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5586 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5587 int ref2=direct?id1:id2;
5590 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5591 newConnLgth+=nbOfSubNodes-1;
5596 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5597 throw INTERP_KERNEL::Exception(oss.str().c_str());
5602 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5605 newConnLgth++;//+1 is for cell type
5606 connI[1]=newConnLgth;
5609 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5610 newConn->alloc(newConnLgth,1);
5611 int *work=newConn->getPointer();
5612 for(int i=0;i<nbOfCells;i++)
5614 *work++=INTERP_KERNEL::NORM_POLYGON;
5615 int offset=descIndex[i];
5616 int nbOfEdges=descIndex[i+1]-offset;
5617 for(int j=0;j<nbOfEdges;j++)
5619 bool direct=desc[offset+j]>0;
5620 int edgeId=std::abs(desc[offset+j])-1;
5622 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5625 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5626 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5627 work=std::copy(it,it+nbOfSubNodes-1,work);
5631 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5634 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5638 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5639 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5640 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5641 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5642 * so it can be useful to call mergeNodes() before calling this method.
5643 * \throw If \a this->getMeshDimension() <= 1.
5644 * \throw If the coordinates array is not set.
5645 * \throw If the nodal connectivity of cells is not defined.
5647 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5649 checkFullyDefined();
5650 if(getMeshDimension()<=1)
5651 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5652 int nbOfCells=getNumberOfCells();
5655 int initMeshLgth=getMeshLength();
5656 int *conn=_nodal_connec->getPointer();
5657 int *index=_nodal_connec_index->getPointer();
5661 for(int i=0;i<nbOfCells;i++)
5663 lgthOfCurCell=index[i+1]-posOfCurCell;
5664 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5666 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5667 conn+newPos+1,newLgth);
5668 conn[newPos]=newType;
5670 posOfCurCell=index[i+1];
5673 if(newPos!=initMeshLgth)
5674 _nodal_connec->reAlloc(newPos);
5679 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5680 * A cell is considered to be oriented correctly if an angle between its
5681 * normal vector and a given vector is less than \c PI / \c 2.
5682 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5684 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5686 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5687 * is not cleared before filling in.
5688 * \throw If \a this->getMeshDimension() != 2.
5689 * \throw If \a this->getSpaceDimension() != 3.
5691 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5692 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5694 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5696 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5697 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5698 int nbOfCells=getNumberOfCells();
5699 const int *conn=_nodal_connec->getConstPointer();
5700 const int *connI=_nodal_connec_index->getConstPointer();
5701 const double *coordsPtr=_coords->getConstPointer();
5702 for(int i=0;i<nbOfCells;i++)
5704 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5705 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5707 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5708 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5715 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5716 * considered to be oriented correctly if an angle between its normal vector and a
5717 * given vector is less than \c PI / \c 2.
5718 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5720 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5722 * \throw If \a this->getMeshDimension() != 2.
5723 * \throw If \a this->getSpaceDimension() != 3.
5725 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5726 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5728 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5730 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5731 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5732 int nbOfCells=getNumberOfCells();
5733 int *conn=_nodal_connec->getPointer();
5734 const int *connI=_nodal_connec_index->getConstPointer();
5735 const double *coordsPtr=_coords->getConstPointer();
5736 bool isModified=false;
5737 for(int i=0;i<nbOfCells;i++)
5739 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5740 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5742 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5743 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5746 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5747 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5748 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5753 _nodal_connec->declareAsNew();
5758 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5759 * oriented facets. The normal vector of the facet should point out of the cell.
5760 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5761 * is not cleared before filling in.
5762 * \throw If \a this->getMeshDimension() != 3.
5763 * \throw If \a this->getSpaceDimension() != 3.
5764 * \throw If the coordinates array is not set.
5765 * \throw If the nodal connectivity of cells is not defined.
5767 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5768 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5770 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5772 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5773 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5774 int nbOfCells=getNumberOfCells();
5775 const int *conn=_nodal_connec->getConstPointer();
5776 const int *connI=_nodal_connec_index->getConstPointer();
5777 const double *coordsPtr=_coords->getConstPointer();
5778 for(int i=0;i<nbOfCells;i++)
5780 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5781 if(type==INTERP_KERNEL::NORM_POLYHED)
5783 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5790 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5792 * \throw If \a this->getMeshDimension() != 3.
5793 * \throw If \a this->getSpaceDimension() != 3.
5794 * \throw If the coordinates array is not set.
5795 * \throw If the nodal connectivity of cells is not defined.
5796 * \throw If the reparation fails.
5798 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5799 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5800 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5802 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5804 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5805 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5806 int nbOfCells=getNumberOfCells();
5807 int *conn=_nodal_connec->getPointer();
5808 const int *connI=_nodal_connec_index->getConstPointer();
5809 const double *coordsPtr=_coords->getConstPointer();
5810 for(int i=0;i<nbOfCells;i++)
5812 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5813 if(type==INTERP_KERNEL::NORM_POLYHED)
5817 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5818 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5820 catch(INTERP_KERNEL::Exception& e)
5822 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5823 throw INTERP_KERNEL::Exception(oss.str().c_str());
5831 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5832 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5833 * according to which the first facet of the cell should be oriented to have the normal vector
5834 * pointing out of cell.
5835 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5836 * cells. The caller is to delete this array using decrRef() as it is no more
5838 * \throw If \a this->getMeshDimension() != 3.
5839 * \throw If \a this->getSpaceDimension() != 3.
5840 * \throw If the coordinates array is not set.
5841 * \throw If the nodal connectivity of cells is not defined.
5843 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5844 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5845 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5847 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5849 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5850 if(getMeshDimension()!=3)
5851 throw INTERP_KERNEL::Exception(msg);
5852 int spaceDim=getSpaceDimension();
5854 throw INTERP_KERNEL::Exception(msg);
5856 int nbOfCells=getNumberOfCells();
5857 int *conn=_nodal_connec->getPointer();
5858 const int *connI=_nodal_connec_index->getConstPointer();
5859 const double *coo=getCoords()->getConstPointer();
5860 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5861 for(int i=0;i<nbOfCells;i++)
5863 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5864 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5866 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5868 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5869 cells->pushBackSilent(i);
5873 return cells.retn();
5877 * This method is a faster method to correct orientation of all 3D cells in \a this.
5878 * 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.
5879 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5881 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5882 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
5884 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5886 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5887 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5888 int nbOfCells=getNumberOfCells();
5889 int *conn=_nodal_connec->getPointer();
5890 const int *connI=_nodal_connec_index->getConstPointer();
5891 const double *coordsPtr=_coords->getConstPointer();
5892 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5893 for(int i=0;i<nbOfCells;i++)
5895 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5898 case INTERP_KERNEL::NORM_TETRA4:
5900 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5902 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5903 ret->pushBackSilent(i);
5907 case INTERP_KERNEL::NORM_PYRA5:
5909 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5911 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5912 ret->pushBackSilent(i);
5916 case INTERP_KERNEL::NORM_PENTA6:
5917 case INTERP_KERNEL::NORM_HEXA8:
5918 case INTERP_KERNEL::NORM_HEXGP12:
5920 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5922 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5923 ret->pushBackSilent(i);
5927 case INTERP_KERNEL::NORM_POLYHED:
5929 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5931 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5932 ret->pushBackSilent(i);
5937 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 !");
5945 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5946 * If it is not the case an exception will be thrown.
5947 * This method is fast because the first cell of \a this is used to compute the plane.
5948 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5949 * \param pos output of size at least 3 used to store a point owned of searched plane.
5951 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5953 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5954 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5955 const int *conn=_nodal_connec->getConstPointer();
5956 const int *connI=_nodal_connec_index->getConstPointer();
5957 const double *coordsPtr=_coords->getConstPointer();
5958 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5959 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5963 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5964 * cells. Currently cells of the following types are treated:
5965 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5966 * For a cell of other type an exception is thrown.
5967 * Space dimension of a 2D mesh can be either 2 or 3.
5968 * The Edge Ratio of a cell \f$t\f$ is:
5969 * \f$\frac{|t|_\infty}{|t|_0}\f$,
5970 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5971 * the smallest edge lengths of \f$t\f$.
5972 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5973 * cells and one time, lying on \a this mesh. The caller is to delete this
5974 * field using decrRef() as it is no more needed.
5975 * \throw If the coordinates array is not set.
5976 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5977 * \throw If the connectivity data array has more than one component.
5978 * \throw If the connectivity data array has a named component.
5979 * \throw If the connectivity index data array has more than one component.
5980 * \throw If the connectivity index data array has a named component.
5981 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
5982 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5983 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
5985 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5988 int spaceDim=getSpaceDimension();
5989 int meshDim=getMeshDimension();
5990 if(spaceDim!=2 && spaceDim!=3)
5991 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5992 if(meshDim!=2 && meshDim!=3)
5993 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5994 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5996 int nbOfCells=getNumberOfCells();
5997 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5998 arr->alloc(nbOfCells,1);
5999 double *pt=arr->getPointer();
6000 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6001 const int *conn=_nodal_connec->getConstPointer();
6002 const int *connI=_nodal_connec_index->getConstPointer();
6003 const double *coo=_coords->getConstPointer();
6005 for(int i=0;i<nbOfCells;i++,pt++)
6007 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6010 case INTERP_KERNEL::NORM_TRI3:
6012 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6013 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
6016 case INTERP_KERNEL::NORM_QUAD4:
6018 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6019 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
6022 case INTERP_KERNEL::NORM_TETRA4:
6024 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6025 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
6029 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6031 conn+=connI[i+1]-connI[i];
6033 ret->setName("EdgeRatio");
6034 ret->synchronizeTimeWithSupport();
6039 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
6040 * cells. Currently cells of the following types are treated:
6041 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
6042 * For a cell of other type an exception is thrown.
6043 * Space dimension of a 2D mesh can be either 2 or 3.
6044 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6045 * cells and one time, lying on \a this mesh. The caller is to delete this
6046 * field using decrRef() as it is no more needed.
6047 * \throw If the coordinates array is not set.
6048 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6049 * \throw If the connectivity data array has more than one component.
6050 * \throw If the connectivity data array has a named component.
6051 * \throw If the connectivity index data array has more than one component.
6052 * \throw If the connectivity index data array has a named component.
6053 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6054 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6055 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6057 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6060 int spaceDim=getSpaceDimension();
6061 int meshDim=getMeshDimension();
6062 if(spaceDim!=2 && spaceDim!=3)
6063 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6064 if(meshDim!=2 && meshDim!=3)
6065 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6066 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6068 int nbOfCells=getNumberOfCells();
6069 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6070 arr->alloc(nbOfCells,1);
6071 double *pt=arr->getPointer();
6072 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6073 const int *conn=_nodal_connec->getConstPointer();
6074 const int *connI=_nodal_connec_index->getConstPointer();
6075 const double *coo=_coords->getConstPointer();
6077 for(int i=0;i<nbOfCells;i++,pt++)
6079 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6082 case INTERP_KERNEL::NORM_TRI3:
6084 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6085 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6088 case INTERP_KERNEL::NORM_QUAD4:
6090 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6091 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6094 case INTERP_KERNEL::NORM_TETRA4:
6096 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6097 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6101 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6103 conn+=connI[i+1]-connI[i];
6105 ret->setName("AspectRatio");
6106 ret->synchronizeTimeWithSupport();
6111 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6112 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6113 * treated: INTERP_KERNEL::NORM_QUAD4.
6114 * For a cell of other type an exception is thrown.
6115 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6116 * cells and one time, lying on \a this mesh. The caller is to delete this
6117 * field using decrRef() as it is no more needed.
6118 * \throw If the coordinates array is not set.
6119 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6120 * \throw If the connectivity data array has more than one component.
6121 * \throw If the connectivity data array has a named component.
6122 * \throw If the connectivity index data array has more than one component.
6123 * \throw If the connectivity index data array has a named component.
6124 * \throw If \a this->getMeshDimension() != 2.
6125 * \throw If \a this->getSpaceDimension() != 3.
6126 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6128 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6131 int spaceDim=getSpaceDimension();
6132 int meshDim=getMeshDimension();
6134 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6136 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6137 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6139 int nbOfCells=getNumberOfCells();
6140 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6141 arr->alloc(nbOfCells,1);
6142 double *pt=arr->getPointer();
6143 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6144 const int *conn=_nodal_connec->getConstPointer();
6145 const int *connI=_nodal_connec_index->getConstPointer();
6146 const double *coo=_coords->getConstPointer();
6148 for(int i=0;i<nbOfCells;i++,pt++)
6150 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6153 case INTERP_KERNEL::NORM_QUAD4:
6155 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6156 *pt=INTERP_KERNEL::quadWarp(tmp);
6160 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6162 conn+=connI[i+1]-connI[i];
6164 ret->setName("Warp");
6165 ret->synchronizeTimeWithSupport();
6171 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6172 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6173 * treated: INTERP_KERNEL::NORM_QUAD4.
6174 * For a cell of other type an exception is thrown.
6175 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6176 * cells and one time, lying on \a this mesh. The caller is to delete this
6177 * field using decrRef() as it is no more needed.
6178 * \throw If the coordinates array is not set.
6179 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6180 * \throw If the connectivity data array has more than one component.
6181 * \throw If the connectivity data array has a named component.
6182 * \throw If the connectivity index data array has more than one component.
6183 * \throw If the connectivity index data array has a named component.
6184 * \throw If \a this->getMeshDimension() != 2.
6185 * \throw If \a this->getSpaceDimension() != 3.
6186 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6188 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6191 int spaceDim=getSpaceDimension();
6192 int meshDim=getMeshDimension();
6194 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6196 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6197 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6199 int nbOfCells=getNumberOfCells();
6200 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6201 arr->alloc(nbOfCells,1);
6202 double *pt=arr->getPointer();
6203 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6204 const int *conn=_nodal_connec->getConstPointer();
6205 const int *connI=_nodal_connec_index->getConstPointer();
6206 const double *coo=_coords->getConstPointer();
6208 for(int i=0;i<nbOfCells;i++,pt++)
6210 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6213 case INTERP_KERNEL::NORM_QUAD4:
6215 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6216 *pt=INTERP_KERNEL::quadSkew(tmp);
6220 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6222 conn+=connI[i+1]-connI[i];
6224 ret->setName("Skew");
6225 ret->synchronizeTimeWithSupport();
6230 * This method aggregate the bbox of each cell and put it into bbox parameter.
6231 * \param bbox out parameter of size 2*spacedim*nbOfcells.
6233 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6235 int spaceDim=getSpaceDimension();
6236 int nbOfCells=getNumberOfCells();
6237 bbox.resize(2*nbOfCells*spaceDim);
6238 for(int i=0;i<nbOfCells*spaceDim;i++)
6240 bbox[2*i]=std::numeric_limits<double>::max();
6241 bbox[2*i+1]=-std::numeric_limits<double>::max();
6243 const double *coordsPtr=_coords->getConstPointer();
6244 const int *conn=_nodal_connec->getConstPointer();
6245 const int *connI=_nodal_connec_index->getConstPointer();
6246 for(int i=0;i<nbOfCells;i++)
6248 int offset=connI[i]+1;
6249 int nbOfNodesForCell=connI[i+1]-offset;
6250 for(int j=0;j<nbOfNodesForCell;j++)
6252 int nodeId=conn[offset+j];
6254 for(int k=0;k<spaceDim;k++)
6256 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6257 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6265 namespace ParaMEDMEMImpl
6270 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6271 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6280 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6281 bool operator() (const int& pos) { return _conn[pos]==_val; }
6291 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6292 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6293 * \a this is composed in cell types.
6294 * The returned array is of size 3*n where n is the number of different types present in \a this.
6295 * For every k in [0,n] ret[3*k+2]==0 because it has no sense here.
6296 * This parameter is kept only for compatibility with other methode listed above.
6298 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6300 checkConnectivityFullyDefined();
6301 const int *conn=_nodal_connec->getConstPointer();
6302 const int *connI=_nodal_connec_index->getConstPointer();
6303 const int *work=connI;
6304 int nbOfCells=getNumberOfCells();
6305 std::size_t n=getAllTypes().size();
6306 std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
6307 std::set<INTERP_KERNEL::NormalizedCellType> types;
6308 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6310 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6311 if(types.find(typ)!=types.end())
6313 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6314 oss << " is not contiguous !";
6315 throw INTERP_KERNEL::Exception(oss.str().c_str());
6319 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6320 ret[3*i+1]=(int)std::distance(work,work2);
6327 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6328 * only for types cell, type node is not managed.
6329 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6330 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6331 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6332 * If 2 or more same geometric type is in \a code and exception is thrown too.
6334 * This method firstly checks
6335 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6336 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6337 * an exception is thrown too.
6339 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6340 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6341 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6343 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6346 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6347 std::size_t sz=code.size();
6350 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6351 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6353 for(std::size_t i=0;i<n;i++)
6354 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6356 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6358 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6359 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6362 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6363 if(idsPerType.empty())
6365 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6366 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6367 if(types.size()==_types.size())
6370 DataArrayInt *ret=DataArrayInt::New();
6372 int *retPtr=ret->getPointer();
6373 const int *connI=_nodal_connec_index->getConstPointer();
6374 const int *conn=_nodal_connec->getConstPointer();
6375 int nbOfCells=getNumberOfCells();
6378 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6380 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6381 int offset=(int)std::distance(connI,i);
6382 if(code[3*kk+2]==-1)
6384 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6385 std::size_t pos2=std::distance(i,j);
6386 for(std::size_t k=0;k<pos2;k++)
6387 *retPtr++=(int)k+offset;
6392 retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
6393 retPtr,std::bind2nd(std::plus<int>(),offset));
6400 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6401 * 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.
6402 * 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.
6403 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6405 * \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.
6406 * \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,
6407 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6408 * \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.
6409 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6410 * \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
6412 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6415 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6416 if(profile->getNumberOfComponents()!=1)
6417 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6418 checkConnectivityFullyDefined();
6419 const int *conn=_nodal_connec->getConstPointer();
6420 const int *connI=_nodal_connec_index->getConstPointer();
6421 int nbOfCells=getNumberOfCells();
6422 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6423 std::vector<int> typeRangeVals(1);
6424 for(const int *i=connI;i!=connI+nbOfCells;)
6426 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6427 if(std::find(types.begin(),types.end(),curType)!=types.end())
6429 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6431 types.push_back(curType);
6432 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6433 typeRangeVals.push_back((int)std::distance(connI,i));
6436 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6437 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6438 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6439 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6440 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6442 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6443 code.resize(3*nbOfCastsFinal);
6444 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6445 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6446 for(int i=0;i<nbOfCastsFinal;i++)
6448 int castId=castsPresent->getIJ(i,0);
6449 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6450 idsInPflPerType2.push_back(tmp3);
6451 code[3*i]=(int)types[castId];
6452 code[3*i+1]=tmp3->getNumberOfTuples();
6453 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6454 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6456 tmp4->copyStringInfoFrom(*profile);
6457 idsPerType2.push_back(tmp4);
6458 code[3*i+2]=(int)idsPerType2.size()-1;
6465 std::size_t sz2=idsInPflPerType2.size();
6466 idsInPflPerType.resize(sz2);
6467 for(std::size_t i=0;i<sz2;i++)
6469 DataArrayInt *locDa=idsInPflPerType2[i];
6471 idsInPflPerType[i]=locDa;
6473 std::size_t sz=idsPerType2.size();
6474 idsPerType.resize(sz);
6475 for(std::size_t i=0;i<sz;i++)
6477 DataArrayInt *locDa=idsPerType2[i];
6479 idsPerType[i]=locDa;
6484 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6485 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6486 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6487 * 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.
6489 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6491 checkFullyDefined();
6492 nM1LevMesh->checkFullyDefined();
6493 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6494 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6495 if(_coords!=nM1LevMesh->getCoords())
6496 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6497 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6498 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6499 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6500 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6501 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6502 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6503 tmp->setConnectivity(tmp0,tmp1);
6504 tmp->renumberCells(ret0->getConstPointer(),false);
6505 revDesc=tmp->getNodalConnectivity();
6506 revDescIndx=tmp->getNodalConnectivityIndex();
6507 DataArrayInt *ret=0;
6508 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6511 ret->getMaxValue(tmp2);
6513 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6514 throw INTERP_KERNEL::Exception(oss.str().c_str());
6519 revDescIndx->incrRef();
6522 meshnM1Old2New=ret0;
6527 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6528 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6529 * in "Old to New" mode.
6530 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6531 * this array using decrRef() as it is no more needed.
6532 * \throw If the nodal connectivity of cells is not defined.
6534 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6536 checkConnectivityFullyDefined();
6537 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6538 renumberCells(ret->getConstPointer(),false);
6543 * This methods checks that cells are sorted by their types.
6544 * This method makes asumption (no check) that connectivity is correctly set before calling.
6546 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6548 checkFullyDefined();
6549 const int *conn=_nodal_connec->getConstPointer();
6550 const int *connI=_nodal_connec_index->getConstPointer();
6551 int nbOfCells=getNumberOfCells();
6552 std::set<INTERP_KERNEL::NormalizedCellType> types;
6553 for(const int *i=connI;i!=connI+nbOfCells;)
6555 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6556 if(types.find(curType)!=types.end())
6558 types.insert(curType);
6559 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6565 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6566 * The geometric type order is specified by MED file.
6568 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6570 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6572 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6576 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6577 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6578 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6579 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6581 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6583 checkFullyDefined();
6584 const int *conn=_nodal_connec->getConstPointer();
6585 const int *connI=_nodal_connec_index->getConstPointer();
6586 int nbOfCells=getNumberOfCells();
6590 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6591 for(const int *i=connI;i!=connI+nbOfCells;)
6593 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6594 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6595 if(isTypeExists!=orderEnd)
6597 int pos=(int)std::distance(orderBg,isTypeExists);
6601 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6605 if(sg.find(curType)==sg.end())
6607 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6618 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6619 * 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
6620 * 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'.
6622 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6624 checkConnectivityFullyDefined();
6625 int nbOfCells=getNumberOfCells();
6626 const int *conn=_nodal_connec->getConstPointer();
6627 const int *connI=_nodal_connec_index->getConstPointer();
6628 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6629 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6630 tmpa->alloc(nbOfCells,1);
6631 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6632 tmpb->fillWithZero();
6633 int *tmp=tmpa->getPointer();
6634 int *tmp2=tmpb->getPointer();
6635 for(const int *i=connI;i!=connI+nbOfCells;i++)
6637 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6640 int pos=(int)std::distance(orderBg,where);
6642 tmp[std::distance(connI,i)]=pos;
6646 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6647 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6648 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6649 throw INTERP_KERNEL::Exception(oss.str().c_str());
6652 nbPerType=tmpb.retn();
6657 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6659 * \return a new object containing the old to new correspondance.
6661 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6663 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6665 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6669 * 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.
6670 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6671 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6672 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6674 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6676 DataArrayInt *nbPerType=0;
6677 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6678 nbPerType->decrRef();
6679 return tmpa->buildPermArrPerLevel();
6683 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6684 * The number of cells remains unchanged after the call of this method.
6685 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6686 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6688 * \return the array giving the correspondance old to new.
6690 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6692 checkFullyDefined();
6694 const int *conn=_nodal_connec->getConstPointer();
6695 const int *connI=_nodal_connec_index->getConstPointer();
6696 int nbOfCells=getNumberOfCells();
6697 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6698 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6699 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6701 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6702 types.push_back(curType);
6703 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6705 DataArrayInt *ret=DataArrayInt::New();
6706 ret->alloc(nbOfCells,1);
6707 int *retPtr=ret->getPointer();
6708 std::fill(retPtr,retPtr+nbOfCells,-1);
6710 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6712 for(const int *i=connI;i!=connI+nbOfCells;i++)
6713 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6714 retPtr[std::distance(connI,i)]=newCellId++;
6716 renumberCells(retPtr,false);
6721 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6722 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6723 * This method makes asumption that connectivity is correctly set before calling.
6725 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6727 checkFullyDefined();
6728 const int *conn=_nodal_connec->getConstPointer();
6729 const int *connI=_nodal_connec_index->getConstPointer();
6730 int nbOfCells=getNumberOfCells();
6731 std::vector<MEDCouplingUMesh *> ret;
6732 for(const int *i=connI;i!=connI+nbOfCells;)
6734 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6735 int beginCellId=(int)std::distance(connI,i);
6736 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6737 int endCellId=(int)std::distance(connI,i);
6738 int sz=endCellId-beginCellId;
6739 int *cells=new int[sz];
6740 for(int j=0;j<sz;j++)
6741 cells[j]=beginCellId+j;
6742 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6750 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6751 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6752 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6754 * \return a newly allocated instance, that the caller must manage.
6755 * \throw If \a this contains more than one geometric type.
6756 * \throw If the nodal connectivity of \a this is not fully defined.
6757 * \throw If the internal data is not coherent.
6759 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6761 checkConnectivityFullyDefined();
6762 if(_types.size()!=1)
6763 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6764 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6766 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6767 ret->setCoords(ret->getCoords());
6768 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6771 int nbCells=getNumberOfCells();
6772 int nbNodesPerCell=retC->getNumberOfNodesPerCell();
6773 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6774 int *outPtr=connOut->getPointer();
6775 const int *conn=_nodal_connec->begin();
6776 const int *connI=_nodal_connec_index->begin();
6778 for(int i=0;i<nbCells;i++,connI++)
6780 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6781 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6784 std::ostringstream oss; oss << "MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : 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 << ") !";
6785 throw INTERP_KERNEL::Exception(oss.str().c_str());
6788 retC->setNodalConnectivity(connOut);
6791 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : not implemented yet for non static geometric type !");
6796 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6797 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6798 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6799 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6800 * are not used here to avoid the build of big permutation array.
6802 * \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
6803 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6804 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6805 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6806 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6807 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
6808 * \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
6809 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6811 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6812 DataArrayInt *&szOfCellGrpOfSameType,
6813 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6815 std::vector<const MEDCouplingUMesh *> ms2;
6816 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6819 (*it)->checkConnectivityFullyDefined();
6823 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6824 const DataArrayDouble *refCoo=ms2[0]->getCoords();
6825 int meshDim=ms2[0]->getMeshDimension();
6826 std::vector<const MEDCouplingUMesh *> m1ssm;
6827 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6829 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6830 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6832 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6833 ret1->alloc(0,1); ret2->alloc(0,1);
6834 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6836 if(meshDim!=(*it)->getMeshDimension())
6837 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6838 if(refCoo!=(*it)->getCoords())
6839 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6840 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6841 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6842 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6843 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6845 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6846 m1ssmSingleAuto.push_back(singleCell);
6847 m1ssmSingle.push_back(singleCell);
6848 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6851 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6852 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6853 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6854 for(std::size_t i=0;i<m1ssm.size();i++)
6855 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6856 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6857 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6858 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6863 * This method returns a newly created DataArrayInt instance.
6864 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6866 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6868 checkFullyDefined();
6869 const int *conn=_nodal_connec->getConstPointer();
6870 const int *connIndex=_nodal_connec_index->getConstPointer();
6871 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6872 for(const int *w=begin;w!=end;w++)
6873 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6874 ret->pushBackSilent(*w);
6879 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6880 * are in [0:getNumberOfCells())
6882 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6884 checkFullyDefined();
6885 const int *conn=_nodal_connec->getConstPointer();
6886 const int *connI=_nodal_connec_index->getConstPointer();
6887 int nbOfCells=getNumberOfCells();
6888 std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6889 int *tmp=new int[nbOfCells];
6890 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6893 for(const int *i=connI;i!=connI+nbOfCells;i++)
6894 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6895 tmp[std::distance(connI,i)]=j++;
6897 DataArrayInt *ret=DataArrayInt::New();
6898 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6899 ret->copyStringInfoFrom(*da);
6900 int *retPtr=ret->getPointer();
6901 const int *daPtr=da->getConstPointer();
6902 int nbOfElems=da->getNbOfElems();
6903 for(int k=0;k<nbOfElems;k++)
6904 retPtr[k]=tmp[daPtr[k]];
6910 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6911 * This method \b works \b for mesh sorted by type.
6912 * cells whose ids is in 'idsPerGeoType' array.
6913 * This method conserves coords and name of mesh.
6915 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6917 std::vector<int> code=getDistributionOfTypes();
6918 std::size_t nOfTypesInThis=code.size()/3;
6919 int sz=0,szOfType=0;
6920 for(std::size_t i=0;i<nOfTypesInThis;i++)
6925 szOfType=code[3*i+1];
6927 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6928 if(*work<0 || *work>=szOfType)
6930 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6931 oss << ". It should be in [0," << szOfType << ") !";
6932 throw INTERP_KERNEL::Exception(oss.str().c_str());
6934 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6935 int *idsPtr=idsTokeep->getPointer();
6937 for(std::size_t i=0;i<nOfTypesInThis;i++)
6940 for(int j=0;j<code[3*i+1];j++)
6943 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6944 offset+=code[3*i+1];
6946 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6947 ret->copyTinyInfoFrom(this);
6952 * This method returns a vector of size 'this->getNumberOfCells()'.
6953 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6955 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
6957 int ncell=getNumberOfCells();
6958 std::vector<bool> ret(ncell);
6959 const int *cI=getNodalConnectivityIndex()->getConstPointer();
6960 const int *c=getNodalConnectivity()->getConstPointer();
6961 for(int i=0;i<ncell;i++)
6963 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6964 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6965 ret[i]=cm.isQuadratic();
6971 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6973 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6975 if(other->getType()!=UNSTRUCTURED)
6976 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6977 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6978 return MergeUMeshes(this,otherC);
6982 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6983 * computed by averaging coordinates of cell nodes, so this method is not a right
6984 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
6985 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6986 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6987 * components. The caller is to delete this array using decrRef() as it is
6989 * \throw If the coordinates array is not set.
6990 * \throw If the nodal connectivity of cells is not defined.
6991 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6993 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
6995 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6996 int spaceDim=getSpaceDimension();
6997 int nbOfCells=getNumberOfCells();
6998 ret->alloc(nbOfCells,spaceDim);
6999 ret->copyStringInfoFrom(*getCoords());
7000 double *ptToFill=ret->getPointer();
7001 const int *nodal=_nodal_connec->getConstPointer();
7002 const int *nodalI=_nodal_connec_index->getConstPointer();
7003 const double *coor=_coords->getConstPointer();
7004 for(int i=0;i<nbOfCells;i++)
7006 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7007 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7014 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7015 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7017 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7018 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7020 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7021 * \throw If \a this is not fully defined (coordinates and connectivity)
7022 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7024 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7026 checkFullyDefined();
7027 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7028 int spaceDim=getSpaceDimension();
7029 int nbOfCells=getNumberOfCells();
7030 int nbOfNodes=getNumberOfNodes();
7031 ret->alloc(nbOfCells,spaceDim);
7032 double *ptToFill=ret->getPointer();
7033 const int *nodal=_nodal_connec->getConstPointer();
7034 const int *nodalI=_nodal_connec_index->getConstPointer();
7035 const double *coor=_coords->getConstPointer();
7036 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7038 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7039 std::fill(ptToFill,ptToFill+spaceDim,0.);
7040 if(type!=INTERP_KERNEL::NORM_POLYHED)
7042 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7044 if(*conn>=0 && *conn<nbOfNodes)
7045 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7048 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7049 throw INTERP_KERNEL::Exception(oss.str().c_str());
7052 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7053 if(nbOfNodesInCell>0)
7054 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7057 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7058 throw INTERP_KERNEL::Exception(oss.str().c_str());
7063 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7065 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7067 if(*it>=0 && *it<nbOfNodes)
7068 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7071 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7072 throw INTERP_KERNEL::Exception(oss.str().c_str());
7076 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7079 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7080 throw INTERP_KERNEL::Exception(oss.str().c_str());
7088 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7089 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7090 * are specified via an array of cell ids.
7091 * \warning Validity of the specified cell ids is not checked!
7092 * Valid range is [ 0, \a this->getNumberOfCells() ).
7093 * \param [in] begin - an array of cell ids of interest.
7094 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7095 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7096 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7097 * caller is to delete this array using decrRef() as it is no more needed.
7098 * \throw If the coordinates array is not set.
7099 * \throw If the nodal connectivity of cells is not defined.
7101 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7102 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7104 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7106 DataArrayDouble *ret=DataArrayDouble::New();
7107 int spaceDim=getSpaceDimension();
7108 int nbOfTuple=(int)std::distance(begin,end);
7109 ret->alloc(nbOfTuple,spaceDim);
7110 double *ptToFill=ret->getPointer();
7111 double *tmp=new double[spaceDim];
7112 const int *nodal=_nodal_connec->getConstPointer();
7113 const int *nodalI=_nodal_connec_index->getConstPointer();
7114 const double *coor=_coords->getConstPointer();
7115 for(const int *w=begin;w!=end;w++)
7117 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7118 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7126 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7129 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7132 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7133 da->checkAllocated();
7134 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7136 int nbOfTuples=da->getNumberOfTuples();
7137 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7138 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7139 c->alloc(2*nbOfTuples,1);
7140 cI->alloc(nbOfTuples+1,1);
7141 int *cp=c->getPointer();
7142 int *cip=cI->getPointer();
7144 for(int i=0;i<nbOfTuples;i++)
7146 *cp++=INTERP_KERNEL::NORM_POINT1;
7150 ret->setConnectivity(c,cI,true);
7154 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7155 * Cells and nodes of
7156 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7157 * \param [in] mesh1 - the first mesh.
7158 * \param [in] mesh2 - the second mesh.
7159 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7160 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7161 * is no more needed.
7162 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7163 * \throw If the coordinates array is not set in none of the meshes.
7164 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7165 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7167 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7169 std::vector<const MEDCouplingUMesh *> tmp(2);
7170 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7171 return MergeUMeshes(tmp);
7175 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7176 * Cells and nodes of
7177 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7178 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7179 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7180 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7181 * is no more needed.
7182 * \throw If \a a.size() == 0.
7183 * \throw If \a a[ *i* ] == NULL.
7184 * \throw If the coordinates array is not set in none of the meshes.
7185 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7186 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7188 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7190 std::size_t sz=a.size();
7192 return MergeUMeshesLL(a);
7193 for(std::size_t ii=0;ii<sz;ii++)
7196 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7197 throw INTERP_KERNEL::Exception(oss.str().c_str());
7199 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7200 std::vector< const MEDCouplingUMesh * > aa(sz);
7202 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7204 const MEDCouplingUMesh *cur=a[i];
7205 const DataArrayDouble *coo=cur->getCoords();
7207 spaceDim=coo->getNumberOfComponents();
7210 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7211 for(std::size_t i=0;i<sz;i++)
7213 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7216 return MergeUMeshesLL(aa);
7221 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7224 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7225 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7226 int meshDim=(*it)->getMeshDimension();
7227 int nbOfCells=(*it)->getNumberOfCells();
7228 int meshLgth=(*it++)->getMeshLength();
7229 for(;it!=a.end();it++)
7231 if(meshDim!=(*it)->getMeshDimension())
7232 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7233 nbOfCells+=(*it)->getNumberOfCells();
7234 meshLgth+=(*it)->getMeshLength();
7236 std::vector<const MEDCouplingPointSet *> aps(a.size());
7237 std::copy(a.begin(),a.end(),aps.begin());
7238 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7239 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7240 ret->setCoords(pts);
7241 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7242 c->alloc(meshLgth,1);
7243 int *cPtr=c->getPointer();
7244 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7245 cI->alloc(nbOfCells+1,1);
7246 int *cIPtr=cI->getPointer();
7250 for(it=a.begin();it!=a.end();it++)
7252 int curNbOfCell=(*it)->getNumberOfCells();
7253 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7254 const int *curC=(*it)->_nodal_connec->getConstPointer();
7255 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7256 for(int j=0;j<curNbOfCell;j++)
7258 const int *src=curC+curCI[j];
7260 for(;src!=curC+curCI[j+1];src++,cPtr++)
7268 offset+=curCI[curNbOfCell];
7269 offset2+=(*it)->getNumberOfNodes();
7272 ret->setConnectivity(c,cI,true);
7279 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7280 * dimension and sharing the node coordinates array.
7281 * All cells of the first mesh precede all cells of the second mesh
7282 * within the result mesh.
7283 * \param [in] mesh1 - the first mesh.
7284 * \param [in] mesh2 - the second mesh.
7285 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7286 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7287 * is no more needed.
7288 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7289 * \throw If the meshes do not share the node coordinates array.
7290 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7291 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7293 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7295 std::vector<const MEDCouplingUMesh *> tmp(2);
7296 tmp[0]=mesh1; tmp[1]=mesh2;
7297 return MergeUMeshesOnSameCoords(tmp);
7301 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7302 * dimension and sharing the node coordinates array.
7303 * All cells of the *i*-th mesh precede all cells of the
7304 * (*i*+1)-th mesh within the result mesh.
7305 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7306 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7307 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7308 * is no more needed.
7309 * \throw If \a a.size() == 0.
7310 * \throw If \a a[ *i* ] == NULL.
7311 * \throw If the meshes do not share the node coordinates array.
7312 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7313 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7315 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7318 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7319 for(std::size_t ii=0;ii<meshes.size();ii++)
7322 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7323 throw INTERP_KERNEL::Exception(oss.str().c_str());
7325 const DataArrayDouble *coords=meshes.front()->getCoords();
7326 int meshDim=meshes.front()->getMeshDimension();
7327 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7329 int meshIndexLgth=0;
7330 for(;iter!=meshes.end();iter++)
7332 if(coords!=(*iter)->getCoords())
7333 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7334 if(meshDim!=(*iter)->getMeshDimension())
7335 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7336 meshLgth+=(*iter)->getMeshLength();
7337 meshIndexLgth+=(*iter)->getNumberOfCells();
7339 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7340 nodal->alloc(meshLgth,1);
7341 int *nodalPtr=nodal->getPointer();
7342 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7343 nodalIndex->alloc(meshIndexLgth+1,1);
7344 int *nodalIndexPtr=nodalIndex->getPointer();
7346 for(iter=meshes.begin();iter!=meshes.end();iter++)
7348 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7349 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7350 int nbOfCells=(*iter)->getNumberOfCells();
7351 int meshLgth2=(*iter)->getMeshLength();
7352 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7353 if(iter!=meshes.begin())
7354 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7356 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7359 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7360 ret->setName("merge");
7361 ret->setMeshDimension(meshDim);
7362 ret->setConnectivity(nodal,nodalIndex,true);
7363 ret->setCoords(coords);
7368 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7369 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7370 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7371 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7372 * New" mode are returned for each input mesh.
7373 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7374 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7375 * valid values [0,1,2], see zipConnectivityTraducer().
7376 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7377 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7378 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7380 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7381 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7382 * is no more needed.
7383 * \throw If \a meshes.size() == 0.
7384 * \throw If \a meshes[ *i* ] == NULL.
7385 * \throw If the meshes do not share the node coordinates array.
7386 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7387 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7388 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7389 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7391 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7393 //All checks are delegated to MergeUMeshesOnSameCoords
7394 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7395 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7396 corr.resize(meshes.size());
7397 std::size_t nbOfMeshes=meshes.size();
7399 const int *o2nPtr=o2n->getConstPointer();
7400 for(std::size_t i=0;i<nbOfMeshes;i++)
7402 DataArrayInt *tmp=DataArrayInt::New();
7403 int curNbOfCells=meshes[i]->getNumberOfCells();
7404 tmp->alloc(curNbOfCells,1);
7405 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7406 offset+=curNbOfCells;
7407 tmp->setName(meshes[i]->getName());
7414 * Makes all given meshes share the nodal connectivity array. The common connectivity
7415 * array is created by concatenating the connectivity arrays of all given meshes. All
7416 * the given meshes must be of the same space dimension but dimension of cells **can
7417 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7418 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7419 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7420 * \param [in,out] meshes - a vector of meshes to update.
7421 * \throw If any of \a meshes is NULL.
7422 * \throw If the coordinates array is not set in any of \a meshes.
7423 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7424 * \throw If \a meshes are of different space dimension.
7426 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7428 std::size_t sz=meshes.size();
7431 std::vector< const DataArrayDouble * > coords(meshes.size());
7432 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7433 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7437 (*it)->checkConnectivityFullyDefined();
7438 const DataArrayDouble *coo=(*it)->getCoords();
7443 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7444 oss << " has no coordinate array defined !";
7445 throw INTERP_KERNEL::Exception(oss.str().c_str());
7450 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7451 oss << " is null !";
7452 throw INTERP_KERNEL::Exception(oss.str().c_str());
7455 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7456 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7457 int offset=(*it)->getNumberOfNodes();
7458 (*it++)->setCoords(res);
7459 for(;it!=meshes.end();it++)
7461 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7462 (*it)->setCoords(res);
7463 (*it)->shiftNodeNumbersInConn(offset);
7464 offset+=oldNumberOfNodes;
7469 * Merges nodes coincident with a given precision within all given meshes that share
7470 * the nodal connectivity array. The given meshes **can be of different** mesh
7471 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7472 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7473 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7474 * \param [in,out] meshes - a vector of meshes to update.
7475 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7476 * \throw If any of \a meshes is NULL.
7477 * \throw If the \a meshes do not share the same node coordinates array.
7478 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7480 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7484 std::set<const DataArrayDouble *> s;
7485 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7488 s.insert((*it)->getCoords());
7491 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 !";
7492 throw INTERP_KERNEL::Exception(oss.str().c_str());
7497 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 !";
7498 throw INTERP_KERNEL::Exception(oss.str().c_str());
7500 const DataArrayDouble *coo=*(s.begin());
7504 DataArrayInt *comm,*commI;
7505 coo->findCommonTuples(eps,-1,comm,commI);
7506 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7507 int oldNbOfNodes=coo->getNumberOfTuples();
7509 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7510 if(oldNbOfNodes==newNbOfNodes)
7512 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7513 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7515 (*it)->renumberNodesInConn(o2n->getConstPointer());
7516 (*it)->setCoords(newCoords);
7521 * 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.
7522 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7523 * \param isQuad specifies the policy of connectivity.
7524 * @ret in/out parameter in which the result will be append
7526 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7528 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7529 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7530 ret.push_back(cm.getExtrudedType());
7531 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7534 case INTERP_KERNEL::NORM_POINT1:
7536 ret.push_back(connBg[1]);
7537 ret.push_back(connBg[1]+nbOfNodesPerLev);
7540 case INTERP_KERNEL::NORM_SEG2:
7542 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7543 ret.insert(ret.end(),conn,conn+4);
7546 case INTERP_KERNEL::NORM_SEG3:
7548 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7549 ret.insert(ret.end(),conn,conn+8);
7552 case INTERP_KERNEL::NORM_QUAD4:
7554 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7555 ret.insert(ret.end(),conn,conn+8);
7558 case INTERP_KERNEL::NORM_TRI3:
7560 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7561 ret.insert(ret.end(),conn,conn+6);
7564 case INTERP_KERNEL::NORM_TRI6:
7566 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,
7567 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7568 ret.insert(ret.end(),conn,conn+15);
7571 case INTERP_KERNEL::NORM_QUAD8:
7574 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7575 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7576 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7578 ret.insert(ret.end(),conn,conn+20);
7581 case INTERP_KERNEL::NORM_POLYGON:
7583 std::back_insert_iterator< std::vector<int> > ii(ret);
7584 std::copy(connBg+1,connEnd,ii);
7586 std::reverse_iterator<const int *> rConnBg(connEnd);
7587 std::reverse_iterator<const int *> rConnEnd(connBg+1);
7588 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7589 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7590 for(std::size_t i=0;i<nbOfRadFaces;i++)
7593 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7594 std::copy(conn,conn+4,ii);
7599 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7604 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7606 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7608 double v[3]={0.,0.,0.};
7609 std::size_t sz=std::distance(begin,end);
7612 for(std::size_t i=0;i<sz;i++)
7614 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];
7615 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7616 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7618 return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7622 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7624 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7626 std::vector<std::pair<int,int> > edges;
7627 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7628 const int *bgFace=begin;
7629 for(std::size_t i=0;i<nbOfFaces;i++)
7631 const int *endFace=std::find(bgFace+1,end,-1);
7632 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7633 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7635 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7636 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7638 edges.push_back(p1);
7642 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7646 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7648 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7650 double vec0[3],vec1[3];
7651 std::size_t sz=std::distance(begin,end);
7653 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7654 int nbOfNodes=(int)sz/2;
7655 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7656 const double *pt0=coords+3*begin[0];
7657 const double *pt1=coords+3*begin[nbOfNodes];
7658 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7659 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7662 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7664 std::size_t sz=std::distance(begin,end);
7665 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7666 std::size_t nbOfNodes(sz/2);
7667 std::copy(begin,end,(int *)tmp);
7668 for(std::size_t j=1;j<nbOfNodes;j++)
7670 begin[j]=tmp[nbOfNodes-j];
7671 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7675 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7677 std::size_t sz=std::distance(begin,end);
7679 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7680 double vec0[3],vec1[3];
7681 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7682 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];
7683 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;
7686 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7688 std::size_t sz=std::distance(begin,end);
7690 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7692 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7693 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7694 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7698 * 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 )
7699 * 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
7702 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7703 * \param [in] coords the coordinates with nb of components exactly equal to 3
7704 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7705 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7706 * \param [out] res the result is put at the end of the vector without any alteration of the data.
7708 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7710 int nbFaces=std::count(begin+1,end,-1)+1;
7711 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7712 double *vPtr=v->getPointer();
7713 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7714 double *pPtr=p->getPointer();
7715 const int *stFaceConn=begin+1;
7716 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7718 const int *endFaceConn=std::find(stFaceConn,end,-1);
7719 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7720 stFaceConn=endFaceConn+1;
7722 pPtr=p->getPointer(); vPtr=v->getPointer();
7723 DataArrayInt *comm1=0,*commI1=0;
7724 v->findCommonTuples(eps,-1,comm1,commI1);
7725 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7726 const int *comm1Ptr=comm1->getConstPointer();
7727 const int *commI1Ptr=commI1->getConstPointer();
7728 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7729 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7731 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7732 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7733 mm->finishInsertingCells();
7735 for(int i=0;i<nbOfGrps1;i++)
7737 int vecId=comm1Ptr[commI1Ptr[i]];
7738 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7739 DataArrayInt *comm2=0,*commI2=0;
7740 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7741 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7742 const int *comm2Ptr=comm2->getConstPointer();
7743 const int *commI2Ptr=commI2->getConstPointer();
7744 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7745 for(int j=0;j<nbOfGrps2;j++)
7747 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7749 res->insertAtTheEnd(begin,end);
7750 res->pushBackSilent(-1);
7754 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7755 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7756 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7757 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7758 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7759 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7760 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7761 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7762 const int *idsNodePtr=idsNode->getConstPointer();
7763 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];
7764 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7765 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7766 if(std::abs(norm)>eps)
7768 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7769 mm3->rotate(center,vec,angle);
7771 mm3->changeSpaceDimension(2);
7772 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7773 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7774 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7775 int nbOfCells=mm4->getNumberOfCells();
7776 for(int k=0;k<nbOfCells;k++)
7779 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7780 res->pushBackSilent(idsNodePtr[*work]);
7781 res->pushBackSilent(-1);
7786 res->popBackSilent();
7790 * 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
7791 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7793 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7794 * \param [in] coords coordinates expected to have 3 components.
7795 * \param [in] begin start of the nodal connectivity of the face.
7796 * \param [in] end end of the nodal connectivity (excluded) of the face.
7797 * \param [out] v the normalized vector of size 3
7798 * \param [out] p the pos of plane
7800 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7802 std::size_t nbPoints=std::distance(begin,end);
7804 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7805 double vec[3]={0.,0.,0.};
7807 bool refFound=false;
7808 for(;j<nbPoints-1 && !refFound;j++)
7810 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7811 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7812 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7813 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7817 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7820 for(std::size_t i=j;i<nbPoints-1;i++)
7823 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7824 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7825 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7826 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7829 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7830 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];
7831 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7834 v[0]/=norm; v[1]/=norm; v[2]/=norm;
7835 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7839 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7843 * This method tries to obtain a well oriented polyhedron.
7844 * If the algorithm fails, an exception will be thrown.
7846 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7848 std::list< std::pair<int,int> > edgesOK,edgesFinished;
7849 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7850 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7852 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7853 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7854 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7856 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7859 std::size_t smthChanged=0;
7860 for(std::size_t i=0;i<nbOfFaces;i++)
7862 endFace=std::find(bgFace+1,end,-1);
7863 nbOfEdgesInFace=std::distance(bgFace,endFace);
7867 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7869 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7870 std::pair<int,int> p2(p1.second,p1.first);
7871 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7872 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7873 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7878 std::reverse(bgFace+1,endFace);
7879 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7881 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7882 std::pair<int,int> p2(p1.second,p1.first);
7883 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7884 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7885 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7886 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7887 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7888 if(it!=edgesOK.end())
7891 edgesFinished.push_back(p1);
7894 edgesOK.push_back(p1);
7901 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7903 if(!edgesOK.empty())
7904 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7905 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7906 {//not lucky ! The first face was not correctly oriented : reorient all faces...
7908 for(std::size_t i=0;i<nbOfFaces;i++)
7910 endFace=std::find(bgFace+1,end,-1);
7911 std::reverse(bgFace+1,endFace);
7918 * This method makes the assumption spacedimension == meshdimension == 2.
7919 * This method works only for linear cells.
7921 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7923 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7925 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7926 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7927 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7928 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7929 int nbOfNodesExpected=m->getNumberOfNodes();
7930 if(m->getNumberOfCells()!=nbOfNodesExpected)
7931 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7932 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7933 const int *n2oPtr=n2o->getConstPointer();
7934 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7935 m->getReverseNodalConnectivity(revNodal,revNodalI);
7936 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7937 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7938 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7939 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7940 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
7941 if(nbOfNodesExpected<1)
7944 int prevNode=nodalPtr[nodalIPtr[0]+1];
7945 *work++=n2oPtr[prevNode];
7946 for(int i=1;i<nbOfNodesExpected;i++)
7948 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7950 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
7951 conn.erase(prevNode);
7954 int curNode=*(conn.begin());
7955 *work++=n2oPtr[curNode];
7956 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
7957 shar.erase(prevCell);
7960 prevCell=*(shar.begin());
7964 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
7967 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
7970 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
7976 * This method makes the assumption spacedimension == meshdimension == 3.
7977 * This method works only for linear cells.
7979 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7981 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
7983 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7984 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7985 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7986 const int *conn=m->getNodalConnectivity()->getConstPointer();
7987 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
7988 int nbOfCells=m->getNumberOfCells();
7989 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7990 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
7993 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7994 for(int i=1;i<nbOfCells;i++)
7997 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8003 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8004 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8006 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
8010 for(int i=0;i<nbOfNodesInCell;i++)
8011 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8012 else if(spaceDim==2)
8014 for(int i=0;i<nbOfNodesInCell;i++)
8016 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8021 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8024 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8026 int nbOfCells=getNumberOfCells();
8028 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8029 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,-1,4};
8030 ofs << " <" << getVTKDataSetType() << ">\n";
8031 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8032 ofs << " <PointData>\n" << pointData << std::endl;
8033 ofs << " </PointData>\n";
8034 ofs << " <CellData>\n" << cellData << std::endl;
8035 ofs << " </CellData>\n";
8036 ofs << " <Points>\n";
8037 if(getSpaceDimension()==3)
8038 _coords->writeVTK(ofs,8,"Points");
8041 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8042 coo->writeVTK(ofs,8,"Points");
8044 ofs << " </Points>\n";
8045 ofs << " <Cells>\n";
8046 const int *cPtr=_nodal_connec->getConstPointer();
8047 const int *cIPtr=_nodal_connec_index->getConstPointer();
8048 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8049 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8050 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8051 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8052 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8053 int szFaceOffsets=0,szConn=0;
8054 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8057 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8060 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8061 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8065 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8066 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8067 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8068 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8069 w4=std::copy(c.begin(),c.end(),w4);
8072 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8073 types->writeVTK(ofs,8,"UInt8","types");
8074 offsets->writeVTK(ofs,8,"Int32","offsets");
8075 if(szFaceOffsets!=0)
8076 {//presence of Polyhedra
8077 connectivity->reAlloc(szConn);
8078 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8079 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8080 w1=faces->getPointer();
8081 for(int i=0;i<nbOfCells;i++)
8082 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8084 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8086 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8087 for(int j=0;j<nbFaces;j++)
8089 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8090 *w1++=(int)std::distance(w6,w5);
8091 w1=std::copy(w6,w5,w1);
8095 faces->writeVTK(ofs,8,"Int32","faces");
8097 connectivity->writeVTK(ofs,8,"Int32","connectivity");
8098 ofs << " </Cells>\n";
8099 ofs << " </Piece>\n";
8100 ofs << " </" << getVTKDataSetType() << ">\n";
8103 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8105 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8107 { stream << " Not set !"; return ; }
8108 stream << " Mesh dimension : " << _mesh_dim << ".";
8112 { stream << " No coordinates set !"; return ; }
8113 if(!_coords->isAllocated())
8114 { stream << " Coordinates set but not allocated !"; return ; }
8115 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8116 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8117 if(!_nodal_connec_index)
8118 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8119 if(!_nodal_connec_index->isAllocated())
8120 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8121 int lgth=_nodal_connec_index->getNumberOfTuples();
8122 int cpt=_nodal_connec_index->getNumberOfComponents();
8123 if(cpt!=1 || lgth<1)
8125 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8128 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8130 return std::string("UnstructuredGrid");
8134 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8135 * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8136 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8138 * \param [in] m1 - the first input mesh which is a partitioned object.
8139 * \param [in] m2 - the second input mesh which is a partition tool.
8140 * \param [in] eps - precision used to detect coincident mesh entities.
8141 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8142 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8143 * this array using decrRef() as it is no more needed.
8144 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8145 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8146 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8147 * any cell of \a m2. The caller is to delete this array using decrRef() as
8148 * it is no more needed.
8149 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8150 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8151 * is no more needed.
8152 * \throw If the coordinates array is not set in any of the meshes.
8153 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8154 * \throw If any of the meshes is not a 2D mesh in 2D space.
8156 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8158 m1->checkFullyDefined();
8159 m2->checkFullyDefined();
8160 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8161 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8162 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8163 MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8164 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8165 std::vector<double> addCoo,addCoordsQuadratic;
8166 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8167 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8168 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8169 m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8170 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8171 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8172 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8173 std::vector< std::vector<int> > intersectEdge2;
8174 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8175 subDiv2.clear(); dd5=0; dd6=0;
8176 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8177 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8178 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8179 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8181 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8182 addCooDa->alloc((int)(addCoo.size())/2,2);
8183 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8184 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8185 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8186 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8187 std::vector<const DataArrayDouble *> coordss(4);
8188 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8189 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8190 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8191 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8192 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8193 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8194 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8195 ret->setConnectivity(conn,connI,true);
8196 ret->setCoords(coo);
8197 cellNb1=c1.retn(); cellNb2=c2.retn();
8201 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8202 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8203 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8204 const std::vector<double>& addCoords,
8205 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8207 static const int SPACEDIM=2;
8208 std::vector<double> bbox1,bbox2;
8209 const double *coo1=m1->getCoords()->getConstPointer();
8210 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8211 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8212 int offset1=m1->getNumberOfNodes();
8213 const double *coo2=m2->getCoords()->getConstPointer();
8214 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8215 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8216 int offset2=offset1+m2->getNumberOfNodes();
8217 int offset3=offset2+((int)addCoords.size())/2;
8218 m1->getBoundingBoxForBBTree(bbox1);
8219 m2->getBoundingBoxForBBTree(bbox2);
8220 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8221 int ncell1=m1->getNumberOfCells();
8223 for(int i=0;i<ncell1;i++)
8225 std::vector<int> candidates2;
8226 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8227 std::map<INTERP_KERNEL::Node *,int> mapp;
8228 std::map<int,INTERP_KERNEL::Node *> mappRev;
8229 INTERP_KERNEL::QuadraticPolygon pol1;
8230 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8231 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8232 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8233 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8234 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8236 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
8237 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8238 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8239 for(it1.first();!it1.finished();it1.next())
8240 edges1.insert(it1.current()->getPtr());
8242 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8243 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8245 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8247 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8248 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8249 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8250 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8251 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8254 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8256 pol1.initLocationsWithOther(pol2s[ii]);
8257 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8258 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8259 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8265 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8267 catch(INTERP_KERNEL::Exception& e)
8269 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();
8270 throw INTERP_KERNEL::Exception(oss.str().c_str());
8273 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8274 (*it).second->decrRef();
8279 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8282 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8283 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8284 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8285 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8286 std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8288 static const int SPACEDIM=2;
8289 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8290 desc2=DataArrayInt::New();
8291 descIndx2=DataArrayInt::New();
8292 revDesc2=DataArrayInt::New();
8293 revDescIndx2=DataArrayInt::New();
8294 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8295 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8296 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8297 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8298 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8299 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8300 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8301 std::vector<double> bbox1,bbox2;
8302 m1Desc->getBoundingBoxForBBTree(bbox1);
8303 m2Desc->getBoundingBoxForBBTree(bbox2);
8304 int ncell1=m1Desc->getNumberOfCells();
8305 int ncell2=m2Desc->getNumberOfCells();
8306 intersectEdge1.resize(ncell1);
8307 colinear2.resize(ncell2);
8308 subDiv2.resize(ncell2);
8309 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8310 std::vector<int> candidates1(1);
8311 int offset1=m1->getNumberOfNodes();
8312 int offset2=offset1+m2->getNumberOfNodes();
8313 for(int i=0;i<ncell1;i++)
8315 std::vector<int> candidates2;
8316 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8317 if(!candidates2.empty())
8319 std::map<INTERP_KERNEL::Node *,int> map1,map2;
8320 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8322 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8323 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8328 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8330 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8331 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8335 * This method performs the 2nd step of Partition of 2D mesh.
8336 * This method has 4 inputs :
8337 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8338 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8339 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8340 * The aim of this method is to sort the splitting nodes, if any, and to put in 'intersectEdge' output paramter based on edges of mesh 'm2'
8341 * \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. Only present for its coords in case of 'subDiv' shares some nodes of 'm1'
8342 * \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.
8343 * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8345 void MEDCouplingUMesh::BuildIntersectEdges(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, const std::vector<double>& addCoo, const std::vector< std::vector<int> >& subDiv, std::vector< std::vector<int> >& intersectEdge) throw(INTERP_KERNEL::Exception)
8347 int offset1=m1->getNumberOfNodes();
8348 int ncell=m2->getNumberOfCells();
8349 const int *c=m2->getNodalConnectivity()->getConstPointer();
8350 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8351 const double *coo=m2->getCoords()->getConstPointer();
8352 const double *cooBis=m1->getCoords()->getConstPointer();
8353 int offset2=offset1+m2->getNumberOfNodes();
8354 intersectEdge.resize(ncell);
8355 for(int i=0;i<ncell;i++,cI++)
8357 const std::vector<int>& divs=subDiv[i];
8358 int nnode=cI[1]-cI[0]-1;
8359 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8360 std::map<INTERP_KERNEL::Node *, int> mapp22;
8361 for(int j=0;j<nnode;j++)
8363 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8364 int nnid=c[(*cI)+j+1];
8365 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8366 mapp22[nn]=nnid+offset1;
8368 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8369 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8370 ((*it).second.first)->decrRef();
8371 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8372 std::map<INTERP_KERNEL::Node *,int> mapp3;
8373 for(std::size_t j=0;j<divs.size();j++)
8376 INTERP_KERNEL::Node *tmp=0;
8378 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8380 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8382 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8386 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8387 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8394 * 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).
8395 * 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
8396 * with a plane. The result will be put in 'cut3DSuf' out parameter.
8397 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8398 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8399 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8400 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8401 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8402 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8403 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8404 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8405 * \param [out] cut3DSuf input/output param.
8407 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8408 const int *nodal3DCurve, const int *nodalIndx3DCurve,
8409 const int *desc, const int *descIndx,
8410 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8412 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8413 int nbOf3DSurfCell=(int)cut3DSurf.size();
8414 for(int i=0;i<nbOf3DSurfCell;i++)
8416 std::vector<int> res;
8417 int offset=descIndx[i];
8418 int nbOfSeg=descIndx[i+1]-offset;
8419 for(int j=0;j<nbOfSeg;j++)
8421 int edgeId=desc[offset+j];
8422 int status=cut3DCurve[edgeId];
8426 res.push_back(status);
8429 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8430 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8438 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8444 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8445 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8448 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8452 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8457 {// case when plane is on a multi colinear edge of a polyhedron
8458 if((int)res.size()==2*nbOfSeg)
8460 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8463 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8470 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8471 * 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).
8472 * 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
8473 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8474 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8475 * \param desc is the descending connectivity 3D->3DSurf
8476 * \param descIndx is the descending connectivity index 3D->3DSurf
8478 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8479 const int *desc, const int *descIndx,
8480 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8482 checkFullyDefined();
8483 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8484 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8485 const int *nodal3D=_nodal_connec->getConstPointer();
8486 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8487 int nbOfCells=getNumberOfCells();
8488 for(int i=0;i<nbOfCells;i++)
8490 std::map<int, std::set<int> > m;
8491 int offset=descIndx[i];
8492 int nbOfFaces=descIndx[i+1]-offset;
8495 for(int j=0;j<nbOfFaces;j++)
8497 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8498 if(p.first!=-1 && p.second!=-1)
8502 start=p.first; end=p.second;
8503 m[p.first].insert(p.second);
8504 m[p.second].insert(p.first);
8508 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8509 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8510 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8511 INTERP_KERNEL::NormalizedCellType cmsId;
8512 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8513 start=tmp[0]; end=tmp[nbOfNodesSon-1];
8514 for(unsigned k=0;k<nbOfNodesSon;k++)
8516 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8517 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8524 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8528 std::map<int, std::set<int> >::const_iterator it=m.find(start);
8529 const std::set<int>& s=(*it).second;
8530 std::set<int> s2; s2.insert(prev);
8532 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8535 int val=*s3.begin();
8536 conn.push_back(start);
8543 conn.push_back(end);
8546 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8547 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8548 cellIds->pushBackSilent(i);
8554 * 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
8555 * 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
8556 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8557 * 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
8558 * 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.
8560 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8562 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8564 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8567 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8568 if(cm.getDimension()==2)
8570 const int *node=nodalConnBg+1;
8571 int startNode=*node++;
8572 double refX=coords[2*startNode];
8573 for(;node!=nodalConnEnd;node++)
8575 if(coords[2*(*node)]<refX)
8578 refX=coords[2*startNode];
8581 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8585 double angle0=-M_PI/2;
8590 double angleNext=0.;
8591 while(nextNode!=startNode)
8595 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8597 if(*node!=tmpOut.back() && *node!=prevNode)
8599 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8600 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8605 res=angle0-angleM+2.*M_PI;
8614 if(nextNode!=startNode)
8616 angle0=angleNext-M_PI;
8619 prevNode=tmpOut.back();
8620 tmpOut.push_back(nextNode);
8623 std::vector<int> tmp3(2*(sz-1));
8624 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8625 std::copy(nodalConnBg+1,nodalConnEnd,it);
8626 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8628 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8631 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8633 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8638 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8639 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8644 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8647 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8651 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8652 * 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.
8654 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8655 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8656 * \param [in,out] arr array in which the remove operation will be done.
8657 * \param [in,out] arrIndx array in the remove operation will modify
8658 * \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])
8659 * \return true if \b arr and \b arrIndx have been modified, false if not.
8661 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8663 if(!arrIndx || !arr)
8664 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8665 if(offsetForRemoval<0)
8666 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8667 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8668 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8669 int *arrIPtr=arrIndx->getPointer();
8672 const int *arrPtr=arr->getConstPointer();
8673 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8674 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8676 if(*arrIPtr-previousArrI>offsetForRemoval)
8678 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8680 if(s.find(*work)==s.end())
8681 arrOut.push_back(*work);
8684 previousArrI=*arrIPtr;
8685 *arrIPtr=(int)arrOut.size();
8687 if(arr->getNumberOfTuples()==(int)arrOut.size())
8689 arr->alloc((int)arrOut.size(),1);
8690 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8695 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8696 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8697 * The selection of extraction is done standardly in new2old format.
8698 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8700 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8701 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8702 * \param [in] arrIn arr origin array from which the extraction will be done.
8703 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8704 * \param [out] arrOut the resulting array
8705 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8707 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8708 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8710 if(!arrIn || !arrIndxIn)
8711 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8712 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8713 const int *arrInPtr=arrIn->getConstPointer();
8714 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8715 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8716 int maxSizeOfArr=arrIn->getNumberOfTuples();
8717 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8718 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8719 arrIo->alloc((int)(sz+1),1);
8720 const int *idsIt=idsOfSelectBg;
8721 int *work=arrIo->getPointer();
8724 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8726 if(*idsIt>=0 && *idsIt<nbOfGrps)
8727 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8730 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8731 throw INTERP_KERNEL::Exception(oss.str().c_str());
8737 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8738 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8739 throw INTERP_KERNEL::Exception(oss.str().c_str());
8742 arro->alloc(lgth,1);
8743 work=arro->getPointer();
8744 idsIt=idsOfSelectBg;
8745 for(std::size_t i=0;i<sz;i++,idsIt++)
8747 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8748 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8751 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8752 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8753 throw INTERP_KERNEL::Exception(oss.str().c_str());
8757 arrIndexOut=arrIo.retn();
8761 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8762 * 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
8763 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8764 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8766 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8767 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8768 * \param [in] arrIn arr origin array from which the extraction will be done.
8769 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8770 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8771 * \param [in] srcArrIndex index array of \b srcArr
8772 * \param [out] arrOut the resulting array
8773 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8775 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8777 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8778 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8779 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8781 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8782 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8783 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8784 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8785 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8786 std::vector<bool> v(nbOfTuples,true);
8788 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8789 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8790 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8792 if(*it>=0 && *it<nbOfTuples)
8795 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8799 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8800 throw INTERP_KERNEL::Exception(oss.str().c_str());
8803 srcArrIndexPtr=srcArrIndex->getConstPointer();
8804 arrIo->alloc(nbOfTuples+1,1);
8805 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8806 const int *arrInPtr=arrIn->getConstPointer();
8807 const int *srcArrPtr=srcArr->getConstPointer();
8808 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8809 int *arroPtr=arro->getPointer();
8810 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8814 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8815 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8819 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8820 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8821 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8825 arrIndexOut=arrIo.retn();
8829 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8830 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8832 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8833 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8834 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8835 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8836 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8837 * \param [in] srcArrIndex index array of \b srcArr
8839 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8841 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8842 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8844 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8845 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8846 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8847 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8848 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8849 int *arrInOutPtr=arrInOut->getPointer();
8850 const int *srcArrPtr=srcArr->getConstPointer();
8851 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8853 if(*it>=0 && *it<nbOfTuples)
8855 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8856 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8859 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] !";
8860 throw INTERP_KERNEL::Exception(oss.str().c_str());
8865 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8866 throw INTERP_KERNEL::Exception(oss.str().c_str());
8872 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8873 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8874 * 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]].
8875 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8876 * A negative value in \b arrIn means that it is ignored.
8877 * 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.
8879 * \param [in] arrIn arr origin array from which the extraction will be done.
8880 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8881 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8882 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8884 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
8886 int seed=0,nbOfDepthPeelingPerformed=0;
8887 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
8891 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8892 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8893 * 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]].
8894 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8895 * A negative value in \b arrIn means that it is ignored.
8896 * 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.
8897 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
8898 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
8899 * \param [in] arrIn arr origin array from which the extraction will be done.
8900 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8901 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8902 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8903 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8904 * \sa MEDCouplingUMesh::partitionBySpreadZone
8906 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8908 nbOfDepthPeelingPerformed=0;
8910 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8911 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8914 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
8918 std::vector<bool> fetched(nbOfTuples,false);
8919 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
8922 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg(std::vector<bool>& fetched, const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8924 nbOfDepthPeelingPerformed=0;
8925 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
8926 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
8927 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8928 std::vector<bool> fetched2(nbOfTuples,false);
8930 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
8932 if(*seedElt>=0 && *seedElt<nbOfTuples)
8933 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
8935 { 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()); }
8937 const int *arrInPtr=arrIn->getConstPointer();
8938 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8939 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
8940 std::vector<int> idsToFetch1(seedBg,seedEnd);
8941 std::vector<int> idsToFetch2;
8942 std::vector<int> *idsToFetch=&idsToFetch1;
8943 std::vector<int> *idsToFetchOther=&idsToFetch2;
8944 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
8946 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
8947 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
8949 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
8950 std::swap(idsToFetch,idsToFetchOther);
8951 idsToFetchOther->clear();
8952 nbOfDepthPeelingPerformed++;
8954 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
8956 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
8957 int *retPtr=ret->getPointer();
8958 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
8965 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8966 * 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
8967 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8968 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8970 * \param [in] start begin of set of ids of the input extraction (included)
8971 * \param [in] end end of set of ids of the input extraction (excluded)
8972 * \param [in] step step of the set of ids in range mode.
8973 * \param [in] arrIn arr origin array from which the extraction will be done.
8974 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8975 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8976 * \param [in] srcArrIndex index array of \b srcArr
8977 * \param [out] arrOut the resulting array
8978 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8980 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
8982 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8983 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8984 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8986 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8987 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
8988 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8989 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8990 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8992 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8993 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8994 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
8996 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8998 if(it>=0 && it<nbOfTuples)
8999 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9002 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9003 throw INTERP_KERNEL::Exception(oss.str().c_str());
9006 srcArrIndexPtr=srcArrIndex->getConstPointer();
9007 arrIo->alloc(nbOfTuples+1,1);
9008 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9009 const int *arrInPtr=arrIn->getConstPointer();
9010 const int *srcArrPtr=srcArr->getConstPointer();
9011 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9012 int *arroPtr=arro->getPointer();
9013 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9015 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9018 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9019 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9023 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9024 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9028 arrIndexOut=arrIo.retn();
9032 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9033 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9035 * \param [in] start begin of set of ids of the input extraction (included)
9036 * \param [in] end end of set of ids of the input extraction (excluded)
9037 * \param [in] step step of the set of ids in range mode.
9038 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9039 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9040 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9041 * \param [in] srcArrIndex index array of \b srcArr
9043 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9045 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9046 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9048 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9049 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9050 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9051 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9052 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9053 int *arrInOutPtr=arrInOut->getPointer();
9054 const int *srcArrPtr=srcArr->getConstPointer();
9055 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9057 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9059 if(it>=0 && it<nbOfTuples)
9061 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9062 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9065 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9066 throw INTERP_KERNEL::Exception(oss.str().c_str());
9071 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9072 throw INTERP_KERNEL::Exception(oss.str().c_str());
9078 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9079 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9080 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9081 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9082 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9084 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9086 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9088 checkFullyDefined();
9089 int mdim=getMeshDimension();
9090 int spaceDim=getSpaceDimension();
9092 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9093 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9094 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9095 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9096 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9097 ret->setCoords(getCoords());
9098 ret->allocateCells((int)partition.size());
9100 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9102 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9103 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9107 cell=tmp->buildUnionOf2DMesh();
9110 cell=tmp->buildUnionOf3DMesh();
9113 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9116 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9119 ret->finishInsertingCells();
9124 * This method partitions \b this into contiguous zone.
9125 * This method only needs a well defined connectivity. Coordinates are not considered here.
9126 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9128 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9131 int nbOfCellsCur=getNumberOfCells();
9132 std::vector<DataArrayInt *> ret;
9135 DataArrayInt *neigh=0,*neighI=0;
9136 computeNeighborsOfCells(neigh,neighI);
9137 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9138 std::vector<bool> fetchedCells(nbOfCellsCur,false);
9139 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9141 while(seed<nbOfCellsCur)
9143 int nbOfPeelPerformed=0;
9144 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9145 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9147 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9148 ret.push_back((*it).retn());
9152 int nbOfCellsCur=getNumberOfCells();
9153 DataArrayInt *neigh=0,*neighI=0;
9154 computeNeighborsOfCells(neigh,neighI);
9155 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9156 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9157 std::vector<DataArrayInt *> ret;
9158 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9159 while(nbOfCellsCur>0)
9161 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9162 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9163 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9164 ret2.push_back(tmp2); ret.push_back(tmp2);
9165 nbOfCellsCur=tmp3->getNumberOfTuples();
9168 ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9169 MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9172 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9173 neighAuto->transformWithIndArr(renum->begin(),renum->end());
9176 for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9183 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9184 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9186 * \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.
9187 * \return a newly allocated DataArrayInt to be managed by the caller.
9188 * \throw In case of \a code has not the right format (typically of size 3*n)
9190 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9192 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9193 std::size_t nb=code.size()/3;
9194 if(code.size()%3!=0)
9195 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9196 ret->alloc((int)nb,2);
9197 int *retPtr=ret->getPointer();
9198 for(std::size_t i=0;i<nb;i++,retPtr+=2)
9200 retPtr[0]=code[3*i+2];
9201 retPtr[1]=code[3*i+2]+code[3*i+1];
9206 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9207 _own_cell(true),_cell_id(-1),_nb_cell(0)
9212 _nb_cell=mesh->getNumberOfCells();
9216 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9224 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9225 _own_cell(false),_cell_id(bg-1),
9232 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9235 if(_cell_id<_nb_cell)
9244 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9250 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9252 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9255 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9261 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9269 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9275 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9280 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9285 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9287 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9290 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9295 _nb_cell=mesh->getNumberOfCells();
9299 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9306 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9308 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9309 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9310 if(_cell_id<_nb_cell)
9312 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9313 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9314 int startId=_cell_id;
9315 _cell_id+=nbOfElems;
9316 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9322 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9326 _conn=mesh->getNodalConnectivity()->getPointer();
9327 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9331 void MEDCouplingUMeshCell::next()
9333 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9338 _conn_lgth=_conn_indx[1]-_conn_indx[0];
9341 std::string MEDCouplingUMeshCell::repr() const
9343 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9345 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9347 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9351 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9354 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9356 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9357 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9359 return INTERP_KERNEL::NORM_ERROR;
9362 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9365 if(_conn_lgth!=NOTICABLE_FIRST_VAL)