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 return MEDCouplingPointSet::zipCoordsTraducer();
1441 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1442 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1444 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1449 return AreCellsEqual0(conn,connI,cell1,cell2);
1451 return AreCellsEqual1(conn,connI,cell1,cell2);
1453 return AreCellsEqual2(conn,connI,cell1,cell2);
1455 return AreCellsEqual3(conn,connI,cell1,cell2);
1457 return AreCellsEqual7(conn,connI,cell1,cell2);
1459 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1463 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1465 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1467 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1468 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1473 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1475 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1477 int sz=connI[cell1+1]-connI[cell1];
1478 if(sz==connI[cell2+1]-connI[cell2])
1480 if(conn[connI[cell1]]==conn[connI[cell2]])
1482 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1483 unsigned dim=cm.getDimension();
1489 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1490 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1491 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1492 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1493 return work!=tmp+sz1?1:0;
1496 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1499 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1506 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1508 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1510 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1512 if(conn[connI[cell1]]==conn[connI[cell2]])
1514 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1515 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1523 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1525 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1527 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1529 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1530 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1537 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1539 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1541 int sz=connI[cell1+1]-connI[cell1];
1542 if(sz==connI[cell2+1]-connI[cell2])
1544 if(conn[connI[cell1]]==conn[connI[cell2]])
1546 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1547 unsigned dim=cm.getDimension();
1553 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1554 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1555 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1556 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1561 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1562 std::reverse_iterator<int *> it2((int *)tmp);
1563 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1569 return work!=tmp+sz1?1:0;
1572 {//case of SEG2 and SEG3
1573 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1575 if(!cm.isQuadratic())
1577 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1578 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1579 if(std::equal(it1,it2,conn+connI[cell2]+1))
1585 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])
1592 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1599 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1600 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1601 * and result remains unchanged.
1602 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1603 * If in 'candidates' pool -1 value is considered as an empty value.
1604 * WARNING this method returns only ONE set of result !
1606 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1608 if(candidates.size()<1)
1611 std::vector<int>::const_iterator iter=candidates.begin();
1612 int start=(*iter++);
1613 for(;iter!=candidates.end();iter++)
1615 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1620 result->pushBackSilent(start);
1624 result->pushBackSilent(*iter);
1626 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1633 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1634 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1636 * \param [in] compType input specifying the technique used to compare cells each other.
1637 * - 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.
1638 * - 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)
1639 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1640 * - 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
1641 * can be used for users not sensitive to orientation of cell
1642 * \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.
1643 * \param [out] commonCells
1644 * \param [out] commonCellsI
1645 * \return the correspondance array old to new in a newly allocated array.
1648 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1650 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1651 getReverseNodalConnectivity(revNodal,revNodalI);
1652 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1655 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1656 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1658 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1659 int nbOfCells=nodalI->getNumberOfTuples()-1;
1660 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1661 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1662 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1663 std::vector<bool> isFetched(nbOfCells,false);
1666 for(int i=0;i<nbOfCells;i++)
1670 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1671 std::vector<int> v,v2;
1672 if(connOfNode!=connPtr+connIPtr[i+1])
1674 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1675 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1678 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1682 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1683 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1684 v2.resize(std::distance(v2.begin(),it));
1688 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1690 int pos=commonCellsI->back();
1691 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1692 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1693 isFetched[*it]=true;
1701 for(int i=startCellId;i<nbOfCells;i++)
1705 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1706 std::vector<int> v,v2;
1707 if(connOfNode!=connPtr+connIPtr[i+1])
1709 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1712 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1716 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1717 v2.resize(std::distance(v2.begin(),it));
1721 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1723 int pos=commonCellsI->back();
1724 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1725 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1726 isFetched[*it]=true;
1732 commonCellsArr=commonCells.retn();
1733 commonCellsIArr=commonCellsI.retn();
1737 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1738 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1739 * than \a other->getNumberOfCells() in the returned array means that there is no
1740 * corresponding cell in \a this mesh.
1741 * It is expected that \a this and \a other meshes share the same node coordinates
1742 * array, if it is not so an exception is thrown.
1743 * \param [in] other - the mesh to compare with.
1744 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1745 * valid values [0,1,2], see zipConnectivityTraducer().
1746 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1747 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1748 * values. The caller is to delete this array using
1749 * decrRef() as it is no more needed.
1750 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1753 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1754 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1755 * \sa checkDeepEquivalOnSameNodesWith()
1756 * \sa checkGeoEquivalWith()
1758 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1760 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1761 int nbOfCells=getNumberOfCells();
1762 static const int possibleCompType[]={0,1,2};
1763 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1765 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1766 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1768 throw INTERP_KERNEL::Exception(oss.str().c_str());
1770 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1771 arr=o2n->substr(nbOfCells);
1772 arr->setName(other->getName());
1774 if(other->getNumberOfCells()==0)
1776 return arr->getMaxValue(tmp)<nbOfCells;
1780 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1781 * This method tries to determine if \b other is fully included in \b this.
1782 * The main difference is that this method is not expected to throw exception.
1783 * This method has two outputs :
1785 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1786 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1788 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1790 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1791 DataArrayInt *commonCells=0,*commonCellsI=0;
1792 int thisNbCells=getNumberOfCells();
1793 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1794 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1795 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1796 int otherNbCells=other->getNumberOfCells();
1797 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1798 arr2->alloc(otherNbCells,1);
1799 arr2->fillWithZero();
1800 int *arr2Ptr=arr2->getPointer();
1801 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1802 for(int i=0;i<nbOfCommon;i++)
1804 int start=commonCellsPtr[commonCellsIPtr[i]];
1805 if(start<thisNbCells)
1807 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1809 int sig=commonCellsPtr[j]>0?1:-1;
1810 int val=std::abs(commonCellsPtr[j])-1;
1811 if(val>=thisNbCells)
1812 arr2Ptr[val-thisNbCells]=sig*(start+1);
1816 arr2->setName(other->getName());
1817 if(arr2->presenceOfValue(0))
1823 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1826 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1827 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1829 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1830 std::vector<const MEDCouplingUMesh *> ms(2);
1833 return MergeUMeshesOnSameCoords(ms);
1837 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1838 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1839 * cellIds is not given explicitely but by a range python like.
1841 * \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.
1842 * \return a newly allocated
1844 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1845 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1847 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1849 if(getMeshDimension()!=-1)
1850 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1853 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1855 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1857 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1859 return const_cast<MEDCouplingUMesh *>(this);
1864 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1865 * The result mesh shares or not the node coordinates array with \a this mesh depending
1866 * on \a keepCoords parameter.
1867 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1868 * to write this mesh to the MED file, its cells must be sorted using
1869 * sortCellsInMEDFileFrmt().
1870 * \param [in] begin - an array of cell ids to include to the new mesh.
1871 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
1872 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1873 * array of \a this mesh, else "free" nodes are removed from the result mesh
1874 * by calling zipCoords().
1875 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1876 * to delete this mesh using decrRef() as it is no more needed.
1877 * \throw If the coordinates array is not set.
1878 * \throw If the nodal connectivity of cells is not defined.
1879 * \throw If any cell id in the array \a begin is not valid.
1881 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1882 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
1884 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1886 if(getMeshDimension()!=-1)
1887 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1891 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1893 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1895 return const_cast<MEDCouplingUMesh *>(this);
1900 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1902 * 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.
1903 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1904 * The number of cells of \b this will remain the same with this method.
1906 * \param [in] begin begin of cell ids (included) of cells in this to assign
1907 * \param [in] end end of cell ids (excluded) of cells in this to assign
1908 * \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 ).
1909 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1911 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1913 checkConnectivityFullyDefined();
1914 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1915 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1916 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1917 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1919 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1920 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1921 throw INTERP_KERNEL::Exception(oss.str().c_str());
1923 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1924 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1926 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1927 throw INTERP_KERNEL::Exception(oss.str().c_str());
1929 int nbOfCells=getNumberOfCells();
1930 bool easyAssign=true;
1931 const int *connI=_nodal_connec_index->getConstPointer();
1932 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1933 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1935 if(*it>=0 && *it<nbOfCells)
1937 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1941 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1942 throw INTERP_KERNEL::Exception(oss.str().c_str());
1947 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1952 DataArrayInt *arrOut=0,*arrIOut=0;
1953 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
1955 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
1956 setConnectivity(arrOut,arrIOut,true);
1960 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1962 checkConnectivityFullyDefined();
1963 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1964 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1965 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1966 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1968 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1969 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1970 throw INTERP_KERNEL::Exception(oss.str().c_str());
1972 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
1973 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1975 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1976 throw INTERP_KERNEL::Exception(oss.str().c_str());
1978 int nbOfCells=getNumberOfCells();
1979 bool easyAssign=true;
1980 const int *connI=_nodal_connec_index->getConstPointer();
1981 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1983 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
1985 if(it>=0 && it<nbOfCells)
1987 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
1991 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
1992 throw INTERP_KERNEL::Exception(oss.str().c_str());
1997 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2002 DataArrayInt *arrOut=0,*arrIOut=0;
2003 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2005 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2006 setConnectivity(arrOut,arrIOut,true);
2011 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2012 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2013 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2014 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2016 * \param [in] begin input start of array of node ids.
2017 * \param [in] end input end of array of node ids.
2018 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2019 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2021 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2023 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2024 checkConnectivityFullyDefined();
2026 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2027 std::vector<bool> fastFinder(sz,false);
2028 for(const int *work=begin;work!=end;work++)
2029 if(*work>=0 && *work<sz)
2030 fastFinder[*work]=true;
2031 int nbOfCells=getNumberOfCells();
2032 const int *conn=getNodalConnectivity()->getConstPointer();
2033 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2034 for(int i=0;i<nbOfCells;i++)
2036 int ref=0,nbOfHit=0;
2037 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2041 if(fastFinder[*work2])
2044 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2045 cellIdsKept->pushBackSilent(i);
2047 cellIdsKeptArr=cellIdsKept.retn();
2051 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2052 * this->getMeshDimension(), that bound some cells of \a this mesh.
2053 * The cells of lower dimension to include to the result mesh are selected basing on
2054 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2055 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2056 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2057 * created mesh shares the node coordinates array with \a this mesh.
2058 * \param [in] begin - the array of node ids.
2059 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2060 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2061 * array \a begin are added, else cells whose any node is in the
2062 * array \a begin are added.
2063 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2064 * to delete this mesh using decrRef() as it is no more needed.
2065 * \throw If the coordinates array is not set.
2066 * \throw If the nodal connectivity of cells is not defined.
2067 * \throw If any node id in \a begin is not valid.
2069 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2070 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2072 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2074 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2075 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2076 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2077 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2078 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2082 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2083 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2084 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2085 * array of \a this mesh, else "free" nodes are removed from the result mesh
2086 * by calling zipCoords().
2087 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2088 * to delete this mesh using decrRef() as it is no more needed.
2089 * \throw If the coordinates array is not set.
2090 * \throw If the nodal connectivity of cells is not defined.
2092 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2093 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2095 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2097 DataArrayInt *desc=DataArrayInt::New();
2098 DataArrayInt *descIndx=DataArrayInt::New();
2099 DataArrayInt *revDesc=DataArrayInt::New();
2100 DataArrayInt *revDescIndx=DataArrayInt::New();
2102 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2105 descIndx->decrRef();
2106 int nbOfCells=meshDM1->getNumberOfCells();
2107 const int *revDescIndxC=revDescIndx->getConstPointer();
2108 std::vector<int> boundaryCells;
2109 for(int i=0;i<nbOfCells;i++)
2110 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2111 boundaryCells.push_back(i);
2112 revDescIndx->decrRef();
2113 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2118 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2119 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2120 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2122 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2124 checkFullyDefined();
2125 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2126 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2127 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2128 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2130 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2131 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2133 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2134 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2135 const int *revDescPtr=revDesc->getConstPointer();
2136 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2137 int nbOfCells=getNumberOfCells();
2138 std::vector<bool> ret1(nbOfCells,false);
2140 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2141 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2142 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2144 DataArrayInt *ret2=DataArrayInt::New();
2146 int *ret2Ptr=ret2->getPointer();
2148 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2151 ret2->setName("BoundaryCells");
2156 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2157 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2158 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2159 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2161 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2162 * This method method returns cells ids set s = s1 + s2 where :
2164 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2165 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2167 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2168 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2170 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2171 * \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
2172 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2174 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2176 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2177 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2178 checkConnectivityFullyDefined();
2179 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2180 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2181 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2182 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2183 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2184 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2185 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2186 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2187 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2188 DataArrayInt *idsOtherInConsti=0;
2189 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2190 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2192 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2194 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2195 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2196 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2197 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2198 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2199 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2200 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2201 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2202 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2203 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2204 neighThisPartAuto=0;
2205 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2206 const int li[2]={0,1};
2207 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2208 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2209 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2212 cellIdsRk0=s0arr.retn();
2213 cellIdsRk1=s_renum1.retn();
2217 * 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
2218 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2220 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2222 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2224 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2225 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2226 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2227 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2229 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2230 revDesc=0; desc=0; descIndx=0;
2231 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2232 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2233 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2237 * Finds nodes lying on the boundary of \a this mesh.
2238 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2239 * nodes. The caller is to delete this array using decrRef() as it is no
2241 * \throw If the coordinates array is not set.
2242 * \throw If the nodal connectivity of cells is node defined.
2244 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2245 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2247 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2249 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2250 return skin->computeFetchedNodeIds();
2253 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2256 return const_cast<MEDCouplingUMesh *>(this);
2260 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2261 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2262 * 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.
2263 * 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.
2264 * 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.
2266 * \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
2267 * parameter is altered during the call.
2268 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2269 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2270 * \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.
2272 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2274 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2275 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2277 checkFullyDefined();
2278 otherDimM1OnSameCoords.checkFullyDefined();
2279 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2280 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2281 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2282 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2283 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2284 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2285 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2286 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2287 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2288 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2289 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2290 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2291 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2292 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2294 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2295 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2296 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2297 DataArrayInt *idsTmp=0;
2298 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2299 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2301 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2302 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2303 DataArrayInt *tmp0=0,*tmp1=0;
2304 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2305 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2306 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2307 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2308 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2309 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2310 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2312 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2313 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2314 nodeIdsToDuplicate=s3.retn();
2318 * This method operates a modification of the connectivity and coords in \b this.
2319 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2320 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2321 * 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
2322 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2323 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2325 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2327 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2328 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2330 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2332 int nbOfNodes=getNumberOfNodes();
2333 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2334 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2338 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2339 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2340 * This method is a generalization of shiftNodeNumbersInConn().
2341 * \warning This method performs no check of validity of new ids. **Use it with care !**
2342 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2343 * this->getNumberOfNodes(), in "Old to New" mode.
2344 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2345 * \throw If the nodal connectivity of cells is not defined.
2347 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2348 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2350 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2352 checkConnectivityFullyDefined();
2353 int *conn=getNodalConnectivity()->getPointer();
2354 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2355 int nbOfCells=getNumberOfCells();
2356 for(int i=0;i<nbOfCells;i++)
2357 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2359 int& node=conn[iconn];
2360 if(node>=0)//avoid polyhedron separator
2362 node=newNodeNumbersO2N[node];
2365 _nodal_connec->declareAsNew();
2370 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2371 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2372 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2374 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2376 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2378 checkConnectivityFullyDefined();
2379 int *conn=getNodalConnectivity()->getPointer();
2380 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2381 int nbOfCells=getNumberOfCells();
2382 for(int i=0;i<nbOfCells;i++)
2383 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2385 int& node=conn[iconn];
2386 if(node>=0)//avoid polyhedron separator
2391 _nodal_connec->declareAsNew();
2396 * This method operates a modification of the connectivity in \b this.
2397 * 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.
2398 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2399 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2400 * 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
2401 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2402 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2404 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2405 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2407 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2408 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2409 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2411 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2413 checkConnectivityFullyDefined();
2414 std::map<int,int> m;
2416 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2418 int *conn=getNodalConnectivity()->getPointer();
2419 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2420 int nbOfCells=getNumberOfCells();
2421 for(int i=0;i<nbOfCells;i++)
2422 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2424 int& node=conn[iconn];
2425 if(node>=0)//avoid polyhedron separator
2427 std::map<int,int>::iterator it=m.find(node);
2436 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2438 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2439 * After the call of this method the number of cells remains the same as before.
2441 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2442 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2443 * be strictly in [0;this->getNumberOfCells()).
2445 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2446 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2447 * should be contained in[0;this->getNumberOfCells()).
2449 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2451 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2453 checkConnectivityFullyDefined();
2454 int nbCells=getNumberOfCells();
2455 const int *array=old2NewBg;
2457 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2459 const int *conn=_nodal_connec->getConstPointer();
2460 const int *connI=_nodal_connec_index->getConstPointer();
2461 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2462 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2463 const int *n2oPtr=n2o->begin();
2464 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2465 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2466 newConn->copyStringInfoFrom(*_nodal_connec);
2467 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2468 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2469 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2471 int *newC=newConn->getPointer();
2472 int *newCI=newConnI->getPointer();
2475 for(int i=0;i<nbCells;i++)
2478 int nbOfElts=connI[pos+1]-connI[pos];
2479 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2484 setConnectivity(newConn,newConnI);
2486 free(const_cast<int *>(array));
2490 * Finds cells whose bounding boxes intersect a given bounding box.
2491 * \param [in] bbox - an array defining the bounding box via coordinates of its
2492 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2494 * \param [in] eps - a factor used to increase size of the bounding box of cell
2495 * before comparing it with \a bbox. This factor is multiplied by the maximal
2496 * extent of the bounding box of cell to produce an addition to this bounding box.
2497 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2498 * cells. The caller is to delete this array using decrRef() as it is no more
2500 * \throw If the coordinates array is not set.
2501 * \throw If the nodal connectivity of cells is not defined.
2503 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2504 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2506 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2508 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2509 if(getMeshDimension()==-1)
2511 elems->pushBackSilent(0);
2512 return elems.retn();
2514 int dim=getSpaceDimension();
2515 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2516 const int* conn = getNodalConnectivity()->getConstPointer();
2517 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2518 const double* coords = getCoords()->getConstPointer();
2519 int nbOfCells=getNumberOfCells();
2520 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2522 for (int i=0; i<dim; i++)
2524 elem_bb[i*2]=std::numeric_limits<double>::max();
2525 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2528 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2530 int node= conn[inode];
2531 if(node>=0)//avoid polyhedron separator
2533 for (int idim=0; idim<dim; idim++)
2535 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2537 elem_bb[idim*2] = coords[node*dim+idim] ;
2539 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2541 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2546 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2547 elems->pushBackSilent(ielem);
2549 return elems.retn();
2553 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2554 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2555 * added in 'elems' parameter.
2557 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2559 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2560 if(getMeshDimension()==-1)
2562 elems->pushBackSilent(0);
2563 return elems.retn();
2565 int dim=getSpaceDimension();
2566 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2567 const int* conn = getNodalConnectivity()->getConstPointer();
2568 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2569 const double* coords = getCoords()->getConstPointer();
2570 int nbOfCells=getNumberOfCells();
2571 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2573 for (int i=0; i<dim; i++)
2575 elem_bb[i*2]=std::numeric_limits<double>::max();
2576 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2579 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2581 int node= conn[inode];
2582 if(node>=0)//avoid polyhedron separator
2584 for (int idim=0; idim<dim; idim++)
2586 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2588 elem_bb[idim*2] = coords[node*dim+idim] ;
2590 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2592 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2597 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2598 elems->pushBackSilent(ielem);
2600 return elems.retn();
2604 * Returns a type of a cell by its id.
2605 * \param [in] cellId - the id of the cell of interest.
2606 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2607 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2609 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2611 const int *ptI=_nodal_connec_index->getConstPointer();
2612 const int *pt=_nodal_connec->getConstPointer();
2613 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2614 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2617 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2618 throw INTERP_KERNEL::Exception(oss.str().c_str());
2623 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2624 * This method does not throw exception if geometric type \a type is not in \a this.
2625 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2626 * The coordinates array is not considered here.
2628 * \param [in] type the geometric type
2629 * \return cell ids in this having geometric type \a type.
2631 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2634 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2636 checkConnectivityFullyDefined();
2637 int nbCells=getNumberOfCells();
2638 int mdim=getMeshDimension();
2639 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2640 if(mdim!=(int)cm.getDimension())
2641 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2642 const int *ptI=_nodal_connec_index->getConstPointer();
2643 const int *pt=_nodal_connec->getConstPointer();
2644 for(int i=0;i<nbCells;i++)
2646 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2647 ret->pushBackSilent(i);
2653 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2655 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2657 const int *ptI=_nodal_connec_index->getConstPointer();
2658 const int *pt=_nodal_connec->getConstPointer();
2659 int nbOfCells=getNumberOfCells();
2661 for(int i=0;i<nbOfCells;i++)
2662 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2668 * Returns the nodal connectivity of a given cell.
2669 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2670 * all returned node ids can be used in getCoordinatesOfNode().
2671 * \param [in] cellId - an id of the cell of interest.
2672 * \param [in,out] conn - a vector where the node ids are appended. It is not
2673 * cleared before the appending.
2674 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2676 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2678 const int *ptI=_nodal_connec_index->getConstPointer();
2679 const int *pt=_nodal_connec->getConstPointer();
2680 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2685 std::string MEDCouplingUMesh::simpleRepr() const
2687 static const char msg0[]="No coordinates specified !";
2688 std::ostringstream ret;
2689 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2690 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2692 double tt=getTime(tmpp1,tmpp2);
2693 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2694 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2696 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2698 { ret << " Mesh dimension has not been set or is invalid !"; }
2701 const int spaceDim=getSpaceDimension();
2702 ret << spaceDim << "\nInfo attached on space dimension : ";
2703 for(int i=0;i<spaceDim;i++)
2704 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2708 ret << msg0 << "\n";
2709 ret << "Number of nodes : ";
2711 ret << getNumberOfNodes() << "\n";
2713 ret << msg0 << "\n";
2714 ret << "Number of cells : ";
2715 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2716 ret << getNumberOfCells() << "\n";
2718 ret << "No connectivity specified !" << "\n";
2719 ret << "Cell types present : ";
2720 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2722 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2723 ret << cm.getRepr() << " ";
2729 std::string MEDCouplingUMesh::advancedRepr() const
2731 std::ostringstream ret;
2732 ret << simpleRepr();
2733 ret << "\nCoordinates array : \n___________________\n\n";
2735 _coords->reprWithoutNameStream(ret);
2737 ret << "No array set !\n";
2738 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2739 reprConnectivityOfThisLL(ret);
2744 * This method returns a C++ code that is a dump of \a this.
2745 * This method will throw if this is not fully defined.
2747 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2749 static const char coordsName[]="coords";
2750 static const char connName[]="conn";
2751 static const char connIName[]="connI";
2752 checkFullyDefined();
2753 std::ostringstream ret; ret << "// coordinates" << std::endl;
2754 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2755 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2756 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2757 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2758 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2759 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2760 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2764 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2766 std::ostringstream ret;
2767 reprConnectivityOfThisLL(ret);
2772 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2773 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2774 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2777 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2778 * 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
2779 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2781 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2783 int mdim=getMeshDimension();
2785 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2786 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2787 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2788 bool needToCpyCT=true;
2791 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2799 if(!_nodal_connec_index)
2801 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2806 tmp2=_nodal_connec_index;
2809 ret->setConnectivity(tmp1,tmp2,false);
2814 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2815 ret->setCoords(coords);
2818 ret->setCoords(_coords);
2822 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2824 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2826 int nbOfCells=getNumberOfCells();
2827 const int *c=_nodal_connec->getConstPointer();
2828 const int *ci=_nodal_connec_index->getConstPointer();
2829 for(int i=0;i<nbOfCells;i++)
2831 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2832 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2833 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2838 stream << "Connectivity not defined !\n";
2841 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2843 const int *ptI=_nodal_connec_index->getConstPointer();
2844 const int *pt=_nodal_connec->getConstPointer();
2845 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2846 return ptI[cellId+1]-ptI[cellId]-1;
2848 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2852 * Returns types of cells of the specified part of \a this mesh.
2853 * This method avoids computing sub-mesh explicitely to get its types.
2854 * \param [in] begin - an array of cell ids of interest.
2855 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2856 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2857 * describing the cell types.
2858 * \throw If the coordinates array is not set.
2859 * \throw If the nodal connectivity of cells is not defined.
2862 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2864 checkFullyDefined();
2865 std::set<INTERP_KERNEL::NormalizedCellType> ret;
2866 const int *conn=_nodal_connec->getConstPointer();
2867 const int *connIndex=_nodal_connec_index->getConstPointer();
2868 for(const int *w=begin;w!=end;w++)
2869 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2874 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2875 * a set of types of cells constituting \a this mesh.
2876 * This method is for advanced users having prepared their connectivity before. For
2877 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2878 * \param [in] conn - the nodal connectivity array.
2879 * \param [in] connIndex - the nodal connectivity index array.
2880 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2883 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2885 DataArrayInt::SetArrayIn(conn,_nodal_connec);
2886 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2887 if(isComputingTypes)
2893 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2894 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2896 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2897 _nodal_connec(0),_nodal_connec_index(0),
2898 _types(other._types)
2900 if(other._nodal_connec)
2901 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2902 if(other._nodal_connec_index)
2903 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2906 MEDCouplingUMesh::~MEDCouplingUMesh()
2909 _nodal_connec->decrRef();
2910 if(_nodal_connec_index)
2911 _nodal_connec_index->decrRef();
2915 * Recomputes a set of cell types of \a this mesh. For more info see
2916 * \ref MEDCouplingUMeshNodalConnectivity.
2918 void MEDCouplingUMesh::computeTypes()
2920 if(_nodal_connec && _nodal_connec_index)
2923 const int *conn=_nodal_connec->getConstPointer();
2924 const int *connIndex=_nodal_connec_index->getConstPointer();
2925 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2927 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
2928 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2933 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2935 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2937 if(!_nodal_connec_index || !_nodal_connec || !_coords)
2938 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2942 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2944 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2946 if(!_nodal_connec_index || !_nodal_connec)
2947 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
2951 * Returns a number of cells constituting \a this mesh.
2952 * \return int - the number of cells in \a this mesh.
2953 * \throw If the nodal connectivity of cells is not defined.
2955 int MEDCouplingUMesh::getNumberOfCells() const
2957 if(_nodal_connec_index)
2958 return _nodal_connec_index->getNumberOfTuples()-1;
2963 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
2967 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
2968 * mesh. For more info see \ref MEDCouplingMeshesPage.
2969 * \return int - the dimension of \a this mesh.
2970 * \throw If the mesh dimension is not defined using setMeshDimension().
2972 int MEDCouplingUMesh::getMeshDimension() const
2975 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
2980 * Returns a length of the nodal connectivity array.
2981 * This method is for test reason. Normally the integer returned is not useable by
2982 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
2983 * \return int - the length of the nodal connectivity array.
2985 int MEDCouplingUMesh::getMeshLength() const
2987 return _nodal_connec->getNbOfElems();
2991 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
2993 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
2995 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
2996 tinyInfo.push_back(getMeshDimension());
2997 tinyInfo.push_back(getNumberOfCells());
2999 tinyInfo.push_back(getMeshLength());
3001 tinyInfo.push_back(-1);
3005 * First step of unserialization process.
3007 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3009 return tinyInfo[6]<=0;
3013 * Second step of serialization process.
3014 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3016 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3018 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3020 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3024 * Third and final step of serialization process.
3026 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3028 MEDCouplingPointSet::serialize(a1,a2);
3029 if(getMeshDimension()>-1)
3031 a1=DataArrayInt::New();
3032 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3033 int *ptA1=a1->getPointer();
3034 const int *conn=getNodalConnectivity()->getConstPointer();
3035 const int *index=getNodalConnectivityIndex()->getConstPointer();
3036 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3037 std::copy(conn,conn+getMeshLength(),ptA1);
3044 * Second and final unserialization process.
3045 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3047 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3049 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3050 setMeshDimension(tinyInfo[5]);
3054 const int *recvBuffer=a1->getConstPointer();
3055 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3056 myConnecIndex->alloc(tinyInfo[6]+1,1);
3057 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3058 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3059 myConnec->alloc(tinyInfo[7],1);
3060 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3061 setConnectivity(myConnec, myConnecIndex);
3066 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3067 * CellIds are given using range specified by a start an end and step.
3069 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3071 checkFullyDefined();
3072 int ncell=getNumberOfCells();
3073 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3074 ret->_mesh_dim=_mesh_dim;
3075 ret->setCoords(_coords);
3076 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3077 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3078 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3080 const int *conn=_nodal_connec->getConstPointer();
3081 const int *connIndex=_nodal_connec_index->getConstPointer();
3082 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3084 if(work>=0 && work<ncell)
3086 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3090 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3091 throw INTERP_KERNEL::Exception(oss.str().c_str());
3094 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3095 int *newConnPtr=newConn->getPointer();
3096 std::set<INTERP_KERNEL::NormalizedCellType> types;
3098 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3100 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3101 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3103 ret->setConnectivity(newConn,newConnI,false);
3105 ret->copyTinyInfoFrom(this);
3110 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3111 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3112 * The return newly allocated mesh will share the same coordinates as \a this.
3114 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3116 checkFullyDefined();
3117 int ncell=getNumberOfCells();
3118 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3119 ret->_mesh_dim=_mesh_dim;
3120 ret->setCoords(_coords);
3121 std::size_t nbOfElemsRet=std::distance(begin,end);
3122 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3124 const int *conn=_nodal_connec->getConstPointer();
3125 const int *connIndex=_nodal_connec_index->getConstPointer();
3127 for(const int *work=begin;work!=end;work++,newNbring++)
3129 if(*work>=0 && *work<ncell)
3130 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3134 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3135 throw INTERP_KERNEL::Exception(oss.str().c_str());
3138 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3139 int *connRetWork=connRet;
3140 std::set<INTERP_KERNEL::NormalizedCellType> types;
3141 for(const int *work=begin;work!=end;work++)
3143 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3144 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3146 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3147 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3148 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3149 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3150 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3152 ret->copyTinyInfoFrom(this);
3157 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3159 * For 1D cells, the returned field contains lengths.<br>
3160 * For 2D cells, the returned field contains areas.<br>
3161 * For 3D cells, the returned field contains volumes.
3162 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3163 * orientation, i.e. the volume is always positive.
3164 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3165 * and one time . The caller is to delete this field using decrRef() as it is no
3168 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3170 std::string name="MeasureOfMesh_";
3172 int nbelem=getNumberOfCells();
3173 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3174 field->setName(name.c_str());
3175 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3176 array->alloc(nbelem,1);
3177 double *area_vol=array->getPointer();
3178 field->setArray(array) ; array=0;
3179 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3180 field->synchronizeTimeWithMesh();
3181 if(getMeshDimension()!=-1)
3184 INTERP_KERNEL::NormalizedCellType type;
3185 int dim_space=getSpaceDimension();
3186 const double *coords=getCoords()->getConstPointer();
3187 const int *connec=getNodalConnectivity()->getConstPointer();
3188 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3189 for(int iel=0;iel<nbelem;iel++)
3191 ipt=connec_index[iel];
3192 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3193 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);
3196 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3200 area_vol[0]=std::numeric_limits<double>::max();
3202 return field.retn();
3206 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3208 * For 1D cells, the returned array contains lengths.<br>
3209 * For 2D cells, the returned array contains areas.<br>
3210 * For 3D cells, the returned array contains volumes.
3211 * This method avoids building explicitly a part of \a this mesh to perform the work.
3212 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3213 * orientation, i.e. the volume is always positive.
3214 * \param [in] begin - an array of cell ids of interest.
3215 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3216 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3217 * delete this array using decrRef() as it is no more needed.
3219 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3220 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3221 * \sa getMeasureField()
3223 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3225 std::string name="PartMeasureOfMesh_";
3227 int nbelem=(int)std::distance(begin,end);
3228 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3229 array->setName(name.c_str());
3230 array->alloc(nbelem,1);
3231 double *area_vol=array->getPointer();
3232 if(getMeshDimension()!=-1)
3235 INTERP_KERNEL::NormalizedCellType type;
3236 int dim_space=getSpaceDimension();
3237 const double *coords=getCoords()->getConstPointer();
3238 const int *connec=getNodalConnectivity()->getConstPointer();
3239 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3240 for(const int *iel=begin;iel!=end;iel++)
3242 ipt=connec_index[*iel];
3243 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3244 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3247 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3251 area_vol[0]=std::numeric_limits<double>::max();
3253 return array.retn();
3257 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3258 * \a this one. The returned field contains the dual cell volume for each corresponding
3259 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3260 * the dual mesh in P1 sens of \a this.<br>
3261 * For 1D cells, the returned field contains lengths.<br>
3262 * For 2D cells, the returned field contains areas.<br>
3263 * For 3D cells, the returned field contains volumes.
3264 * This method is useful to check "P1*" conservative interpolators.
3265 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3266 * orientation, i.e. the volume is always positive.
3267 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3268 * nodes and one time. The caller is to delete this array using decrRef() as
3269 * it is no more needed.
3271 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3273 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3274 std::string name="MeasureOnNodeOfMesh_";
3276 int nbNodes=getNumberOfNodes();
3277 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3278 double cst=1./((double)getMeshDimension()+1.);
3279 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3280 array->alloc(nbNodes,1);
3281 double *valsToFill=array->getPointer();
3282 std::fill(valsToFill,valsToFill+nbNodes,0.);
3283 const double *values=tmp->getArray()->getConstPointer();
3284 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3285 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3286 getReverseNodalConnectivity(da,daInd);
3287 const int *daPtr=da->getConstPointer();
3288 const int *daIPtr=daInd->getConstPointer();
3289 for(int i=0;i<nbNodes;i++)
3290 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3291 valsToFill[i]+=cst*values[*cell];
3293 ret->setArray(array);
3298 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3299 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3300 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3301 * and are normalized.
3302 * <br> \a this can be either
3303 * - a 2D mesh in 2D or 3D space or
3304 * - an 1D mesh in 2D space.
3306 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3307 * cells and one time. The caller is to delete this field using decrRef() as
3308 * it is no more needed.
3309 * \throw If the nodal connectivity of cells is not defined.
3310 * \throw If the coordinates array is not set.
3311 * \throw If the mesh dimension is not set.
3312 * \throw If the mesh and space dimension is not as specified above.
3314 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3316 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3317 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3318 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3319 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3320 int nbOfCells=getNumberOfCells();
3321 int nbComp=getMeshDimension()+1;
3322 array->alloc(nbOfCells,nbComp);
3323 double *vals=array->getPointer();
3324 const int *connI=_nodal_connec_index->getConstPointer();
3325 const int *conn=_nodal_connec->getConstPointer();
3326 const double *coords=_coords->getConstPointer();
3327 if(getMeshDimension()==2)
3329 if(getSpaceDimension()==3)
3331 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3332 const double *locPtr=loc->getConstPointer();
3333 for(int i=0;i<nbOfCells;i++,vals+=3)
3335 int offset=connI[i];
3336 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3337 double n=INTERP_KERNEL::norm<3>(vals);
3338 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3343 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3344 const double *isAbsPtr=isAbs->getArray()->begin();
3345 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3346 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3349 else//meshdimension==1
3352 for(int i=0;i<nbOfCells;i++)
3354 int offset=connI[i];
3355 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3356 double n=INTERP_KERNEL::norm<2>(tmp);
3357 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3362 ret->setArray(array);
3364 ret->synchronizeTimeWithSupport();
3369 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3370 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3371 * and are normalized.
3372 * <br> \a this can be either
3373 * - a 2D mesh in 2D or 3D space or
3374 * - an 1D mesh in 2D space.
3376 * This method avoids building explicitly a part of \a this mesh to perform the work.
3377 * \param [in] begin - an array of cell ids of interest.
3378 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3379 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3380 * cells and one time. The caller is to delete this field using decrRef() as
3381 * it is no more needed.
3382 * \throw If the nodal connectivity of cells is not defined.
3383 * \throw If the coordinates array is not set.
3384 * \throw If the mesh dimension is not set.
3385 * \throw If the mesh and space dimension is not as specified above.
3386 * \sa buildOrthogonalField()
3388 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3389 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3391 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3393 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3394 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3395 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3396 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3397 std::size_t nbelems=std::distance(begin,end);
3398 int nbComp=getMeshDimension()+1;
3399 array->alloc((int)nbelems,nbComp);
3400 double *vals=array->getPointer();
3401 const int *connI=_nodal_connec_index->getConstPointer();
3402 const int *conn=_nodal_connec->getConstPointer();
3403 const double *coords=_coords->getConstPointer();
3404 if(getMeshDimension()==2)
3406 if(getSpaceDimension()==3)
3408 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3409 const double *locPtr=loc->getConstPointer();
3410 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3412 int offset=connI[*i];
3413 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3414 double n=INTERP_KERNEL::norm<3>(vals);
3415 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3420 for(std::size_t i=0;i<nbelems;i++)
3421 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3424 else//meshdimension==1
3427 for(const int *i=begin;i!=end;i++)
3429 int offset=connI[*i];
3430 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3431 double n=INTERP_KERNEL::norm<2>(tmp);
3432 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3437 ret->setArray(array);
3439 ret->synchronizeTimeWithSupport();
3444 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3445 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3446 * and are \b not normalized.
3447 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3448 * cells and one time. The caller is to delete this field using decrRef() as
3449 * it is no more needed.
3450 * \throw If the nodal connectivity of cells is not defined.
3451 * \throw If the coordinates array is not set.
3452 * \throw If \a this->getMeshDimension() != 1.
3453 * \throw If \a this mesh includes cells of type other than SEG2.
3455 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3457 if(getMeshDimension()!=1)
3458 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3459 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3460 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3461 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3462 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3463 int nbOfCells=getNumberOfCells();
3464 int spaceDim=getSpaceDimension();
3465 array->alloc(nbOfCells,spaceDim);
3466 double *pt=array->getPointer();
3467 const double *coo=getCoords()->getConstPointer();
3468 std::vector<int> conn;
3470 for(int i=0;i<nbOfCells;i++)
3473 getNodeIdsOfCell(i,conn);
3474 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3476 ret->setArray(array);
3478 ret->synchronizeTimeWithSupport();
3483 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3484 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3485 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3486 * from. If a result face is shared by two 3D cells, then the face in included twice in
3488 * \param [in] origin - 3 components of a point defining location of the plane.
3489 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3490 * must be greater than 1e-6.
3491 * \param [in] eps - half-thickness of the plane.
3492 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3493 * producing correspondent 2D cells. The caller is to delete this array
3494 * using decrRef() as it is no more needed.
3495 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3496 * not share the node coordinates array with \a this mesh. The caller is to
3497 * delete this mesh using decrRef() as it is no more needed.
3498 * \throw If the coordinates array is not set.
3499 * \throw If the nodal connectivity of cells is not defined.
3500 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3501 * \throw If magnitude of \a vec is less than 1e-6.
3502 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3503 * \throw If \a this includes quadratic cells.
3505 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3507 checkFullyDefined();
3508 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3509 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3510 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3511 if(candidates->empty())
3512 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3513 std::vector<int> nodes;
3514 DataArrayInt *cellIds1D=0;
3515 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3516 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3517 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3518 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3519 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3520 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3521 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3522 revDesc2=0; revDescIndx2=0;
3523 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3524 revDesc1=0; revDescIndx1=0;
3525 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3526 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3528 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3529 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3531 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3532 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3533 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3534 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3535 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3536 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3537 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3538 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3539 if(cellIds2->empty())
3540 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3541 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3542 ret->setCoords(mDesc1->getCoords());
3543 ret->setConnectivity(conn,connI,true);
3544 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3549 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3550 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
3551 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3553 * \param [in] origin - 3 components of a point defining location of the plane.
3554 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3555 * must be greater than 1e-6.
3556 * \param [in] eps - half-thickness of the plane.
3557 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3558 * producing correspondent segments. The caller is to delete this array
3559 * using decrRef() as it is no more needed.
3560 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3561 * mesh in 3D space. This mesh does not share the node coordinates array with
3562 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3564 * \throw If the coordinates array is not set.
3565 * \throw If the nodal connectivity of cells is not defined.
3566 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3567 * \throw If magnitude of \a vec is less than 1e-6.
3568 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3569 * \throw If \a this includes quadratic cells.
3571 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3573 checkFullyDefined();
3574 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3575 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3576 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3577 if(candidates->empty())
3578 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3579 std::vector<int> nodes;
3580 DataArrayInt *cellIds1D=0;
3581 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3582 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3583 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3584 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3585 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3586 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3587 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3588 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3589 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3591 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3592 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3594 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3595 int ncellsSub=subMesh->getNumberOfCells();
3596 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3597 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3598 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3599 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3600 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3602 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3603 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3604 for(int i=0;i<ncellsSub;i++)
3606 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3608 if(cut3DSurf[i].first!=-2)
3610 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3611 connI->pushBackSilent(conn->getNumberOfTuples());
3612 cellIds2->pushBackSilent(i);
3616 int cellId3DSurf=cut3DSurf[i].second;
3617 int offset=nodalI[cellId3DSurf]+1;
3618 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3619 for(int j=0;j<nbOfEdges;j++)
3621 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3622 connI->pushBackSilent(conn->getNumberOfTuples());
3623 cellIds2->pushBackSilent(cellId3DSurf);
3628 if(cellIds2->empty())
3629 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3630 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3631 ret->setCoords(mDesc1->getCoords());
3632 ret->setConnectivity(conn,connI,true);
3633 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3638 * Finds cells whose bounding boxes intersect a given plane.
3639 * \param [in] origin - 3 components of a point defining location of the plane.
3640 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3641 * must be greater than 1e-6.
3642 * \param [in] eps - half-thickness of the plane.
3643 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3644 * cells. The caller is to delete this array using decrRef() as it is no more
3646 * \throw If the coordinates array is not set.
3647 * \throw If the nodal connectivity of cells is not defined.
3648 * \throw If \a this->getSpaceDimension() != 3.
3649 * \throw If magnitude of \a vec is less than 1e-6.
3650 * \sa buildSlice3D()
3652 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3654 checkFullyDefined();
3655 if(getSpaceDimension()!=3)
3656 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3657 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3659 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3661 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3662 double angle=acos(vec[2]/normm);
3663 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3667 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3668 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3669 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3671 mw->getBoundingBox(bbox);
3672 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3673 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3677 getBoundingBox(bbox);
3678 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3679 cellIds=getCellsInBoundingBox(bbox,eps);
3681 return cellIds.retn();
3685 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3686 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3687 * No consideration of coordinate is done by this method.
3688 * 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)
3689 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3691 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3693 if(getMeshDimension()!=1)
3694 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3695 int nbCells=getNumberOfCells();
3697 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3698 const int *connI=_nodal_connec_index->getConstPointer();
3699 const int *conn=_nodal_connec->getConstPointer();
3700 int ref=conn[connI[0]+2];
3701 for(int i=1;i<nbCells;i++)
3703 if(conn[connI[i]+1]!=ref)
3705 ref=conn[connI[i]+2];
3711 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3712 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3713 * \param pt reference point of the line
3714 * \param v normalized director vector of the line
3715 * \param eps max precision before throwing an exception
3716 * \param res output of size this->getNumberOfCells
3718 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3720 if(getMeshDimension()!=1)
3721 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3722 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3723 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3724 if(getSpaceDimension()!=3)
3725 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3726 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3727 const double *fPtr=f->getArray()->getConstPointer();
3729 for(int i=0;i<getNumberOfCells();i++)
3731 const double *tmp1=fPtr+3*i;
3732 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3733 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3734 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3735 double n1=INTERP_KERNEL::norm<3>(tmp);
3736 n1/=INTERP_KERNEL::norm<3>(tmp1);
3738 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3740 const double *coo=getCoords()->getConstPointer();
3741 for(int i=0;i<getNumberOfNodes();i++)
3743 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3744 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3745 res[i]=std::accumulate(tmp,tmp+3,0.);
3750 * 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.
3751 * \a this is expected to be a mesh so that its space dimension is equal to its
3752 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3753 * 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).
3755 * 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
3756 * 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).
3757 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3759 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3760 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3762 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3763 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3764 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3765 * \return the positive value of the distance.
3766 * \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
3768 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3770 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
3772 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3773 if(meshDim!=spaceDim-1)
3774 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3775 if(meshDim!=2 && meshDim!=1)
3776 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3777 checkFullyDefined();
3778 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3779 { 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()); }
3780 DataArrayInt *ret1=0;
3781 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3782 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3783 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3784 cellId=*ret1Safe->begin();
3785 return *ret0->begin();
3789 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3790 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
3791 * 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
3792 * 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).
3793 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3795 * \a this is expected to be a mesh so that its space dimension is equal to its
3796 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3797 * 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).
3799 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3800 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3802 * \param [in] pts the list of points in which each tuple represents a point
3803 * \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.
3804 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3805 * \throw if number of components of \a pts is not equal to the space dimension.
3806 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3807 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3809 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
3812 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3813 pts->checkAllocated();
3814 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3815 if(meshDim!=spaceDim-1)
3816 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3817 if(meshDim!=2 && meshDim!=1)
3818 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3819 if(pts->getNumberOfComponents()!=spaceDim)
3821 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3822 throw INTERP_KERNEL::Exception(oss.str().c_str());
3824 checkFullyDefined();
3825 int nbCells=getNumberOfCells();
3827 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3828 int nbOfPts=pts->getNumberOfTuples();
3829 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3830 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3831 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3832 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3833 std::vector<double> bbox;
3834 getBoundingBoxForBBTree(bbox);
3839 BBTreeDst<3> myTree(&bbox[0],0,0,nbCells);
3840 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3842 double x=std::numeric_limits<double>::max();
3843 std::vector<int> elems;
3844 myTree.getMinDistanceOfMax(ptsPtr,x);
3845 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3846 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3852 BBTreeDst<2> myTree(&bbox[0],0,0,nbCells);
3853 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3855 double x=std::numeric_limits<double>::max();
3856 std::vector<int> elems;
3857 myTree.getMinDistanceOfMax(ptsPtr,x);
3858 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3859 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3864 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3866 cellIds=ret1.retn();
3871 * \param [in] pt the start pointer (included) of the coordinates of the point
3872 * \param [in] cellIdsBg the start pointer (included) of cellIds
3873 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3874 * \param [in] nc nodal connectivity
3875 * \param [in] ncI nodal connectivity index
3876 * \param [in,out] ret0 the min distance between \a this and the external input point
3877 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3878 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3880 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)
3883 ret0=std::numeric_limits<double>::max();
3884 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3886 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3888 case INTERP_KERNEL::NORM_TRI3:
3890 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3892 { ret0=tmp; cellId=*zeCell; }
3895 case INTERP_KERNEL::NORM_QUAD4:
3896 case INTERP_KERNEL::NORM_POLYGON:
3898 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3900 { ret0=tmp; cellId=*zeCell; }
3904 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3910 * \param [in] pt the start pointer (included) of the coordinates of the point
3911 * \param [in] cellIdsBg the start pointer (included) of cellIds
3912 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3913 * \param [in] nc nodal connectivity
3914 * \param [in] ncI nodal connectivity index
3915 * \param [in,out] ret0 the min distance between \a this and the external input point
3916 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3917 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3919 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)
3922 ret0=std::numeric_limits<double>::max();
3923 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3925 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3927 case INTERP_KERNEL::NORM_SEG2:
3929 std::size_t uselessEntry=0;
3930 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
3933 { ret0=tmp; cellId=*zeCell; }
3937 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3943 * Finds cells in contact with a ball (i.e. a point with precision).
3944 * \warning This method is suitable if the caller intends to evaluate only one
3945 * point, for more points getCellsContainingPoints() is recommended as it is
3947 * \param [in] pos - array of coordinates of the ball central point.
3948 * \param [in] eps - ball radius.
3949 * \return int - a smallest id of cells being in contact with the ball, -1 in case
3950 * if there are no such cells.
3951 * \throw If the coordinates array is not set.
3952 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
3954 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
3956 std::vector<int> elts;
3957 getCellsContainingPoint(pos,eps,elts);
3960 return elts.front();
3964 * Finds cells in contact with a ball (i.e. a point with precision).
3965 * \warning This method is suitable if the caller intends to evaluate only one
3966 * point, for more points getCellsContainingPoints() is recommended as it is
3968 * \param [in] pos - array of coordinates of the ball central point.
3969 * \param [in] eps - ball radius.
3970 * \param [in,out] elts - vector returning ids of the found cells. It is cleared
3971 * before inserting ids.
3972 * \throw If the coordinates array is not set.
3973 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
3975 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
3976 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
3978 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
3980 std::vector<int> eltsIndex;
3981 getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
3986 namespace ParaMEDMEM
3988 template<const int SPACEDIMM>
3992 static const int MY_SPACEDIM=SPACEDIMM;
3993 static const int MY_MESHDIM=8;
3994 typedef int MyConnType;
3995 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
3997 // useless, but for windows compilation ...
3998 const double* getCoordinatesPtr() const { return 0; }
3999 const int* getConnectivityPtr() const { return 0; }
4000 const int* getConnectivityIndexPtr() const { return 0; }
4001 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4005 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4007 INTERP_KERNEL::Edge *ret=0;
4010 case INTERP_KERNEL::NORM_SEG2:
4012 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4015 case INTERP_KERNEL::NORM_SEG3:
4017 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4018 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4019 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4020 bool colinearity=inters.areColinears();
4021 delete e1; delete e2;
4023 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4025 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4026 mapp2[bg[2]].second=false;
4030 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4036 * 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'.
4037 * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4038 * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4040 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4043 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.
4044 const double *coo=mDesc->getCoords()->getConstPointer();
4045 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4046 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4048 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4049 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4050 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4052 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4053 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4055 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4056 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4058 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4059 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4061 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4063 if((*it2).second.second)
4064 mapp[(*it2).second.first]=(*it2).first;
4065 ((*it2).second.first)->decrRef();
4070 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4074 int locId=nodeId-offset2;
4075 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4079 int locId=nodeId-offset1;
4080 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4082 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4085 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4086 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4087 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4089 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4091 int eltId1=abs(*desc1)-1;
4092 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4094 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4095 if(it==mappRev.end())
4097 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4108 template<int SPACEDIM>
4109 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4110 double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4112 std::vector<double> bbox;
4113 eltsIndex.resize(nbOfPoints+1);
4116 getBoundingBoxForBBTree(bbox);
4117 int nbOfCells=getNumberOfCells();
4118 const int *conn=_nodal_connec->getConstPointer();
4119 const int *connI=_nodal_connec_index->getConstPointer();
4120 double bb[2*SPACEDIM];
4121 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4122 for(int i=0;i<nbOfPoints;i++)
4124 eltsIndex[i+1]=eltsIndex[i];
4125 for(int j=0;j<SPACEDIM;j++)
4127 bb[2*j]=pos[SPACEDIM*i+j];
4128 bb[2*j+1]=pos[SPACEDIM*i+j];
4130 std::vector<int> candidates;
4131 myTree.getIntersectingElems(bb,candidates);
4132 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4134 int sz=connI[(*iter)+1]-connI[*iter]-1;
4135 if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4136 (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4137 coords,conn+connI[*iter]+1,sz,eps))
4140 elts.push_back(*iter);
4146 * Finds cells in contact with several balls (i.e. points with precision).
4147 * This method is an extension of getCellContainingPoint() and
4148 * getCellsContainingPoint() for the case of multiple points.
4149 * \param [in] pos - an array of coordinates of points in full interlace mode :
4150 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4151 * this->getSpaceDimension() * \a nbOfPoints
4152 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4153 * \param [in] eps - radius of balls (i.e. the precision).
4154 * \param [in,out] elts - vector returning ids of found cells.
4155 * \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4156 * dividing cell ids in \a elts into groups each referring to one
4157 * point. Its every element (except the last one) is an index pointing to the
4158 * first id of a group of cells. For example cells in contact with the *i*-th
4159 * point are described by following range of indices:
4160 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4161 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4162 * Number of cells in contact with the *i*-th point is
4163 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4164 * \throw If the coordinates array is not set.
4165 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4167 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4168 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4170 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4171 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4173 int spaceDim=getSpaceDimension();
4174 int mDim=getMeshDimension();
4179 const double *coords=_coords->getConstPointer();
4180 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4187 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4189 else if(spaceDim==2)
4193 const double *coords=_coords->getConstPointer();
4194 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4197 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4199 else if(spaceDim==1)
4203 const double *coords=_coords->getConstPointer();
4204 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4207 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4210 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4214 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4215 * least two its edges intersect each other anywhere except their extremities. An
4216 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4217 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4218 * cleared before filling in.
4219 * \param [in] eps - precision.
4220 * \throw If \a this->getMeshDimension() != 2.
4221 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4223 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4225 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4226 if(getMeshDimension()!=2)
4227 throw INTERP_KERNEL::Exception(msg);
4228 int spaceDim=getSpaceDimension();
4229 if(spaceDim!=2 && spaceDim!=3)
4230 throw INTERP_KERNEL::Exception(msg);
4231 const int *conn=_nodal_connec->getConstPointer();
4232 const int *connI=_nodal_connec_index->getConstPointer();
4233 int nbOfCells=getNumberOfCells();
4234 std::vector<double> cell2DinS2;
4235 for(int i=0;i<nbOfCells;i++)
4237 int offset=connI[i];
4238 int nbOfNodesForCell=connI[i+1]-offset-1;
4239 if(nbOfNodesForCell<=3)
4241 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4242 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4243 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4250 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4252 * 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.
4253 * 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.
4255 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4256 * This convex envelop is computed using Jarvis march algorithm.
4257 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4258 * 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)
4259 * 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.
4261 * \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.
4263 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4265 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4266 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4267 checkFullyDefined();
4268 const double *coords=getCoords()->getConstPointer();
4269 int nbOfCells=getNumberOfCells();
4270 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4271 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4272 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4273 int *workIndexOut=nodalConnecIndexOut->getPointer();
4275 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4276 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4277 std::set<INTERP_KERNEL::NormalizedCellType> types;
4278 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4279 isChanged->alloc(0,1);
4280 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4282 int pos=nodalConnecOut->getNumberOfTuples();
4283 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4284 isChanged->pushBackSilent(i);
4285 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4286 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4288 if(isChanged->empty())
4290 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4292 return isChanged.retn();
4296 * This method is \b NOT const because it can modify \a this.
4297 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4298 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4299 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4300 * \b 1 for translation and rotation around point of 'mesh1D'.
4301 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4303 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4305 checkFullyDefined();
4306 mesh1D->checkFullyDefined();
4307 if(!mesh1D->isContiguous1D())
4308 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4309 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4310 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4311 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4312 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4313 if(mesh1D->getMeshDimension()!=1)
4314 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4316 if(isPresenceOfQuadratic())
4318 if(mesh1D->isFullyQuadratic())
4321 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4324 int oldNbOfNodes=getNumberOfNodes();
4325 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4330 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4335 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4339 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4341 setCoords(newCoords);
4342 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4348 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4349 * If it is not the case an exception will be thrown.
4350 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4351 * intersection of plane defined by ('origin','vec').
4352 * This method has one in/out parameter : 'cut3DCurve'.
4353 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4354 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4355 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4356 * This method will throw an exception if \a this contains a non linear segment.
4358 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4360 checkFullyDefined();
4361 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4362 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4363 int ncells=getNumberOfCells();
4364 int nnodes=getNumberOfNodes();
4365 double vec2[3],vec3[3],vec4[3];
4366 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4368 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4369 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4370 const int *conn=_nodal_connec->getConstPointer();
4371 const int *connI=_nodal_connec_index->getConstPointer();
4372 const double *coo=_coords->getConstPointer();
4373 std::vector<double> addCoo;
4374 for(int i=0;i<ncells;i++)
4376 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4378 if(cut3DCurve[i]==-2)
4380 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4381 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];
4382 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4383 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4384 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4386 const double *st2=coo+3*st;
4387 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4388 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]));
4389 if(pos>eps && pos<1-eps)
4391 int nNode=((int)addCoo.size())/3;
4392 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4393 addCoo.insert(addCoo.end(),vec4,vec4+3);
4394 cut3DCurve[i]=nnodes+nNode;
4400 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4404 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4405 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4406 coo2->alloc(newNbOfNodes,3);
4407 double *tmp=coo2->getPointer();
4408 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4409 std::copy(addCoo.begin(),addCoo.end(),tmp);
4410 DataArrayDouble::SetArrayIn(coo2,_coords);
4415 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4416 * \param mesh1D is the input 1D mesh used for translation computation.
4417 * \return newCoords new coords filled by this method.
4419 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4421 int oldNbOfNodes=getNumberOfNodes();
4422 int nbOf1DCells=mesh1D->getNumberOfCells();
4423 int spaceDim=getSpaceDimension();
4424 DataArrayDouble *ret=DataArrayDouble::New();
4425 std::vector<bool> isQuads;
4426 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4427 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4428 double *retPtr=ret->getPointer();
4429 const double *coords=getCoords()->getConstPointer();
4430 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4432 std::vector<double> c;
4436 for(int i=0;i<nbOf1DCells;i++)
4439 mesh1D->getNodeIdsOfCell(i,v);
4441 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4442 mesh1D->getCoordinatesOfNode(v[0],c);
4443 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4444 for(int j=0;j<oldNbOfNodes;j++)
4445 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4449 mesh1D->getCoordinatesOfNode(v[1],c);
4450 mesh1D->getCoordinatesOfNode(v[0],c);
4451 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4452 for(int j=0;j<oldNbOfNodes;j++)
4453 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4456 ret->copyStringInfoFrom(*getCoords());
4461 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4462 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4463 * \return newCoords new coords filled by this method.
4465 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4467 if(mesh1D->getSpaceDimension()==2)
4468 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4469 if(mesh1D->getSpaceDimension()==3)
4470 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4471 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4475 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4476 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4477 * \return newCoords new coords filled by this method.
4479 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4482 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4483 int oldNbOfNodes=getNumberOfNodes();
4484 int nbOf1DCells=mesh1D->getNumberOfCells();
4486 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4487 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4488 int nbOfLevsInVec=nbOf1DCells+1;
4489 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4490 double *retPtr=ret->getPointer();
4491 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4492 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4493 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4494 tmp->setCoords(tmp2);
4495 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4496 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4497 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4498 for(int i=1;i<nbOfLevsInVec;i++)
4500 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4501 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4502 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4503 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4504 tmp->translate(vec);
4505 double tmp3[2],radius,alpha,alpha0;
4506 const double *p0=i+1<nbOfLevsInVec?begin:third;
4507 const double *p1=i+1<nbOfLevsInVec?end:begin;
4508 const double *p2=i+1<nbOfLevsInVec?third:end;
4509 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4510 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]);
4511 double angle=acos(cosangle/(radius*radius));
4512 tmp->rotate(end,0,angle);
4513 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4519 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4520 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4521 * \return newCoords new coords filled by this method.
4523 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4526 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4527 int oldNbOfNodes=getNumberOfNodes();
4528 int nbOf1DCells=mesh1D->getNumberOfCells();
4530 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4531 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4532 int nbOfLevsInVec=nbOf1DCells+1;
4533 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4534 double *retPtr=ret->getPointer();
4535 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4536 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4537 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4538 tmp->setCoords(tmp2);
4539 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4540 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4541 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4542 for(int i=1;i<nbOfLevsInVec;i++)
4544 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4545 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4546 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4547 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4548 tmp->translate(vec);
4549 double tmp3[2],radius,alpha,alpha0;
4550 const double *p0=i+1<nbOfLevsInVec?begin:third;
4551 const double *p1=i+1<nbOfLevsInVec?end:begin;
4552 const double *p2=i+1<nbOfLevsInVec?third:end;
4553 double vecPlane[3]={
4554 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4555 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4556 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4558 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4561 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4562 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4563 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4565 double c2=cos(asin(s2));
4567 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4568 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4569 {-vec2[1]*s2, vec2[0]*s2, c2}
4571 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]};
4572 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]};
4573 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]};
4574 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4575 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]);
4576 double angle=acos(cosangle/(radius*radius));
4577 tmp->rotate(end,vecPlane,angle);
4580 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4586 * This method is private because not easy to use for end user. This method is const contrary to
4587 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4588 * the coords sorted slice by slice.
4589 * \param isQuad specifies presence of quadratic cells.
4591 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4593 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4594 int nbOf2DCells=getNumberOfCells();
4595 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4596 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4597 const int *conn=_nodal_connec->getConstPointer();
4598 const int *connI=_nodal_connec_index->getConstPointer();
4599 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4600 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4601 newConnI->alloc(nbOf3DCells+1,1);
4602 int *newConnIPtr=newConnI->getPointer();
4604 std::vector<int> newc;
4605 for(int j=0;j<nbOf2DCells;j++)
4607 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4608 *newConnIPtr++=(int)newc.size();
4610 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4611 int *newConnPtr=newConn->getPointer();
4612 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4613 newConnIPtr=newConnI->getPointer();
4614 for(int iz=0;iz<nbOf1DCells;iz++)
4617 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4618 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4620 int icell=(int)(iter-newc.begin());
4621 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4624 *newConnPtr=(*iter)+iz*deltaPerLev;
4629 *newConnPtr=(*iter);
4632 ret->setConnectivity(newConn,newConnI,true);
4633 ret->setCoords(getCoords());
4638 * Checks if \a this mesh is constituted by only quadratic cells.
4639 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4640 * \throw If the coordinates array is not set.
4641 * \throw If the nodal connectivity of cells is not defined.
4643 bool MEDCouplingUMesh::isFullyQuadratic() const
4645 checkFullyDefined();
4647 int nbOfCells=getNumberOfCells();
4648 for(int i=0;i<nbOfCells && ret;i++)
4650 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4651 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4652 ret=cm.isQuadratic();
4658 * Checks if \a this mesh includes any quadratic cell.
4659 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4660 * \throw If the coordinates array is not set.
4661 * \throw If the nodal connectivity of cells is not defined.
4663 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4665 checkFullyDefined();
4667 int nbOfCells=getNumberOfCells();
4668 for(int i=0;i<nbOfCells && !ret;i++)
4670 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4671 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4672 ret=cm.isQuadratic();
4678 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4679 * this mesh, it remains unchanged.
4680 * \throw If the coordinates array is not set.
4681 * \throw If the nodal connectivity of cells is not defined.
4683 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4685 checkFullyDefined();
4686 int nbOfCells=getNumberOfCells();
4688 const int *iciptr=_nodal_connec_index->getConstPointer();
4689 for(int i=0;i<nbOfCells;i++)
4691 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4692 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4693 if(cm.isQuadratic())
4695 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4696 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4697 if(!cml.isDynamic())
4698 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4700 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4705 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4706 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4707 const int *icptr=_nodal_connec->getConstPointer();
4708 newConn->alloc(getMeshLength()-delta,1);
4709 newConnI->alloc(nbOfCells+1,1);
4710 int *ocptr=newConn->getPointer();
4711 int *ociptr=newConnI->getPointer();
4714 for(int i=0;i<nbOfCells;i++,ociptr++)
4716 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4717 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4718 if(!cm.isQuadratic())
4720 _types.insert(type);
4721 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4722 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4726 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4727 _types.insert(typel);
4728 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4729 int newNbOfNodes=cml.getNumberOfNodes();
4731 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4732 *ocptr++=(int)typel;
4733 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4734 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4737 setConnectivity(newConn,newConnI,false);
4741 * This method converts all linear cell in \a this to quadratic one.
4742 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4743 * 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)
4744 * 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.
4745 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4746 * end of the existing coordinates.
4748 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4749 * corresponding quadratic cells. 1 is those creating the 'most' complex.
4750 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4752 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4754 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4756 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4758 DataArrayInt *conn=0,*connI=0;
4759 DataArrayDouble *coords=0;
4760 std::set<INTERP_KERNEL::NormalizedCellType> types;
4761 checkFullyDefined();
4762 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4763 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4764 int meshDim=getMeshDimension();
4765 switch(conversionType)
4771 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4772 connSafe=conn; connISafe=connI; coordsSafe=coords;
4775 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4776 connSafe=conn; connISafe=connI; coordsSafe=coords;
4779 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4780 connSafe=conn; connISafe=connI; coordsSafe=coords;
4783 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4791 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4792 connSafe=conn; connISafe=connI; coordsSafe=coords;
4795 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4796 connSafe=conn; connISafe=connI; coordsSafe=coords;
4799 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4800 connSafe=conn; connISafe=connI; coordsSafe=coords;
4803 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4808 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4810 setConnectivity(connSafe,connISafe,false);
4812 setCoords(coordsSafe);
4817 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4818 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4819 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4821 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4823 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4824 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4825 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4826 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4827 int nbOfCells=getNumberOfCells();
4828 int nbOfNodes=getNumberOfNodes();
4829 const int *cPtr=_nodal_connec->getConstPointer();
4830 const int *icPtr=_nodal_connec_index->getConstPointer();
4831 int lastVal=0,offset=nbOfNodes;
4832 for(int i=0;i<nbOfCells;i++,icPtr++)
4834 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4835 if(type==INTERP_KERNEL::NORM_SEG2)
4837 types.insert(INTERP_KERNEL::NORM_SEG3);
4838 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4839 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4840 newConn->pushBackSilent(offset++);
4842 newConnI->pushBackSilent(lastVal);
4843 ret->pushBackSilent(i);
4848 lastVal+=(icPtr[1]-icPtr[0]);
4849 newConnI->pushBackSilent(lastVal);
4850 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4853 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4854 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4858 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)
4860 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4861 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4862 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4864 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4865 DataArrayInt *conn1D=0,*conn1DI=0;
4866 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4867 DataArrayDouble *coordsTmp=0;
4868 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4869 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4870 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4871 const int *c1DPtr=conn1D->begin();
4872 const int *c1DIPtr=conn1DI->begin();
4873 int nbOfCells=getNumberOfCells();
4874 const int *cPtr=_nodal_connec->getConstPointer();
4875 const int *icPtr=_nodal_connec_index->getConstPointer();
4877 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4879 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4880 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4881 if(!cm.isQuadratic())
4883 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4884 types.insert(typ2); newConn->pushBackSilent(typ2);
4885 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4886 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4887 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4888 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4889 newConnI->pushBackSilent(lastVal);
4890 ret->pushBackSilent(i);
4895 lastVal+=(icPtr[1]-icPtr[0]);
4896 newConnI->pushBackSilent(lastVal);
4897 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4900 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4905 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4906 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4907 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4909 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4912 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4913 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4914 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4917 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4919 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4920 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4922 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4923 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4924 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4926 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4927 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4928 DataArrayInt *conn1D=0,*conn1DI=0;
4929 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4930 DataArrayDouble *coordsTmp=0;
4931 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4932 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4933 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4934 const int *c1DPtr=conn1D->begin();
4935 const int *c1DIPtr=conn1DI->begin();
4936 int nbOfCells=getNumberOfCells();
4937 const int *cPtr=_nodal_connec->getConstPointer();
4938 const int *icPtr=_nodal_connec_index->getConstPointer();
4939 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4940 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4942 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4943 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4944 if(!cm.isQuadratic())
4946 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
4947 types.insert(typ2); newConn->pushBackSilent(typ2);
4948 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4949 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4950 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4951 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
4952 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
4953 newConnI->pushBackSilent(lastVal);
4954 ret->pushBackSilent(i);
4959 lastVal+=(icPtr[1]-icPtr[0]);
4960 newConnI->pushBackSilent(lastVal);
4961 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4964 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4965 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
4970 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4971 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4972 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4974 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4976 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4977 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4978 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4981 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4983 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4984 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
4985 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
4986 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
4988 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4989 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4990 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
4992 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4993 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
4994 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
4995 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
4996 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
4997 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
4998 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4999 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5000 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5001 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5002 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5003 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5004 int nbOfCells=getNumberOfCells();
5005 const int *cPtr=_nodal_connec->getConstPointer();
5006 const int *icPtr=_nodal_connec_index->getConstPointer();
5007 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5008 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5010 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5011 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5012 if(!cm.isQuadratic())
5014 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5015 if(typ2==INTERP_KERNEL::NORM_ERROR)
5017 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5018 throw INTERP_KERNEL::Exception(oss.str().c_str());
5020 types.insert(typ2); newConn->pushBackSilent(typ2);
5021 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5022 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5023 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5024 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5026 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5027 int tmpPos=newConn->getNumberOfTuples();
5028 newConn->pushBackSilent(nodeId2);
5029 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5031 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5032 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5033 newConnI->pushBackSilent(lastVal);
5034 ret->pushBackSilent(i);
5039 lastVal+=(icPtr[1]-icPtr[0]);
5040 newConnI->pushBackSilent(lastVal);
5041 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5044 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5045 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5046 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5047 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5048 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5049 int *c=newConn->getPointer();
5050 const int *cI(newConnI->begin());
5051 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5052 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5053 offset=coordsTmp2Safe->getNumberOfTuples();
5054 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5055 c[cI[(*elt)+1]-1]+=offset;
5056 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5061 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5062 * so that the number of cells remains the same. Quadratic faces are converted to
5063 * polygons. This method works only for 2D meshes in
5064 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5065 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5066 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5067 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5068 * a polylinized edge constituting the input polygon.
5069 * \throw If the coordinates array is not set.
5070 * \throw If the nodal connectivity of cells is not defined.
5071 * \throw If \a this->getMeshDimension() != 2.
5072 * \throw If \a this->getSpaceDimension() != 2.
5074 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5076 checkFullyDefined();
5077 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5078 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5079 double epsa=fabs(eps);
5080 if(epsa<std::numeric_limits<double>::min())
5081 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 !");
5082 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5083 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5084 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5085 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5086 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5087 revDesc1=0; revDescIndx1=0;
5088 mDesc->tessellate2DCurve(eps);
5089 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5090 setCoords(mDesc->getCoords());
5094 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5095 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5096 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5097 * a sub-divided edge.
5098 * \throw If the coordinates array is not set.
5099 * \throw If the nodal connectivity of cells is not defined.
5100 * \throw If \a this->getMeshDimension() != 1.
5101 * \throw If \a this->getSpaceDimension() != 2.
5103 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5105 checkFullyDefined();
5106 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5107 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5108 double epsa=fabs(eps);
5109 if(epsa<std::numeric_limits<double>::min())
5110 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 !");
5111 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5112 int nbCells=getNumberOfCells();
5113 int nbNodes=getNumberOfNodes();
5114 const int *conn=_nodal_connec->getConstPointer();
5115 const int *connI=_nodal_connec_index->getConstPointer();
5116 const double *coords=_coords->getConstPointer();
5117 std::vector<double> addCoo;
5118 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5119 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5120 newConnI->alloc(nbCells+1,1);
5121 int *newConnIPtr=newConnI->getPointer();
5124 INTERP_KERNEL::Node *tmp2[3];
5125 std::set<INTERP_KERNEL::NormalizedCellType> types;
5126 for(int i=0;i<nbCells;i++,newConnIPtr++)
5128 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5129 if(cm.isQuadratic())
5130 {//assert(connI[i+1]-connI[i]-1==3)
5131 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5132 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5133 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5134 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5135 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5138 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5139 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5141 newConnIPtr[1]=(int)newConn.size();
5145 types.insert(INTERP_KERNEL::NORM_SEG2);
5146 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5147 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5148 newConnIPtr[1]=newConnIPtr[0]+3;
5153 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5154 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5155 newConnIPtr[1]=newConnIPtr[0]+3;
5158 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5161 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5162 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5163 newConnArr->alloc((int)newConn.size(),1);
5164 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5165 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5166 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5167 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5168 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5169 std::copy(addCoo.begin(),addCoo.end(),work);
5170 DataArrayDouble::SetArrayIn(newCoords,_coords);
5175 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5176 * In addition, returns an array mapping new cells to old ones. <br>
5177 * This method typically increases the number of cells in \a this mesh
5178 * but the number of nodes remains \b unchanged.
5179 * That's why the 3D splitting policies
5180 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5181 * \param [in] policy - specifies a pattern used for splitting.
5182 * The semantic of \a policy is:
5183 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5184 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5185 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5186 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5187 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5188 * an id of old cell producing it. The caller is to delete this array using
5189 * decrRef() as it is no more needed.
5190 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5191 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5192 * and \a this->getMeshDimension() != 3.
5193 * \throw If \a policy is not one of the four discussed above.
5194 * \throw If the nodal connectivity of cells is not defined.
5196 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5201 return simplexizePol0();
5203 return simplexizePol1();
5204 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5205 return simplexizePlanarFace5();
5206 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5207 return simplexizePlanarFace6();
5209 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)");
5214 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5215 * - 1D: INTERP_KERNEL::NORM_SEG2
5216 * - 2D: INTERP_KERNEL::NORM_TRI3
5217 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5219 * This method is useful for users that need to use P1 field services as
5220 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5221 * All these methods need mesh support containing only simplex cells.
5222 * \return bool - \c true if there are only simplex cells in \a this mesh.
5223 * \throw If the coordinates array is not set.
5224 * \throw If the nodal connectivity of cells is not defined.
5225 * \throw If \a this->getMeshDimension() < 1.
5227 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5229 checkFullyDefined();
5230 int mdim=getMeshDimension();
5231 if(mdim<1 || mdim>3)
5232 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5233 int nbCells=getNumberOfCells();
5234 const int *conn=_nodal_connec->getConstPointer();
5235 const int *connI=_nodal_connec_index->getConstPointer();
5236 for(int i=0;i<nbCells;i++)
5238 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5246 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5248 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5250 checkConnectivityFullyDefined();
5251 if(getMeshDimension()!=2)
5252 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5253 int nbOfCells=getNumberOfCells();
5254 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5255 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5256 ret->alloc(nbOfCells+nbOfCutCells,1);
5257 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5258 int *retPt=ret->getPointer();
5259 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5260 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5261 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5262 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5263 int *pt=newConn->getPointer();
5264 int *ptI=newConnI->getPointer();
5266 const int *oldc=_nodal_connec->getConstPointer();
5267 const int *ci=_nodal_connec_index->getConstPointer();
5268 for(int i=0;i<nbOfCells;i++,ci++)
5270 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5272 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5273 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5274 pt=std::copy(tmp,tmp+8,pt);
5283 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5284 ptI[1]=ptI[0]+ci[1]-ci[0];
5289 _nodal_connec->decrRef();
5290 _nodal_connec=newConn.retn();
5291 _nodal_connec_index->decrRef();
5292 _nodal_connec_index=newConnI.retn();
5299 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5301 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5303 checkConnectivityFullyDefined();
5304 if(getMeshDimension()!=2)
5305 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5306 int nbOfCells=getNumberOfCells();
5307 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5308 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5309 ret->alloc(nbOfCells+nbOfCutCells,1);
5310 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5311 int *retPt=ret->getPointer();
5312 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5313 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5314 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5315 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5316 int *pt=newConn->getPointer();
5317 int *ptI=newConnI->getPointer();
5319 const int *oldc=_nodal_connec->getConstPointer();
5320 const int *ci=_nodal_connec_index->getConstPointer();
5321 for(int i=0;i<nbOfCells;i++,ci++)
5323 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5325 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5326 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5327 pt=std::copy(tmp,tmp+8,pt);
5336 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5337 ptI[1]=ptI[0]+ci[1]-ci[0];
5342 _nodal_connec->decrRef();
5343 _nodal_connec=newConn.retn();
5344 _nodal_connec_index->decrRef();
5345 _nodal_connec_index=newConnI.retn();
5352 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5354 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5356 checkConnectivityFullyDefined();
5357 if(getMeshDimension()!=3)
5358 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5359 int nbOfCells=getNumberOfCells();
5360 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5361 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5362 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5363 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5364 int *retPt=ret->getPointer();
5365 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5366 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5367 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5368 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5369 int *pt=newConn->getPointer();
5370 int *ptI=newConnI->getPointer();
5372 const int *oldc=_nodal_connec->getConstPointer();
5373 const int *ci=_nodal_connec_index->getConstPointer();
5374 for(int i=0;i<nbOfCells;i++,ci++)
5376 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5378 for(int j=0;j<5;j++,pt+=5,ptI++)
5380 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5381 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];
5388 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5389 ptI[1]=ptI[0]+ci[1]-ci[0];
5394 _nodal_connec->decrRef();
5395 _nodal_connec=newConn.retn();
5396 _nodal_connec_index->decrRef();
5397 _nodal_connec_index=newConnI.retn();
5404 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5406 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5408 checkConnectivityFullyDefined();
5409 if(getMeshDimension()!=3)
5410 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5411 int nbOfCells=getNumberOfCells();
5412 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5413 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5414 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5415 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5416 int *retPt=ret->getPointer();
5417 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5418 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5419 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5420 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5421 int *pt=newConn->getPointer();
5422 int *ptI=newConnI->getPointer();
5424 const int *oldc=_nodal_connec->getConstPointer();
5425 const int *ci=_nodal_connec_index->getConstPointer();
5426 for(int i=0;i<nbOfCells;i++,ci++)
5428 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5430 for(int j=0;j<6;j++,pt+=5,ptI++)
5432 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5433 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];
5440 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5441 ptI[1]=ptI[0]+ci[1]-ci[0];
5446 _nodal_connec->decrRef();
5447 _nodal_connec=newConn.retn();
5448 _nodal_connec_index->decrRef();
5449 _nodal_connec_index=newConnI.retn();
5456 * 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.
5457 * This method completly ignore coordinates.
5458 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5459 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5460 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5461 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5463 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5465 checkFullyDefined();
5466 if(getMeshDimension()!=2)
5467 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5468 int nbOfCells=getNumberOfCells();
5469 int *connI=_nodal_connec_index->getPointer();
5471 for(int i=0;i<nbOfCells;i++,connI++)
5473 int offset=descIndex[i];
5474 int nbOfEdges=descIndex[i+1]-offset;
5476 bool ddirect=desc[offset+nbOfEdges-1]>0;
5477 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5478 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5479 for(int j=0;j<nbOfEdges;j++)
5481 bool direct=desc[offset+j]>0;
5482 int edgeId=std::abs(desc[offset+j])-1;
5483 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5485 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5486 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5487 int ref2=direct?id1:id2;
5490 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5491 newConnLgth+=nbOfSubNodes-1;
5496 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5497 throw INTERP_KERNEL::Exception(oss.str().c_str());
5502 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5505 newConnLgth++;//+1 is for cell type
5506 connI[1]=newConnLgth;
5509 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5510 newConn->alloc(newConnLgth,1);
5511 int *work=newConn->getPointer();
5512 for(int i=0;i<nbOfCells;i++)
5514 *work++=INTERP_KERNEL::NORM_POLYGON;
5515 int offset=descIndex[i];
5516 int nbOfEdges=descIndex[i+1]-offset;
5517 for(int j=0;j<nbOfEdges;j++)
5519 bool direct=desc[offset+j]>0;
5520 int edgeId=std::abs(desc[offset+j])-1;
5522 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5525 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5526 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5527 work=std::copy(it,it+nbOfSubNodes-1,work);
5531 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5534 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5538 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5539 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5540 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5541 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5542 * so it can be useful to call mergeNodes() before calling this method.
5543 * \throw If \a this->getMeshDimension() <= 1.
5544 * \throw If the coordinates array is not set.
5545 * \throw If the nodal connectivity of cells is not defined.
5547 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5549 checkFullyDefined();
5550 if(getMeshDimension()<=1)
5551 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5552 int nbOfCells=getNumberOfCells();
5555 int initMeshLgth=getMeshLength();
5556 int *conn=_nodal_connec->getPointer();
5557 int *index=_nodal_connec_index->getPointer();
5561 for(int i=0;i<nbOfCells;i++)
5563 lgthOfCurCell=index[i+1]-posOfCurCell;
5564 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5566 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5567 conn+newPos+1,newLgth);
5568 conn[newPos]=newType;
5570 posOfCurCell=index[i+1];
5573 if(newPos!=initMeshLgth)
5574 _nodal_connec->reAlloc(newPos);
5579 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5580 * A cell is considered to be oriented correctly if an angle between its
5581 * normal vector and a given vector is less than \c PI / \c 2.
5582 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5584 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5586 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5587 * is not cleared before filling in.
5588 * \throw If \a this->getMeshDimension() != 2.
5589 * \throw If \a this->getSpaceDimension() != 3.
5591 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5592 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5594 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5596 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5597 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5598 int nbOfCells=getNumberOfCells();
5599 const int *conn=_nodal_connec->getConstPointer();
5600 const int *connI=_nodal_connec_index->getConstPointer();
5601 const double *coordsPtr=_coords->getConstPointer();
5602 for(int i=0;i<nbOfCells;i++)
5604 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5605 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5607 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5608 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5615 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5616 * considered to be oriented correctly if an angle between its normal vector and a
5617 * given vector is less than \c PI / \c 2.
5618 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5620 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5622 * \throw If \a this->getMeshDimension() != 2.
5623 * \throw If \a this->getSpaceDimension() != 3.
5625 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5626 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5628 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5630 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5631 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5632 int nbOfCells=getNumberOfCells();
5633 int *conn=_nodal_connec->getPointer();
5634 const int *connI=_nodal_connec_index->getConstPointer();
5635 const double *coordsPtr=_coords->getConstPointer();
5636 bool isModified=false;
5637 for(int i=0;i<nbOfCells;i++)
5639 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5640 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5642 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5643 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5646 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5647 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5648 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5653 _nodal_connec->declareAsNew();
5658 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5659 * oriented facets. The normal vector of the facet should point out of the cell.
5660 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5661 * is not cleared before filling in.
5662 * \throw If \a this->getMeshDimension() != 3.
5663 * \throw If \a this->getSpaceDimension() != 3.
5664 * \throw If the coordinates array is not set.
5665 * \throw If the nodal connectivity of cells is not defined.
5667 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5668 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5670 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5672 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5673 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5674 int nbOfCells=getNumberOfCells();
5675 const int *conn=_nodal_connec->getConstPointer();
5676 const int *connI=_nodal_connec_index->getConstPointer();
5677 const double *coordsPtr=_coords->getConstPointer();
5678 for(int i=0;i<nbOfCells;i++)
5680 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5681 if(type==INTERP_KERNEL::NORM_POLYHED)
5683 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5690 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5692 * \throw If \a this->getMeshDimension() != 3.
5693 * \throw If \a this->getSpaceDimension() != 3.
5694 * \throw If the coordinates array is not set.
5695 * \throw If the nodal connectivity of cells is not defined.
5696 * \throw If the reparation fails.
5698 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5699 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5700 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5702 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5704 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5705 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5706 int nbOfCells=getNumberOfCells();
5707 int *conn=_nodal_connec->getPointer();
5708 const int *connI=_nodal_connec_index->getConstPointer();
5709 const double *coordsPtr=_coords->getConstPointer();
5710 for(int i=0;i<nbOfCells;i++)
5712 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5713 if(type==INTERP_KERNEL::NORM_POLYHED)
5717 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5718 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5720 catch(INTERP_KERNEL::Exception& e)
5722 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5723 throw INTERP_KERNEL::Exception(oss.str().c_str());
5731 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5732 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5733 * according to which the first facet of the cell should be oriented to have the normal vector
5734 * pointing out of cell.
5735 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5736 * cells. The caller is to delete this array using decrRef() as it is no more
5738 * \throw If \a this->getMeshDimension() != 3.
5739 * \throw If \a this->getSpaceDimension() != 3.
5740 * \throw If the coordinates array is not set.
5741 * \throw If the nodal connectivity of cells is not defined.
5743 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5744 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5745 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5747 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5749 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5750 if(getMeshDimension()!=3)
5751 throw INTERP_KERNEL::Exception(msg);
5752 int spaceDim=getSpaceDimension();
5754 throw INTERP_KERNEL::Exception(msg);
5756 int nbOfCells=getNumberOfCells();
5757 int *conn=_nodal_connec->getPointer();
5758 const int *connI=_nodal_connec_index->getConstPointer();
5759 const double *coo=getCoords()->getConstPointer();
5760 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5761 for(int i=0;i<nbOfCells;i++)
5763 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5764 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5766 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5768 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5769 cells->pushBackSilent(i);
5773 return cells.retn();
5777 * This method is a faster method to correct orientation of all 3D cells in \a this.
5778 * 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.
5779 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5781 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5782 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
5784 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5786 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5787 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5788 int nbOfCells=getNumberOfCells();
5789 int *conn=_nodal_connec->getPointer();
5790 const int *connI=_nodal_connec_index->getConstPointer();
5791 const double *coordsPtr=_coords->getConstPointer();
5792 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5793 for(int i=0;i<nbOfCells;i++)
5795 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5798 case INTERP_KERNEL::NORM_TETRA4:
5800 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5802 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5803 ret->pushBackSilent(i);
5807 case INTERP_KERNEL::NORM_PYRA5:
5809 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5811 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5812 ret->pushBackSilent(i);
5816 case INTERP_KERNEL::NORM_PENTA6:
5817 case INTERP_KERNEL::NORM_HEXA8:
5818 case INTERP_KERNEL::NORM_HEXGP12:
5820 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5822 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5823 ret->pushBackSilent(i);
5827 case INTERP_KERNEL::NORM_POLYHED:
5829 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5831 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5832 ret->pushBackSilent(i);
5837 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 !");
5845 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5846 * If it is not the case an exception will be thrown.
5847 * This method is fast because the first cell of \a this is used to compute the plane.
5848 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5849 * \param pos output of size at least 3 used to store a point owned of searched plane.
5851 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5853 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5854 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5855 const int *conn=_nodal_connec->getConstPointer();
5856 const int *connI=_nodal_connec_index->getConstPointer();
5857 const double *coordsPtr=_coords->getConstPointer();
5858 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5859 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5863 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5864 * cells. Currently cells of the following types are treated:
5865 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5866 * For a cell of other type an exception is thrown.
5867 * Space dimension of a 2D mesh can be either 2 or 3.
5868 * The Edge Ratio of a cell \f$t\f$ is:
5869 * \f$\frac{|t|_\infty}{|t|_0}\f$,
5870 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5871 * the smallest edge lengths of \f$t\f$.
5872 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5873 * cells and one time, lying on \a this mesh. The caller is to delete this
5874 * field using decrRef() as it is no more needed.
5875 * \throw If the coordinates array is not set.
5876 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5877 * \throw If the connectivity data array has more than one component.
5878 * \throw If the connectivity data array has a named component.
5879 * \throw If the connectivity index data array has more than one component.
5880 * \throw If the connectivity index data array has a named component.
5881 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
5882 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5883 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
5885 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5888 int spaceDim=getSpaceDimension();
5889 int meshDim=getMeshDimension();
5890 if(spaceDim!=2 && spaceDim!=3)
5891 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5892 if(meshDim!=2 && meshDim!=3)
5893 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5894 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5896 int nbOfCells=getNumberOfCells();
5897 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5898 arr->alloc(nbOfCells,1);
5899 double *pt=arr->getPointer();
5900 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5901 const int *conn=_nodal_connec->getConstPointer();
5902 const int *connI=_nodal_connec_index->getConstPointer();
5903 const double *coo=_coords->getConstPointer();
5905 for(int i=0;i<nbOfCells;i++,pt++)
5907 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5910 case INTERP_KERNEL::NORM_TRI3:
5912 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5913 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5916 case INTERP_KERNEL::NORM_QUAD4:
5918 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5919 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5922 case INTERP_KERNEL::NORM_TETRA4:
5924 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5925 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5929 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5931 conn+=connI[i+1]-connI[i];
5933 ret->setName("EdgeRatio");
5934 ret->synchronizeTimeWithSupport();
5939 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5940 * cells. Currently cells of the following types are treated:
5941 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5942 * For a cell of other type an exception is thrown.
5943 * Space dimension of a 2D mesh can be either 2 or 3.
5944 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5945 * cells and one time, lying on \a this mesh. The caller is to delete this
5946 * field using decrRef() as it is no more needed.
5947 * \throw If the coordinates array is not set.
5948 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5949 * \throw If the connectivity data array has more than one component.
5950 * \throw If the connectivity data array has a named component.
5951 * \throw If the connectivity index data array has more than one component.
5952 * \throw If the connectivity index data array has a named component.
5953 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
5954 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5955 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
5957 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
5960 int spaceDim=getSpaceDimension();
5961 int meshDim=getMeshDimension();
5962 if(spaceDim!=2 && spaceDim!=3)
5963 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
5964 if(meshDim!=2 && meshDim!=3)
5965 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
5966 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5968 int nbOfCells=getNumberOfCells();
5969 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5970 arr->alloc(nbOfCells,1);
5971 double *pt=arr->getPointer();
5972 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5973 const int *conn=_nodal_connec->getConstPointer();
5974 const int *connI=_nodal_connec_index->getConstPointer();
5975 const double *coo=_coords->getConstPointer();
5977 for(int i=0;i<nbOfCells;i++,pt++)
5979 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5982 case INTERP_KERNEL::NORM_TRI3:
5984 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5985 *pt=INTERP_KERNEL::triAspectRatio(tmp);
5988 case INTERP_KERNEL::NORM_QUAD4:
5990 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5991 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
5994 case INTERP_KERNEL::NORM_TETRA4:
5996 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5997 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6001 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6003 conn+=connI[i+1]-connI[i];
6005 ret->setName("AspectRatio");
6006 ret->synchronizeTimeWithSupport();
6011 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6012 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6013 * treated: INTERP_KERNEL::NORM_QUAD4.
6014 * For a cell of other type an exception is thrown.
6015 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6016 * cells and one time, lying on \a this mesh. The caller is to delete this
6017 * field using decrRef() as it is no more needed.
6018 * \throw If the coordinates array is not set.
6019 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6020 * \throw If the connectivity data array has more than one component.
6021 * \throw If the connectivity data array has a named component.
6022 * \throw If the connectivity index data array has more than one component.
6023 * \throw If the connectivity index data array has a named component.
6024 * \throw If \a this->getMeshDimension() != 2.
6025 * \throw If \a this->getSpaceDimension() != 3.
6026 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6028 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6031 int spaceDim=getSpaceDimension();
6032 int meshDim=getMeshDimension();
6034 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6036 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6037 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6039 int nbOfCells=getNumberOfCells();
6040 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6041 arr->alloc(nbOfCells,1);
6042 double *pt=arr->getPointer();
6043 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6044 const int *conn=_nodal_connec->getConstPointer();
6045 const int *connI=_nodal_connec_index->getConstPointer();
6046 const double *coo=_coords->getConstPointer();
6048 for(int i=0;i<nbOfCells;i++,pt++)
6050 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6053 case INTERP_KERNEL::NORM_QUAD4:
6055 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6056 *pt=INTERP_KERNEL::quadWarp(tmp);
6060 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6062 conn+=connI[i+1]-connI[i];
6064 ret->setName("Warp");
6065 ret->synchronizeTimeWithSupport();
6071 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6072 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6073 * treated: INTERP_KERNEL::NORM_QUAD4.
6074 * For a cell of other type an exception is thrown.
6075 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6076 * cells and one time, lying on \a this mesh. The caller is to delete this
6077 * field using decrRef() as it is no more needed.
6078 * \throw If the coordinates array is not set.
6079 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6080 * \throw If the connectivity data array has more than one component.
6081 * \throw If the connectivity data array has a named component.
6082 * \throw If the connectivity index data array has more than one component.
6083 * \throw If the connectivity index data array has a named component.
6084 * \throw If \a this->getMeshDimension() != 2.
6085 * \throw If \a this->getSpaceDimension() != 3.
6086 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6088 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6091 int spaceDim=getSpaceDimension();
6092 int meshDim=getMeshDimension();
6094 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6096 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6097 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6099 int nbOfCells=getNumberOfCells();
6100 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6101 arr->alloc(nbOfCells,1);
6102 double *pt=arr->getPointer();
6103 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6104 const int *conn=_nodal_connec->getConstPointer();
6105 const int *connI=_nodal_connec_index->getConstPointer();
6106 const double *coo=_coords->getConstPointer();
6108 for(int i=0;i<nbOfCells;i++,pt++)
6110 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6113 case INTERP_KERNEL::NORM_QUAD4:
6115 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6116 *pt=INTERP_KERNEL::quadSkew(tmp);
6120 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6122 conn+=connI[i+1]-connI[i];
6124 ret->setName("Skew");
6125 ret->synchronizeTimeWithSupport();
6130 * This method aggregate the bbox of each cell and put it into bbox parameter.
6131 * \param bbox out parameter of size 2*spacedim*nbOfcells.
6133 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6135 int spaceDim=getSpaceDimension();
6136 int nbOfCells=getNumberOfCells();
6137 bbox.resize(2*nbOfCells*spaceDim);
6138 for(int i=0;i<nbOfCells*spaceDim;i++)
6140 bbox[2*i]=std::numeric_limits<double>::max();
6141 bbox[2*i+1]=-std::numeric_limits<double>::max();
6143 const double *coordsPtr=_coords->getConstPointer();
6144 const int *conn=_nodal_connec->getConstPointer();
6145 const int *connI=_nodal_connec_index->getConstPointer();
6146 for(int i=0;i<nbOfCells;i++)
6148 int offset=connI[i]+1;
6149 int nbOfNodesForCell=connI[i+1]-offset;
6150 for(int j=0;j<nbOfNodesForCell;j++)
6152 int nodeId=conn[offset+j];
6154 for(int k=0;k<spaceDim;k++)
6156 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6157 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6165 namespace ParaMEDMEMImpl
6170 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6171 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6180 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6181 bool operator() (const int& pos) { return _conn[pos]==_val; }
6191 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6192 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6193 * \a this is composed in cell types.
6194 * The returned array is of size 3*n where n is the number of different types present in \a this.
6195 * For every k in [0,n] ret[3*k+2]==0 because it has no sense here.
6196 * This parameter is kept only for compatibility with other methode listed above.
6198 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6200 checkConnectivityFullyDefined();
6201 const int *conn=_nodal_connec->getConstPointer();
6202 const int *connI=_nodal_connec_index->getConstPointer();
6203 const int *work=connI;
6204 int nbOfCells=getNumberOfCells();
6205 std::size_t n=getAllTypes().size();
6206 std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
6207 std::set<INTERP_KERNEL::NormalizedCellType> types;
6208 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6210 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6211 if(types.find(typ)!=types.end())
6213 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6214 oss << " is not contiguous !";
6215 throw INTERP_KERNEL::Exception(oss.str().c_str());
6219 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6220 ret[3*i+1]=(int)std::distance(work,work2);
6227 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6228 * only for types cell, type node is not managed.
6229 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6230 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6231 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6232 * If 2 or more same geometric type is in \a code and exception is thrown too.
6234 * This method firstly checks
6235 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6236 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6237 * an exception is thrown too.
6239 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6240 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6241 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6243 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6246 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6247 std::size_t sz=code.size();
6250 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6251 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6253 bool isNoPflUsed=true;
6254 for(std::size_t i=0;i<n;i++)
6255 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6257 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6259 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6260 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6261 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6264 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6267 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6268 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6269 if(types.size()==_types.size())
6272 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6274 int *retPtr=ret->getPointer();
6275 const int *connI=_nodal_connec_index->getConstPointer();
6276 const int *conn=_nodal_connec->getConstPointer();
6277 int nbOfCells=getNumberOfCells();
6280 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6282 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6283 int offset=(int)std::distance(connI,i);
6284 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6285 int nbOfCellsOfCurType=(int)std::distance(i,j);
6286 if(code[3*kk+2]==-1)
6287 for(int k=0;k<nbOfCellsOfCurType;k++)
6291 int idInIdsPerType=code[3*kk+2];
6292 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6294 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6297 zePfl->checkAllocated();
6298 if(zePfl->getNumberOfComponents()==1)
6300 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6302 if(*k>=0 && *k<nbOfCellsOfCurType)
6303 *retPtr=(*k)+offset;
6306 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6307 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6308 throw INTERP_KERNEL::Exception(oss.str().c_str());
6313 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6316 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6320 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6321 oss << " should be in [0," << idsPerType.size() << ") !";
6322 throw INTERP_KERNEL::Exception(oss.str().c_str());
6331 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6332 * 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.
6333 * 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.
6334 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6336 * \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.
6337 * \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,
6338 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6339 * \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.
6340 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6341 * \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
6343 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6346 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6347 if(profile->getNumberOfComponents()!=1)
6348 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6349 checkConnectivityFullyDefined();
6350 const int *conn=_nodal_connec->getConstPointer();
6351 const int *connI=_nodal_connec_index->getConstPointer();
6352 int nbOfCells=getNumberOfCells();
6353 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6354 std::vector<int> typeRangeVals(1);
6355 for(const int *i=connI;i!=connI+nbOfCells;)
6357 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6358 if(std::find(types.begin(),types.end(),curType)!=types.end())
6360 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6362 types.push_back(curType);
6363 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6364 typeRangeVals.push_back((int)std::distance(connI,i));
6367 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6368 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6369 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6370 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6371 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6373 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6374 code.resize(3*nbOfCastsFinal);
6375 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6376 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6377 for(int i=0;i<nbOfCastsFinal;i++)
6379 int castId=castsPresent->getIJ(i,0);
6380 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6381 idsInPflPerType2.push_back(tmp3);
6382 code[3*i]=(int)types[castId];
6383 code[3*i+1]=tmp3->getNumberOfTuples();
6384 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6385 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6387 tmp4->copyStringInfoFrom(*profile);
6388 idsPerType2.push_back(tmp4);
6389 code[3*i+2]=(int)idsPerType2.size()-1;
6396 std::size_t sz2=idsInPflPerType2.size();
6397 idsInPflPerType.resize(sz2);
6398 for(std::size_t i=0;i<sz2;i++)
6400 DataArrayInt *locDa=idsInPflPerType2[i];
6402 idsInPflPerType[i]=locDa;
6404 std::size_t sz=idsPerType2.size();
6405 idsPerType.resize(sz);
6406 for(std::size_t i=0;i<sz;i++)
6408 DataArrayInt *locDa=idsPerType2[i];
6410 idsPerType[i]=locDa;
6415 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6416 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6417 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6418 * 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.
6420 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6422 checkFullyDefined();
6423 nM1LevMesh->checkFullyDefined();
6424 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6425 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6426 if(_coords!=nM1LevMesh->getCoords())
6427 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6428 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6429 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6430 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6431 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6432 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6433 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6434 tmp->setConnectivity(tmp0,tmp1);
6435 tmp->renumberCells(ret0->getConstPointer(),false);
6436 revDesc=tmp->getNodalConnectivity();
6437 revDescIndx=tmp->getNodalConnectivityIndex();
6438 DataArrayInt *ret=0;
6439 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6442 ret->getMaxValue(tmp2);
6444 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6445 throw INTERP_KERNEL::Exception(oss.str().c_str());
6450 revDescIndx->incrRef();
6453 meshnM1Old2New=ret0;
6458 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6459 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6460 * in "Old to New" mode.
6461 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6462 * this array using decrRef() as it is no more needed.
6463 * \throw If the nodal connectivity of cells is not defined.
6465 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6467 checkConnectivityFullyDefined();
6468 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6469 renumberCells(ret->getConstPointer(),false);
6474 * This methods checks that cells are sorted by their types.
6475 * This method makes asumption (no check) that connectivity is correctly set before calling.
6477 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6479 checkFullyDefined();
6480 const int *conn=_nodal_connec->getConstPointer();
6481 const int *connI=_nodal_connec_index->getConstPointer();
6482 int nbOfCells=getNumberOfCells();
6483 std::set<INTERP_KERNEL::NormalizedCellType> types;
6484 for(const int *i=connI;i!=connI+nbOfCells;)
6486 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6487 if(types.find(curType)!=types.end())
6489 types.insert(curType);
6490 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6496 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6497 * The geometric type order is specified by MED file.
6499 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6501 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6503 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6507 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6508 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6509 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6510 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6512 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6514 checkFullyDefined();
6515 const int *conn=_nodal_connec->getConstPointer();
6516 const int *connI=_nodal_connec_index->getConstPointer();
6517 int nbOfCells=getNumberOfCells();
6521 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6522 for(const int *i=connI;i!=connI+nbOfCells;)
6524 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6525 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6526 if(isTypeExists!=orderEnd)
6528 int pos=(int)std::distance(orderBg,isTypeExists);
6532 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6536 if(sg.find(curType)==sg.end())
6538 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6549 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6550 * 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
6551 * 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'.
6553 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6555 checkConnectivityFullyDefined();
6556 int nbOfCells=getNumberOfCells();
6557 const int *conn=_nodal_connec->getConstPointer();
6558 const int *connI=_nodal_connec_index->getConstPointer();
6559 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6560 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6561 tmpa->alloc(nbOfCells,1);
6562 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6563 tmpb->fillWithZero();
6564 int *tmp=tmpa->getPointer();
6565 int *tmp2=tmpb->getPointer();
6566 for(const int *i=connI;i!=connI+nbOfCells;i++)
6568 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6571 int pos=(int)std::distance(orderBg,where);
6573 tmp[std::distance(connI,i)]=pos;
6577 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6578 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6579 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6580 throw INTERP_KERNEL::Exception(oss.str().c_str());
6583 nbPerType=tmpb.retn();
6588 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6590 * \return a new object containing the old to new correspondance.
6592 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6594 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6596 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6600 * 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.
6601 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6602 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6603 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6605 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6607 DataArrayInt *nbPerType=0;
6608 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6609 nbPerType->decrRef();
6610 return tmpa->buildPermArrPerLevel();
6614 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6615 * The number of cells remains unchanged after the call of this method.
6616 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6617 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6619 * \return the array giving the correspondance old to new.
6621 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6623 checkFullyDefined();
6625 const int *conn=_nodal_connec->getConstPointer();
6626 const int *connI=_nodal_connec_index->getConstPointer();
6627 int nbOfCells=getNumberOfCells();
6628 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6629 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6630 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6632 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6633 types.push_back(curType);
6634 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6636 DataArrayInt *ret=DataArrayInt::New();
6637 ret->alloc(nbOfCells,1);
6638 int *retPtr=ret->getPointer();
6639 std::fill(retPtr,retPtr+nbOfCells,-1);
6641 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6643 for(const int *i=connI;i!=connI+nbOfCells;i++)
6644 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6645 retPtr[std::distance(connI,i)]=newCellId++;
6647 renumberCells(retPtr,false);
6652 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6653 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6654 * This method makes asumption that connectivity is correctly set before calling.
6656 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6658 checkFullyDefined();
6659 const int *conn=_nodal_connec->getConstPointer();
6660 const int *connI=_nodal_connec_index->getConstPointer();
6661 int nbOfCells=getNumberOfCells();
6662 std::vector<MEDCouplingUMesh *> ret;
6663 for(const int *i=connI;i!=connI+nbOfCells;)
6665 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6666 int beginCellId=(int)std::distance(connI,i);
6667 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6668 int endCellId=(int)std::distance(connI,i);
6669 int sz=endCellId-beginCellId;
6670 int *cells=new int[sz];
6671 for(int j=0;j<sz;j++)
6672 cells[j]=beginCellId+j;
6673 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6681 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6682 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6683 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6685 * \return a newly allocated instance, that the caller must manage.
6686 * \throw If \a this contains more than one geometric type.
6687 * \throw If the nodal connectivity of \a this is not fully defined.
6688 * \throw If the internal data is not coherent.
6690 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6692 checkConnectivityFullyDefined();
6693 if(_types.size()!=1)
6694 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6695 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6696 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6697 ret->setCoords(getCoords());
6698 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6701 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6702 retC->setNodalConnectivity(c);
6706 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6708 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6709 DataArrayInt *c=0,*ci=0;
6710 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6711 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6712 retD->setNodalConnectivity(cs,cis);
6717 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6719 checkConnectivityFullyDefined();
6720 if(_types.size()!=1)
6721 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6722 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6723 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6726 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6727 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6728 throw INTERP_KERNEL::Exception(oss.str().c_str());
6730 int nbCells=getNumberOfCells();
6732 int nbNodesPerCell=(int)cm.getNumberOfNodes();
6733 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6734 int *outPtr=connOut->getPointer();
6735 const int *conn=_nodal_connec->begin();
6736 const int *connI=_nodal_connec_index->begin();
6738 for(int i=0;i<nbCells;i++,connI++)
6740 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6741 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6744 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : there something wrong in cell #" << i << " ! The type of cell is not those expected, or the length of nodal connectivity is not those expected (" << nbNodesPerCell-1 << ") !";
6745 throw INTERP_KERNEL::Exception(oss.str().c_str());
6748 return connOut.retn();
6751 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const throw(INTERP_KERNEL::Exception)
6753 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
6754 checkConnectivityFullyDefined();
6755 if(_types.size()!=1)
6756 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6757 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6759 throw INTERP_KERNEL::Exception(msg0);
6760 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6761 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6762 int *cp(c->getPointer()),*cip(ci->getPointer());
6763 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6765 for(int i=0;i<nbCells;i++,cip++,incip++)
6767 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6768 int delta(stop-strt);
6771 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6772 cp=std::copy(incp+strt,incp+stop,cp);
6774 throw INTERP_KERNEL::Exception(msg0);
6777 throw INTERP_KERNEL::Exception(msg0);
6778 cip[1]=cip[0]+delta;
6780 nodalConn=c.retn(); nodalConnIndex=ci.retn();
6784 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6785 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6786 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6787 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6788 * are not used here to avoid the build of big permutation array.
6790 * \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
6791 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6792 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6793 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6794 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6795 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
6796 * \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
6797 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6799 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6800 DataArrayInt *&szOfCellGrpOfSameType,
6801 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6803 std::vector<const MEDCouplingUMesh *> ms2;
6804 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6807 (*it)->checkConnectivityFullyDefined();
6811 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6812 const DataArrayDouble *refCoo=ms2[0]->getCoords();
6813 int meshDim=ms2[0]->getMeshDimension();
6814 std::vector<const MEDCouplingUMesh *> m1ssm;
6815 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6817 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6818 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6820 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6821 ret1->alloc(0,1); ret2->alloc(0,1);
6822 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6824 if(meshDim!=(*it)->getMeshDimension())
6825 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6826 if(refCoo!=(*it)->getCoords())
6827 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6828 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6829 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6830 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6831 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6833 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6834 m1ssmSingleAuto.push_back(singleCell);
6835 m1ssmSingle.push_back(singleCell);
6836 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6839 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6840 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6841 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6842 for(std::size_t i=0;i<m1ssm.size();i++)
6843 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6844 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6845 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6846 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6851 * This method returns a newly created DataArrayInt instance.
6852 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6854 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6856 checkFullyDefined();
6857 const int *conn=_nodal_connec->getConstPointer();
6858 const int *connIndex=_nodal_connec_index->getConstPointer();
6859 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6860 for(const int *w=begin;w!=end;w++)
6861 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6862 ret->pushBackSilent(*w);
6867 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6868 * are in [0:getNumberOfCells())
6870 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6872 checkFullyDefined();
6873 const int *conn=_nodal_connec->getConstPointer();
6874 const int *connI=_nodal_connec_index->getConstPointer();
6875 int nbOfCells=getNumberOfCells();
6876 std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6877 int *tmp=new int[nbOfCells];
6878 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6881 for(const int *i=connI;i!=connI+nbOfCells;i++)
6882 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6883 tmp[std::distance(connI,i)]=j++;
6885 DataArrayInt *ret=DataArrayInt::New();
6886 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6887 ret->copyStringInfoFrom(*da);
6888 int *retPtr=ret->getPointer();
6889 const int *daPtr=da->getConstPointer();
6890 int nbOfElems=da->getNbOfElems();
6891 for(int k=0;k<nbOfElems;k++)
6892 retPtr[k]=tmp[daPtr[k]];
6898 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6899 * This method \b works \b for mesh sorted by type.
6900 * cells whose ids is in 'idsPerGeoType' array.
6901 * This method conserves coords and name of mesh.
6903 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6905 std::vector<int> code=getDistributionOfTypes();
6906 std::size_t nOfTypesInThis=code.size()/3;
6907 int sz=0,szOfType=0;
6908 for(std::size_t i=0;i<nOfTypesInThis;i++)
6913 szOfType=code[3*i+1];
6915 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6916 if(*work<0 || *work>=szOfType)
6918 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6919 oss << ". It should be in [0," << szOfType << ") !";
6920 throw INTERP_KERNEL::Exception(oss.str().c_str());
6922 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6923 int *idsPtr=idsTokeep->getPointer();
6925 for(std::size_t i=0;i<nOfTypesInThis;i++)
6928 for(int j=0;j<code[3*i+1];j++)
6931 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6932 offset+=code[3*i+1];
6934 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6935 ret->copyTinyInfoFrom(this);
6940 * This method returns a vector of size 'this->getNumberOfCells()'.
6941 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6943 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
6945 int ncell=getNumberOfCells();
6946 std::vector<bool> ret(ncell);
6947 const int *cI=getNodalConnectivityIndex()->getConstPointer();
6948 const int *c=getNodalConnectivity()->getConstPointer();
6949 for(int i=0;i<ncell;i++)
6951 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6952 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6953 ret[i]=cm.isQuadratic();
6959 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6961 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6963 if(other->getType()!=UNSTRUCTURED)
6964 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6965 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6966 return MergeUMeshes(this,otherC);
6970 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6971 * computed by averaging coordinates of cell nodes, so this method is not a right
6972 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
6973 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6974 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6975 * components. The caller is to delete this array using decrRef() as it is
6977 * \throw If the coordinates array is not set.
6978 * \throw If the nodal connectivity of cells is not defined.
6979 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6981 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
6983 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6984 int spaceDim=getSpaceDimension();
6985 int nbOfCells=getNumberOfCells();
6986 ret->alloc(nbOfCells,spaceDim);
6987 ret->copyStringInfoFrom(*getCoords());
6988 double *ptToFill=ret->getPointer();
6989 const int *nodal=_nodal_connec->getConstPointer();
6990 const int *nodalI=_nodal_connec_index->getConstPointer();
6991 const double *coor=_coords->getConstPointer();
6992 for(int i=0;i<nbOfCells;i++)
6994 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6995 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7002 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7003 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7005 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7006 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7008 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7009 * \throw If \a this is not fully defined (coordinates and connectivity)
7010 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7012 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7014 checkFullyDefined();
7015 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7016 int spaceDim=getSpaceDimension();
7017 int nbOfCells=getNumberOfCells();
7018 int nbOfNodes=getNumberOfNodes();
7019 ret->alloc(nbOfCells,spaceDim);
7020 double *ptToFill=ret->getPointer();
7021 const int *nodal=_nodal_connec->getConstPointer();
7022 const int *nodalI=_nodal_connec_index->getConstPointer();
7023 const double *coor=_coords->getConstPointer();
7024 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7026 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7027 std::fill(ptToFill,ptToFill+spaceDim,0.);
7028 if(type!=INTERP_KERNEL::NORM_POLYHED)
7030 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7032 if(*conn>=0 && *conn<nbOfNodes)
7033 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7036 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7037 throw INTERP_KERNEL::Exception(oss.str().c_str());
7040 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7041 if(nbOfNodesInCell>0)
7042 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7045 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7046 throw INTERP_KERNEL::Exception(oss.str().c_str());
7051 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7053 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7055 if(*it>=0 && *it<nbOfNodes)
7056 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7059 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7060 throw INTERP_KERNEL::Exception(oss.str().c_str());
7064 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7067 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7068 throw INTERP_KERNEL::Exception(oss.str().c_str());
7076 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7077 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7078 * are specified via an array of cell ids.
7079 * \warning Validity of the specified cell ids is not checked!
7080 * Valid range is [ 0, \a this->getNumberOfCells() ).
7081 * \param [in] begin - an array of cell ids of interest.
7082 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7083 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7084 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7085 * caller is to delete this array using decrRef() as it is no more needed.
7086 * \throw If the coordinates array is not set.
7087 * \throw If the nodal connectivity of cells is not defined.
7089 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7090 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7092 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7094 DataArrayDouble *ret=DataArrayDouble::New();
7095 int spaceDim=getSpaceDimension();
7096 int nbOfTuple=(int)std::distance(begin,end);
7097 ret->alloc(nbOfTuple,spaceDim);
7098 double *ptToFill=ret->getPointer();
7099 double *tmp=new double[spaceDim];
7100 const int *nodal=_nodal_connec->getConstPointer();
7101 const int *nodalI=_nodal_connec_index->getConstPointer();
7102 const double *coor=_coords->getConstPointer();
7103 for(const int *w=begin;w!=end;w++)
7105 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7106 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7114 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7117 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7120 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7121 da->checkAllocated();
7122 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7124 int nbOfTuples=da->getNumberOfTuples();
7125 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7126 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7127 c->alloc(2*nbOfTuples,1);
7128 cI->alloc(nbOfTuples+1,1);
7129 int *cp=c->getPointer();
7130 int *cip=cI->getPointer();
7132 for(int i=0;i<nbOfTuples;i++)
7134 *cp++=INTERP_KERNEL::NORM_POINT1;
7138 ret->setConnectivity(c,cI,true);
7142 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7143 * Cells and nodes of
7144 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7145 * \param [in] mesh1 - the first mesh.
7146 * \param [in] mesh2 - the second mesh.
7147 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7148 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7149 * is no more needed.
7150 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7151 * \throw If the coordinates array is not set in none of the meshes.
7152 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7153 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7155 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7157 std::vector<const MEDCouplingUMesh *> tmp(2);
7158 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7159 return MergeUMeshes(tmp);
7163 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7164 * Cells and nodes of
7165 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7166 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7167 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7168 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7169 * is no more needed.
7170 * \throw If \a a.size() == 0.
7171 * \throw If \a a[ *i* ] == NULL.
7172 * \throw If the coordinates array is not set in none of the meshes.
7173 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7174 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7176 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7178 std::size_t sz=a.size();
7180 return MergeUMeshesLL(a);
7181 for(std::size_t ii=0;ii<sz;ii++)
7184 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7185 throw INTERP_KERNEL::Exception(oss.str().c_str());
7187 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7188 std::vector< const MEDCouplingUMesh * > aa(sz);
7190 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7192 const MEDCouplingUMesh *cur=a[i];
7193 const DataArrayDouble *coo=cur->getCoords();
7195 spaceDim=coo->getNumberOfComponents();
7198 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7199 for(std::size_t i=0;i<sz;i++)
7201 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7204 return MergeUMeshesLL(aa);
7209 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7212 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7213 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7214 int meshDim=(*it)->getMeshDimension();
7215 int nbOfCells=(*it)->getNumberOfCells();
7216 int meshLgth=(*it++)->getMeshLength();
7217 for(;it!=a.end();it++)
7219 if(meshDim!=(*it)->getMeshDimension())
7220 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7221 nbOfCells+=(*it)->getNumberOfCells();
7222 meshLgth+=(*it)->getMeshLength();
7224 std::vector<const MEDCouplingPointSet *> aps(a.size());
7225 std::copy(a.begin(),a.end(),aps.begin());
7226 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7227 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7228 ret->setCoords(pts);
7229 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7230 c->alloc(meshLgth,1);
7231 int *cPtr=c->getPointer();
7232 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7233 cI->alloc(nbOfCells+1,1);
7234 int *cIPtr=cI->getPointer();
7238 for(it=a.begin();it!=a.end();it++)
7240 int curNbOfCell=(*it)->getNumberOfCells();
7241 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7242 const int *curC=(*it)->_nodal_connec->getConstPointer();
7243 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7244 for(int j=0;j<curNbOfCell;j++)
7246 const int *src=curC+curCI[j];
7248 for(;src!=curC+curCI[j+1];src++,cPtr++)
7256 offset+=curCI[curNbOfCell];
7257 offset2+=(*it)->getNumberOfNodes();
7260 ret->setConnectivity(c,cI,true);
7267 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7268 * dimension and sharing the node coordinates array.
7269 * All cells of the first mesh precede all cells of the second mesh
7270 * within the result mesh.
7271 * \param [in] mesh1 - the first mesh.
7272 * \param [in] mesh2 - the second mesh.
7273 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7274 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7275 * is no more needed.
7276 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7277 * \throw If the meshes do not share the node coordinates array.
7278 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7279 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7281 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7283 std::vector<const MEDCouplingUMesh *> tmp(2);
7284 tmp[0]=mesh1; tmp[1]=mesh2;
7285 return MergeUMeshesOnSameCoords(tmp);
7289 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7290 * dimension and sharing the node coordinates array.
7291 * All cells of the *i*-th mesh precede all cells of the
7292 * (*i*+1)-th mesh within the result mesh.
7293 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7294 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7295 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7296 * is no more needed.
7297 * \throw If \a a.size() == 0.
7298 * \throw If \a a[ *i* ] == NULL.
7299 * \throw If the meshes do not share the node coordinates array.
7300 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7301 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7303 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7306 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7307 for(std::size_t ii=0;ii<meshes.size();ii++)
7310 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7311 throw INTERP_KERNEL::Exception(oss.str().c_str());
7313 const DataArrayDouble *coords=meshes.front()->getCoords();
7314 int meshDim=meshes.front()->getMeshDimension();
7315 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7317 int meshIndexLgth=0;
7318 for(;iter!=meshes.end();iter++)
7320 if(coords!=(*iter)->getCoords())
7321 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7322 if(meshDim!=(*iter)->getMeshDimension())
7323 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7324 meshLgth+=(*iter)->getMeshLength();
7325 meshIndexLgth+=(*iter)->getNumberOfCells();
7327 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7328 nodal->alloc(meshLgth,1);
7329 int *nodalPtr=nodal->getPointer();
7330 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7331 nodalIndex->alloc(meshIndexLgth+1,1);
7332 int *nodalIndexPtr=nodalIndex->getPointer();
7334 for(iter=meshes.begin();iter!=meshes.end();iter++)
7336 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7337 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7338 int nbOfCells=(*iter)->getNumberOfCells();
7339 int meshLgth2=(*iter)->getMeshLength();
7340 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7341 if(iter!=meshes.begin())
7342 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7344 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7347 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7348 ret->setName("merge");
7349 ret->setMeshDimension(meshDim);
7350 ret->setConnectivity(nodal,nodalIndex,true);
7351 ret->setCoords(coords);
7356 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7357 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7358 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7359 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7360 * New" mode are returned for each input mesh.
7361 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7362 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7363 * valid values [0,1,2], see zipConnectivityTraducer().
7364 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7365 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7366 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7368 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7369 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7370 * is no more needed.
7371 * \throw If \a meshes.size() == 0.
7372 * \throw If \a meshes[ *i* ] == NULL.
7373 * \throw If the meshes do not share the node coordinates array.
7374 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7375 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7376 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7377 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7379 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7381 //All checks are delegated to MergeUMeshesOnSameCoords
7382 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7383 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7384 corr.resize(meshes.size());
7385 std::size_t nbOfMeshes=meshes.size();
7387 const int *o2nPtr=o2n->getConstPointer();
7388 for(std::size_t i=0;i<nbOfMeshes;i++)
7390 DataArrayInt *tmp=DataArrayInt::New();
7391 int curNbOfCells=meshes[i]->getNumberOfCells();
7392 tmp->alloc(curNbOfCells,1);
7393 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7394 offset+=curNbOfCells;
7395 tmp->setName(meshes[i]->getName());
7402 * Makes all given meshes share the nodal connectivity array. The common connectivity
7403 * array is created by concatenating the connectivity arrays of all given meshes. All
7404 * the given meshes must be of the same space dimension but dimension of cells **can
7405 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7406 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7407 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7408 * \param [in,out] meshes - a vector of meshes to update.
7409 * \throw If any of \a meshes is NULL.
7410 * \throw If the coordinates array is not set in any of \a meshes.
7411 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7412 * \throw If \a meshes are of different space dimension.
7414 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7416 std::size_t sz=meshes.size();
7419 std::vector< const DataArrayDouble * > coords(meshes.size());
7420 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7421 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7425 (*it)->checkConnectivityFullyDefined();
7426 const DataArrayDouble *coo=(*it)->getCoords();
7431 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7432 oss << " has no coordinate array defined !";
7433 throw INTERP_KERNEL::Exception(oss.str().c_str());
7438 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7439 oss << " is null !";
7440 throw INTERP_KERNEL::Exception(oss.str().c_str());
7443 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7444 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7445 int offset=(*it)->getNumberOfNodes();
7446 (*it++)->setCoords(res);
7447 for(;it!=meshes.end();it++)
7449 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7450 (*it)->setCoords(res);
7451 (*it)->shiftNodeNumbersInConn(offset);
7452 offset+=oldNumberOfNodes;
7457 * Merges nodes coincident with a given precision within all given meshes that share
7458 * the nodal connectivity array. The given meshes **can be of different** mesh
7459 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7460 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7461 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7462 * \param [in,out] meshes - a vector of meshes to update.
7463 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7464 * \throw If any of \a meshes is NULL.
7465 * \throw If the \a meshes do not share the same node coordinates array.
7466 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7468 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7472 std::set<const DataArrayDouble *> s;
7473 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7476 s.insert((*it)->getCoords());
7479 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 !";
7480 throw INTERP_KERNEL::Exception(oss.str().c_str());
7485 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 !";
7486 throw INTERP_KERNEL::Exception(oss.str().c_str());
7488 const DataArrayDouble *coo=*(s.begin());
7492 DataArrayInt *comm,*commI;
7493 coo->findCommonTuples(eps,-1,comm,commI);
7494 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7495 int oldNbOfNodes=coo->getNumberOfTuples();
7497 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7498 if(oldNbOfNodes==newNbOfNodes)
7500 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7501 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7503 (*it)->renumberNodesInConn(o2n->getConstPointer());
7504 (*it)->setCoords(newCoords);
7509 * 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.
7510 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7511 * \param isQuad specifies the policy of connectivity.
7512 * @ret in/out parameter in which the result will be append
7514 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7516 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7517 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7518 ret.push_back(cm.getExtrudedType());
7519 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7522 case INTERP_KERNEL::NORM_POINT1:
7524 ret.push_back(connBg[1]);
7525 ret.push_back(connBg[1]+nbOfNodesPerLev);
7528 case INTERP_KERNEL::NORM_SEG2:
7530 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7531 ret.insert(ret.end(),conn,conn+4);
7534 case INTERP_KERNEL::NORM_SEG3:
7536 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7537 ret.insert(ret.end(),conn,conn+8);
7540 case INTERP_KERNEL::NORM_QUAD4:
7542 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7543 ret.insert(ret.end(),conn,conn+8);
7546 case INTERP_KERNEL::NORM_TRI3:
7548 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7549 ret.insert(ret.end(),conn,conn+6);
7552 case INTERP_KERNEL::NORM_TRI6:
7554 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,
7555 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7556 ret.insert(ret.end(),conn,conn+15);
7559 case INTERP_KERNEL::NORM_QUAD8:
7562 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7563 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7564 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7566 ret.insert(ret.end(),conn,conn+20);
7569 case INTERP_KERNEL::NORM_POLYGON:
7571 std::back_insert_iterator< std::vector<int> > ii(ret);
7572 std::copy(connBg+1,connEnd,ii);
7574 std::reverse_iterator<const int *> rConnBg(connEnd);
7575 std::reverse_iterator<const int *> rConnEnd(connBg+1);
7576 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7577 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7578 for(std::size_t i=0;i<nbOfRadFaces;i++)
7581 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7582 std::copy(conn,conn+4,ii);
7587 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7592 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7594 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7596 double v[3]={0.,0.,0.};
7597 std::size_t sz=std::distance(begin,end);
7600 for(std::size_t i=0;i<sz;i++)
7602 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];
7603 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7604 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7606 return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7610 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7612 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7614 std::vector<std::pair<int,int> > edges;
7615 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7616 const int *bgFace=begin;
7617 for(std::size_t i=0;i<nbOfFaces;i++)
7619 const int *endFace=std::find(bgFace+1,end,-1);
7620 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7621 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7623 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7624 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7626 edges.push_back(p1);
7630 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7634 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7636 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7638 double vec0[3],vec1[3];
7639 std::size_t sz=std::distance(begin,end);
7641 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7642 int nbOfNodes=(int)sz/2;
7643 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7644 const double *pt0=coords+3*begin[0];
7645 const double *pt1=coords+3*begin[nbOfNodes];
7646 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7647 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7650 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7652 std::size_t sz=std::distance(begin,end);
7653 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7654 std::size_t nbOfNodes(sz/2);
7655 std::copy(begin,end,(int *)tmp);
7656 for(std::size_t j=1;j<nbOfNodes;j++)
7658 begin[j]=tmp[nbOfNodes-j];
7659 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7663 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7665 std::size_t sz=std::distance(begin,end);
7667 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7668 double vec0[3],vec1[3];
7669 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7670 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];
7671 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;
7674 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7676 std::size_t sz=std::distance(begin,end);
7678 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7680 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7681 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7682 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7686 * 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 )
7687 * 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
7690 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7691 * \param [in] coords the coordinates with nb of components exactly equal to 3
7692 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7693 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7694 * \param [out] res the result is put at the end of the vector without any alteration of the data.
7696 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7698 int nbFaces=std::count(begin+1,end,-1)+1;
7699 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7700 double *vPtr=v->getPointer();
7701 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7702 double *pPtr=p->getPointer();
7703 const int *stFaceConn=begin+1;
7704 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7706 const int *endFaceConn=std::find(stFaceConn,end,-1);
7707 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7708 stFaceConn=endFaceConn+1;
7710 pPtr=p->getPointer(); vPtr=v->getPointer();
7711 DataArrayInt *comm1=0,*commI1=0;
7712 v->findCommonTuples(eps,-1,comm1,commI1);
7713 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7714 const int *comm1Ptr=comm1->getConstPointer();
7715 const int *commI1Ptr=commI1->getConstPointer();
7716 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7717 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7719 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7720 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7721 mm->finishInsertingCells();
7723 for(int i=0;i<nbOfGrps1;i++)
7725 int vecId=comm1Ptr[commI1Ptr[i]];
7726 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7727 DataArrayInt *comm2=0,*commI2=0;
7728 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7729 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7730 const int *comm2Ptr=comm2->getConstPointer();
7731 const int *commI2Ptr=commI2->getConstPointer();
7732 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7733 for(int j=0;j<nbOfGrps2;j++)
7735 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7737 res->insertAtTheEnd(begin,end);
7738 res->pushBackSilent(-1);
7742 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7743 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7744 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7745 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7746 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7747 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7748 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7749 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7750 const int *idsNodePtr=idsNode->getConstPointer();
7751 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];
7752 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7753 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7754 if(std::abs(norm)>eps)
7756 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7757 mm3->rotate(center,vec,angle);
7759 mm3->changeSpaceDimension(2);
7760 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7761 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7762 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7763 int nbOfCells=mm4->getNumberOfCells();
7764 for(int k=0;k<nbOfCells;k++)
7767 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7768 res->pushBackSilent(idsNodePtr[*work]);
7769 res->pushBackSilent(-1);
7774 res->popBackSilent();
7778 * 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
7779 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7781 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7782 * \param [in] coords coordinates expected to have 3 components.
7783 * \param [in] begin start of the nodal connectivity of the face.
7784 * \param [in] end end of the nodal connectivity (excluded) of the face.
7785 * \param [out] v the normalized vector of size 3
7786 * \param [out] p the pos of plane
7788 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7790 std::size_t nbPoints=std::distance(begin,end);
7792 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7793 double vec[3]={0.,0.,0.};
7795 bool refFound=false;
7796 for(;j<nbPoints-1 && !refFound;j++)
7798 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7799 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7800 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7801 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7805 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7808 for(std::size_t i=j;i<nbPoints-1;i++)
7811 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7812 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7813 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7814 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7817 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7818 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];
7819 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7822 v[0]/=norm; v[1]/=norm; v[2]/=norm;
7823 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7827 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7831 * This method tries to obtain a well oriented polyhedron.
7832 * If the algorithm fails, an exception will be thrown.
7834 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7836 std::list< std::pair<int,int> > edgesOK,edgesFinished;
7837 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7838 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7840 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7841 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7842 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7844 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7847 std::size_t smthChanged=0;
7848 for(std::size_t i=0;i<nbOfFaces;i++)
7850 endFace=std::find(bgFace+1,end,-1);
7851 nbOfEdgesInFace=std::distance(bgFace,endFace);
7855 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7857 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7858 std::pair<int,int> p2(p1.second,p1.first);
7859 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7860 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7861 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7866 std::reverse(bgFace+1,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 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7872 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7873 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7874 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7875 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7876 if(it!=edgesOK.end())
7879 edgesFinished.push_back(p1);
7882 edgesOK.push_back(p1);
7889 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7891 if(!edgesOK.empty())
7892 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7893 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7894 {//not lucky ! The first face was not correctly oriented : reorient all faces...
7896 for(std::size_t i=0;i<nbOfFaces;i++)
7898 endFace=std::find(bgFace+1,end,-1);
7899 std::reverse(bgFace+1,endFace);
7906 * This method makes the assumption spacedimension == meshdimension == 2.
7907 * This method works only for linear cells.
7909 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7911 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7913 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7914 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7915 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7916 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7917 int nbOfNodesExpected=m->getNumberOfNodes();
7918 if(m->getNumberOfCells()!=nbOfNodesExpected)
7919 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7920 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7921 const int *n2oPtr=n2o->getConstPointer();
7922 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7923 m->getReverseNodalConnectivity(revNodal,revNodalI);
7924 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7925 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7926 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7927 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7928 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
7929 if(nbOfNodesExpected<1)
7932 int prevNode=nodalPtr[nodalIPtr[0]+1];
7933 *work++=n2oPtr[prevNode];
7934 for(int i=1;i<nbOfNodesExpected;i++)
7936 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7938 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
7939 conn.erase(prevNode);
7942 int curNode=*(conn.begin());
7943 *work++=n2oPtr[curNode];
7944 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
7945 shar.erase(prevCell);
7948 prevCell=*(shar.begin());
7952 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
7955 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
7958 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
7964 * This method makes the assumption spacedimension == meshdimension == 3.
7965 * This method works only for linear cells.
7967 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7969 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
7971 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7972 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7973 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7974 const int *conn=m->getNodalConnectivity()->getConstPointer();
7975 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
7976 int nbOfCells=m->getNumberOfCells();
7977 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7978 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
7981 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7982 for(int i=1;i<nbOfCells;i++)
7985 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7991 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
7992 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
7994 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
7998 for(int i=0;i<nbOfNodesInCell;i++)
7999 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8000 else if(spaceDim==2)
8002 for(int i=0;i<nbOfNodesInCell;i++)
8004 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8009 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8012 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8014 int nbOfCells=getNumberOfCells();
8016 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8017 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};
8018 ofs << " <" << getVTKDataSetType() << ">\n";
8019 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8020 ofs << " <PointData>\n" << pointData << std::endl;
8021 ofs << " </PointData>\n";
8022 ofs << " <CellData>\n" << cellData << std::endl;
8023 ofs << " </CellData>\n";
8024 ofs << " <Points>\n";
8025 if(getSpaceDimension()==3)
8026 _coords->writeVTK(ofs,8,"Points");
8029 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8030 coo->writeVTK(ofs,8,"Points");
8032 ofs << " </Points>\n";
8033 ofs << " <Cells>\n";
8034 const int *cPtr=_nodal_connec->getConstPointer();
8035 const int *cIPtr=_nodal_connec_index->getConstPointer();
8036 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8037 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8038 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8039 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8040 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8041 int szFaceOffsets=0,szConn=0;
8042 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8045 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8048 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8049 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8053 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8054 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8055 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8056 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8057 w4=std::copy(c.begin(),c.end(),w4);
8060 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8061 types->writeVTK(ofs,8,"UInt8","types");
8062 offsets->writeVTK(ofs,8,"Int32","offsets");
8063 if(szFaceOffsets!=0)
8064 {//presence of Polyhedra
8065 connectivity->reAlloc(szConn);
8066 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8067 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8068 w1=faces->getPointer();
8069 for(int i=0;i<nbOfCells;i++)
8070 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8072 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8074 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8075 for(int j=0;j<nbFaces;j++)
8077 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8078 *w1++=(int)std::distance(w6,w5);
8079 w1=std::copy(w6,w5,w1);
8083 faces->writeVTK(ofs,8,"Int32","faces");
8085 connectivity->writeVTK(ofs,8,"Int32","connectivity");
8086 ofs << " </Cells>\n";
8087 ofs << " </Piece>\n";
8088 ofs << " </" << getVTKDataSetType() << ">\n";
8091 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8093 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8095 { stream << " Not set !"; return ; }
8096 stream << " Mesh dimension : " << _mesh_dim << ".";
8100 { stream << " No coordinates set !"; return ; }
8101 if(!_coords->isAllocated())
8102 { stream << " Coordinates set but not allocated !"; return ; }
8103 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8104 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8105 if(!_nodal_connec_index)
8106 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8107 if(!_nodal_connec_index->isAllocated())
8108 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8109 int lgth=_nodal_connec_index->getNumberOfTuples();
8110 int cpt=_nodal_connec_index->getNumberOfComponents();
8111 if(cpt!=1 || lgth<1)
8113 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8116 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8118 return std::string("UnstructuredGrid");
8122 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8123 * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8124 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8126 * \param [in] m1 - the first input mesh which is a partitioned object.
8127 * \param [in] m2 - the second input mesh which is a partition tool.
8128 * \param [in] eps - precision used to detect coincident mesh entities.
8129 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8130 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8131 * this array using decrRef() as it is no more needed.
8132 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8133 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8134 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8135 * any cell of \a m2. The caller is to delete this array using decrRef() as
8136 * it is no more needed.
8137 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8138 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8139 * is no more needed.
8140 * \throw If the coordinates array is not set in any of the meshes.
8141 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8142 * \throw If any of the meshes is not a 2D mesh in 2D space.
8144 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8146 m1->checkFullyDefined();
8147 m2->checkFullyDefined();
8148 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8149 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8150 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8151 MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8152 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8153 std::vector<double> addCoo,addCoordsQuadratic;
8154 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8155 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8156 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8157 m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8158 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8159 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8160 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8161 std::vector< std::vector<int> > intersectEdge2;
8162 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8163 subDiv2.clear(); dd5=0; dd6=0;
8164 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8165 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8166 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8167 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8169 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8170 addCooDa->alloc((int)(addCoo.size())/2,2);
8171 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8172 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8173 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8174 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8175 std::vector<const DataArrayDouble *> coordss(4);
8176 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8177 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8178 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8179 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8180 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8181 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8182 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8183 ret->setConnectivity(conn,connI,true);
8184 ret->setCoords(coo);
8185 cellNb1=c1.retn(); cellNb2=c2.retn();
8189 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8190 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8191 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8192 const std::vector<double>& addCoords,
8193 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8195 static const int SPACEDIM=2;
8196 std::vector<double> bbox1,bbox2;
8197 const double *coo1=m1->getCoords()->getConstPointer();
8198 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8199 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8200 int offset1=m1->getNumberOfNodes();
8201 const double *coo2=m2->getCoords()->getConstPointer();
8202 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8203 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8204 int offset2=offset1+m2->getNumberOfNodes();
8205 int offset3=offset2+((int)addCoords.size())/2;
8206 m1->getBoundingBoxForBBTree(bbox1);
8207 m2->getBoundingBoxForBBTree(bbox2);
8208 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8209 int ncell1=m1->getNumberOfCells();
8211 for(int i=0;i<ncell1;i++)
8213 std::vector<int> candidates2;
8214 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8215 std::map<INTERP_KERNEL::Node *,int> mapp;
8216 std::map<int,INTERP_KERNEL::Node *> mappRev;
8217 INTERP_KERNEL::QuadraticPolygon pol1;
8218 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8219 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8220 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8221 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8222 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8224 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
8225 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8226 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8227 for(it1.first();!it1.finished();it1.next())
8228 edges1.insert(it1.current()->getPtr());
8230 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8231 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8233 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8235 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8236 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8237 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8238 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8239 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8242 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8244 pol1.initLocationsWithOther(pol2s[ii]);
8245 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8246 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8247 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8253 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8255 catch(INTERP_KERNEL::Exception& e)
8257 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();
8258 throw INTERP_KERNEL::Exception(oss.str().c_str());
8261 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8262 (*it).second->decrRef();
8267 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8270 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8271 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8272 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8273 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8274 std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8276 static const int SPACEDIM=2;
8277 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8278 desc2=DataArrayInt::New();
8279 descIndx2=DataArrayInt::New();
8280 revDesc2=DataArrayInt::New();
8281 revDescIndx2=DataArrayInt::New();
8282 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8283 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8284 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8285 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8286 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8287 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8288 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8289 std::vector<double> bbox1,bbox2;
8290 m1Desc->getBoundingBoxForBBTree(bbox1);
8291 m2Desc->getBoundingBoxForBBTree(bbox2);
8292 int ncell1=m1Desc->getNumberOfCells();
8293 int ncell2=m2Desc->getNumberOfCells();
8294 intersectEdge1.resize(ncell1);
8295 colinear2.resize(ncell2);
8296 subDiv2.resize(ncell2);
8297 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8298 std::vector<int> candidates1(1);
8299 int offset1=m1->getNumberOfNodes();
8300 int offset2=offset1+m2->getNumberOfNodes();
8301 for(int i=0;i<ncell1;i++)
8303 std::vector<int> candidates2;
8304 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8305 if(!candidates2.empty())
8307 std::map<INTERP_KERNEL::Node *,int> map1,map2;
8308 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8310 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8311 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8316 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8318 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8319 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8323 * This method performs the 2nd step of Partition of 2D mesh.
8324 * This method has 4 inputs :
8325 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8326 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8327 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8328 * 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'
8329 * \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'
8330 * \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.
8331 * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8333 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)
8335 int offset1=m1->getNumberOfNodes();
8336 int ncell=m2->getNumberOfCells();
8337 const int *c=m2->getNodalConnectivity()->getConstPointer();
8338 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8339 const double *coo=m2->getCoords()->getConstPointer();
8340 const double *cooBis=m1->getCoords()->getConstPointer();
8341 int offset2=offset1+m2->getNumberOfNodes();
8342 intersectEdge.resize(ncell);
8343 for(int i=0;i<ncell;i++,cI++)
8345 const std::vector<int>& divs=subDiv[i];
8346 int nnode=cI[1]-cI[0]-1;
8347 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8348 std::map<INTERP_KERNEL::Node *, int> mapp22;
8349 for(int j=0;j<nnode;j++)
8351 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8352 int nnid=c[(*cI)+j+1];
8353 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8354 mapp22[nn]=nnid+offset1;
8356 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8357 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8358 ((*it).second.first)->decrRef();
8359 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8360 std::map<INTERP_KERNEL::Node *,int> mapp3;
8361 for(std::size_t j=0;j<divs.size();j++)
8364 INTERP_KERNEL::Node *tmp=0;
8366 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8368 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8370 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8374 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8375 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8382 * 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).
8383 * 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
8384 * with a plane. The result will be put in 'cut3DSuf' out parameter.
8385 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8386 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8387 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8388 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8389 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8390 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8391 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8392 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8393 * \param [out] cut3DSuf input/output param.
8395 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8396 const int *nodal3DCurve, const int *nodalIndx3DCurve,
8397 const int *desc, const int *descIndx,
8398 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8400 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8401 int nbOf3DSurfCell=(int)cut3DSurf.size();
8402 for(int i=0;i<nbOf3DSurfCell;i++)
8404 std::vector<int> res;
8405 int offset=descIndx[i];
8406 int nbOfSeg=descIndx[i+1]-offset;
8407 for(int j=0;j<nbOfSeg;j++)
8409 int edgeId=desc[offset+j];
8410 int status=cut3DCurve[edgeId];
8414 res.push_back(status);
8417 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8418 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8426 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8432 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8433 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8436 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8440 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8445 {// case when plane is on a multi colinear edge of a polyhedron
8446 if((int)res.size()==2*nbOfSeg)
8448 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8451 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8458 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8459 * 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).
8460 * 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
8461 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8462 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8463 * \param desc is the descending connectivity 3D->3DSurf
8464 * \param descIndx is the descending connectivity index 3D->3DSurf
8466 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8467 const int *desc, const int *descIndx,
8468 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8470 checkFullyDefined();
8471 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8472 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8473 const int *nodal3D=_nodal_connec->getConstPointer();
8474 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8475 int nbOfCells=getNumberOfCells();
8476 for(int i=0;i<nbOfCells;i++)
8478 std::map<int, std::set<int> > m;
8479 int offset=descIndx[i];
8480 int nbOfFaces=descIndx[i+1]-offset;
8483 for(int j=0;j<nbOfFaces;j++)
8485 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8486 if(p.first!=-1 && p.second!=-1)
8490 start=p.first; end=p.second;
8491 m[p.first].insert(p.second);
8492 m[p.second].insert(p.first);
8496 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8497 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8498 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8499 INTERP_KERNEL::NormalizedCellType cmsId;
8500 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8501 start=tmp[0]; end=tmp[nbOfNodesSon-1];
8502 for(unsigned k=0;k<nbOfNodesSon;k++)
8504 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8505 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8512 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8516 std::map<int, std::set<int> >::const_iterator it=m.find(start);
8517 const std::set<int>& s=(*it).second;
8518 std::set<int> s2; s2.insert(prev);
8520 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8523 int val=*s3.begin();
8524 conn.push_back(start);
8531 conn.push_back(end);
8534 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8535 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8536 cellIds->pushBackSilent(i);
8542 * 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
8543 * 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
8544 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8545 * 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
8546 * 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.
8548 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8550 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8552 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8555 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8556 if(cm.getDimension()==2)
8558 const int *node=nodalConnBg+1;
8559 int startNode=*node++;
8560 double refX=coords[2*startNode];
8561 for(;node!=nodalConnEnd;node++)
8563 if(coords[2*(*node)]<refX)
8566 refX=coords[2*startNode];
8569 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8573 double angle0=-M_PI/2;
8578 double angleNext=0.;
8579 while(nextNode!=startNode)
8583 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8585 if(*node!=tmpOut.back() && *node!=prevNode)
8587 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8588 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8593 res=angle0-angleM+2.*M_PI;
8602 if(nextNode!=startNode)
8604 angle0=angleNext-M_PI;
8607 prevNode=tmpOut.back();
8608 tmpOut.push_back(nextNode);
8611 std::vector<int> tmp3(2*(sz-1));
8612 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8613 std::copy(nodalConnBg+1,nodalConnEnd,it);
8614 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8616 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8619 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8621 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8626 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8627 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8632 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8635 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8639 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8640 * 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.
8642 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8643 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8644 * \param [in,out] arr array in which the remove operation will be done.
8645 * \param [in,out] arrIndx array in the remove operation will modify
8646 * \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])
8647 * \return true if \b arr and \b arrIndx have been modified, false if not.
8649 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8651 if(!arrIndx || !arr)
8652 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8653 if(offsetForRemoval<0)
8654 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8655 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8656 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8657 int *arrIPtr=arrIndx->getPointer();
8660 const int *arrPtr=arr->getConstPointer();
8661 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8662 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8664 if(*arrIPtr-previousArrI>offsetForRemoval)
8666 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8668 if(s.find(*work)==s.end())
8669 arrOut.push_back(*work);
8672 previousArrI=*arrIPtr;
8673 *arrIPtr=(int)arrOut.size();
8675 if(arr->getNumberOfTuples()==(int)arrOut.size())
8677 arr->alloc((int)arrOut.size(),1);
8678 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8683 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8684 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8685 * The selection of extraction is done standardly in new2old format.
8686 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8688 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8689 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8690 * \param [in] arrIn arr origin array from which the extraction will be done.
8691 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8692 * \param [out] arrOut the resulting array
8693 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8694 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
8696 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8697 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8699 if(!arrIn || !arrIndxIn)
8700 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8701 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8702 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8703 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
8704 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8705 const int *arrInPtr=arrIn->getConstPointer();
8706 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8707 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8709 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8710 int maxSizeOfArr=arrIn->getNumberOfTuples();
8711 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8712 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8713 arrIo->alloc((int)(sz+1),1);
8714 const int *idsIt=idsOfSelectBg;
8715 int *work=arrIo->getPointer();
8718 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8720 if(*idsIt>=0 && *idsIt<nbOfGrps)
8721 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8724 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8725 throw INTERP_KERNEL::Exception(oss.str().c_str());
8731 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8732 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8733 throw INTERP_KERNEL::Exception(oss.str().c_str());
8736 arro->alloc(lgth,1);
8737 work=arro->getPointer();
8738 idsIt=idsOfSelectBg;
8739 for(std::size_t i=0;i<sz;i++,idsIt++)
8741 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8742 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8745 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8746 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8747 throw INTERP_KERNEL::Exception(oss.str().c_str());
8751 arrIndexOut=arrIo.retn();
8755 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8756 * This method returns the result of the extraction ( specified by a set of ids with a slice given by \a idsOfSelectStart, \a idsOfSelectStop and \a idsOfSelectStep ).
8757 * The selection of extraction is done standardly in new2old format.
8758 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8760 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8761 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8762 * \param [in] arrIn arr origin array from which the extraction will be done.
8763 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8764 * \param [out] arrOut the resulting array
8765 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8766 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
8768 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8769 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8771 if(!arrIn || !arrIndxIn)
8772 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
8773 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8774 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8775 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
8776 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
8777 const int *arrInPtr=arrIn->getConstPointer();
8778 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8779 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8781 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8782 int maxSizeOfArr=arrIn->getNumberOfTuples();
8783 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8784 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8785 arrIo->alloc((int)(sz+1),1);
8786 int idsIt=idsOfSelectStart;
8787 int *work=arrIo->getPointer();
8790 for(std::size_t i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
8792 if(idsIt>=0 && idsIt<nbOfGrps)
8793 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
8796 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8797 throw INTERP_KERNEL::Exception(oss.str().c_str());
8803 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
8804 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
8805 throw INTERP_KERNEL::Exception(oss.str().c_str());
8808 arro->alloc(lgth,1);
8809 work=arro->getPointer();
8810 idsIt=idsOfSelectStart;
8811 for(std::size_t i=0;i<sz;i++,idsIt+=idsOfSelectStep)
8813 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
8814 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
8817 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
8818 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8819 throw INTERP_KERNEL::Exception(oss.str().c_str());
8823 arrIndexOut=arrIo.retn();
8827 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8828 * 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
8829 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8830 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
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] arrIn 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
8838 * \param [out] arrOut the resulting array
8839 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8841 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8843 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8844 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8845 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8847 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8848 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8849 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8850 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8851 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8852 std::vector<bool> v(nbOfTuples,true);
8854 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8855 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8856 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8858 if(*it>=0 && *it<nbOfTuples)
8861 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8865 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8866 throw INTERP_KERNEL::Exception(oss.str().c_str());
8869 srcArrIndexPtr=srcArrIndex->getConstPointer();
8870 arrIo->alloc(nbOfTuples+1,1);
8871 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8872 const int *arrInPtr=arrIn->getConstPointer();
8873 const int *srcArrPtr=srcArr->getConstPointer();
8874 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8875 int *arroPtr=arro->getPointer();
8876 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8880 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8881 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8885 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8886 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8887 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8891 arrIndexOut=arrIo.retn();
8895 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8896 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8898 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8899 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8900 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8901 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8902 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8903 * \param [in] srcArrIndex index array of \b srcArr
8905 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8907 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8908 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8910 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8911 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8912 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8913 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8914 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8915 int *arrInOutPtr=arrInOut->getPointer();
8916 const int *srcArrPtr=srcArr->getConstPointer();
8917 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8919 if(*it>=0 && *it<nbOfTuples)
8921 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8922 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8925 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] !";
8926 throw INTERP_KERNEL::Exception(oss.str().c_str());
8931 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8932 throw INTERP_KERNEL::Exception(oss.str().c_str());
8938 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8939 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8940 * 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]].
8941 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8942 * A negative value in \b arrIn means that it is ignored.
8943 * 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.
8945 * \param [in] arrIn arr origin array from which the extraction will be done.
8946 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8947 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8948 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8950 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
8952 int seed=0,nbOfDepthPeelingPerformed=0;
8953 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
8957 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8958 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8959 * 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]].
8960 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8961 * A negative value in \b arrIn means that it is ignored.
8962 * 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.
8963 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
8964 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
8965 * \param [in] arrIn arr origin array from which the extraction will be done.
8966 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8967 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8968 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8969 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8970 * \sa MEDCouplingUMesh::partitionBySpreadZone
8972 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8974 nbOfDepthPeelingPerformed=0;
8976 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8977 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8980 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
8984 std::vector<bool> fetched(nbOfTuples,false);
8985 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
8988 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)
8990 nbOfDepthPeelingPerformed=0;
8991 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
8992 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
8993 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8994 std::vector<bool> fetched2(nbOfTuples,false);
8996 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
8998 if(*seedElt>=0 && *seedElt<nbOfTuples)
8999 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9001 { 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()); }
9003 const int *arrInPtr=arrIn->getConstPointer();
9004 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9005 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9006 std::vector<int> idsToFetch1(seedBg,seedEnd);
9007 std::vector<int> idsToFetch2;
9008 std::vector<int> *idsToFetch=&idsToFetch1;
9009 std::vector<int> *idsToFetchOther=&idsToFetch2;
9010 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9012 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9013 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9015 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9016 std::swap(idsToFetch,idsToFetchOther);
9017 idsToFetchOther->clear();
9018 nbOfDepthPeelingPerformed++;
9020 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9022 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9023 int *retPtr=ret->getPointer();
9024 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9031 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9032 * 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
9033 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9034 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9036 * \param [in] start begin of set of ids of the input extraction (included)
9037 * \param [in] end end of set of ids of the input extraction (excluded)
9038 * \param [in] step step of the set of ids in range mode.
9039 * \param [in] arrIn arr origin array from which the extraction will be done.
9040 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9041 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9042 * \param [in] srcArrIndex index array of \b srcArr
9043 * \param [out] arrOut the resulting array
9044 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9046 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9048 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9049 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9050 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9052 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9053 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9054 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9055 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9056 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9058 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9059 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9060 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9062 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9064 if(it>=0 && it<nbOfTuples)
9065 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9068 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9069 throw INTERP_KERNEL::Exception(oss.str().c_str());
9072 srcArrIndexPtr=srcArrIndex->getConstPointer();
9073 arrIo->alloc(nbOfTuples+1,1);
9074 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9075 const int *arrInPtr=arrIn->getConstPointer();
9076 const int *srcArrPtr=srcArr->getConstPointer();
9077 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9078 int *arroPtr=arro->getPointer();
9079 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9081 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9084 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9085 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9089 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9090 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9094 arrIndexOut=arrIo.retn();
9098 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9099 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9101 * \param [in] start begin of set of ids of the input extraction (included)
9102 * \param [in] end end of set of ids of the input extraction (excluded)
9103 * \param [in] step step of the set of ids in range mode.
9104 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9105 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9106 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9107 * \param [in] srcArrIndex index array of \b srcArr
9109 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9111 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9112 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9114 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9115 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9116 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9117 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9118 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9119 int *arrInOutPtr=arrInOut->getPointer();
9120 const int *srcArrPtr=srcArr->getConstPointer();
9121 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9123 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9125 if(it>=0 && it<nbOfTuples)
9127 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9128 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9131 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9132 throw INTERP_KERNEL::Exception(oss.str().c_str());
9137 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9138 throw INTERP_KERNEL::Exception(oss.str().c_str());
9144 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9145 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9146 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9147 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9148 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9150 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9152 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9154 checkFullyDefined();
9155 int mdim=getMeshDimension();
9156 int spaceDim=getSpaceDimension();
9158 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9159 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9160 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9161 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9162 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9163 ret->setCoords(getCoords());
9164 ret->allocateCells((int)partition.size());
9166 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9168 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9169 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9173 cell=tmp->buildUnionOf2DMesh();
9176 cell=tmp->buildUnionOf3DMesh();
9179 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9182 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9185 ret->finishInsertingCells();
9190 * This method partitions \b this into contiguous zone.
9191 * This method only needs a well defined connectivity. Coordinates are not considered here.
9192 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9194 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9197 int nbOfCellsCur=getNumberOfCells();
9198 std::vector<DataArrayInt *> ret;
9201 DataArrayInt *neigh=0,*neighI=0;
9202 computeNeighborsOfCells(neigh,neighI);
9203 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9204 std::vector<bool> fetchedCells(nbOfCellsCur,false);
9205 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9207 while(seed<nbOfCellsCur)
9209 int nbOfPeelPerformed=0;
9210 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9211 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9213 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9214 ret.push_back((*it).retn());
9218 int nbOfCellsCur=getNumberOfCells();
9219 DataArrayInt *neigh=0,*neighI=0;
9220 computeNeighborsOfCells(neigh,neighI);
9221 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9222 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9223 std::vector<DataArrayInt *> ret;
9224 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9225 while(nbOfCellsCur>0)
9227 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9228 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9229 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9230 ret2.push_back(tmp2); ret.push_back(tmp2);
9231 nbOfCellsCur=tmp3->getNumberOfTuples();
9234 ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9235 MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9238 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9239 neighAuto->transformWithIndArr(renum->begin(),renum->end());
9242 for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9249 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9250 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9252 * \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.
9253 * \return a newly allocated DataArrayInt to be managed by the caller.
9254 * \throw In case of \a code has not the right format (typically of size 3*n)
9256 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9258 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9259 std::size_t nb=code.size()/3;
9260 if(code.size()%3!=0)
9261 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9262 ret->alloc((int)nb,2);
9263 int *retPtr=ret->getPointer();
9264 for(std::size_t i=0;i<nb;i++,retPtr+=2)
9266 retPtr[0]=code[3*i+2];
9267 retPtr[1]=code[3*i+2]+code[3*i+1];
9272 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9273 _own_cell(true),_cell_id(-1),_nb_cell(0)
9278 _nb_cell=mesh->getNumberOfCells();
9282 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9290 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9291 _own_cell(false),_cell_id(bg-1),
9298 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9301 if(_cell_id<_nb_cell)
9310 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9316 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9318 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9321 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9327 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9335 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9341 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9346 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9351 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9353 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9356 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9361 _nb_cell=mesh->getNumberOfCells();
9365 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9372 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9374 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9375 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9376 if(_cell_id<_nb_cell)
9378 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9379 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9380 int startId=_cell_id;
9381 _cell_id+=nbOfElems;
9382 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9388 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9392 _conn=mesh->getNodalConnectivity()->getPointer();
9393 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9397 void MEDCouplingUMeshCell::next()
9399 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9404 _conn_lgth=_conn_indx[1]-_conn_indx[0];
9407 std::string MEDCouplingUMeshCell::repr() const
9409 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9411 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9413 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9417 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9420 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9422 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9423 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9425 return INTERP_KERNEL::NORM_ERROR;
9428 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9431 if(_conn_lgth!=NOTICABLE_FIRST_VAL)