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))
1824 * Merges nodes equal within \a precision and returns an array describing the
1825 * permutation used to remove duplicate nodes.
1826 * \param [in] precision - minimal absolute distance between two nodes at which they are
1827 * considered not coincident.
1828 * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1829 * \param [out] newNbOfNodes - number of nodes remaining after the removal.
1830 * \return DataArrayInt * - the permutation array in "Old to New" mode. For more
1831 * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1832 * is to delete this array using decrRef() as it is no more needed.
1833 * \throw If the coordinates array is not set.
1834 * \throw If the nodal connectivity of cells is not defined.
1836 * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1837 * \ref py_mcumesh_mergeNodes "Here is a Python example".
1839 DataArrayInt *MEDCouplingUMesh::mergeNodes(double precision, bool& areNodesMerged, int& newNbOfNodes)
1841 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1843 renumberNodes(ret->begin(),newNbOfNodes);
1849 * Merges nodes equal within \a precision and returns an array describing the
1850 * permutation used to remove duplicate nodes. In contrast to mergeNodes(), location
1851 * of merged nodes is changed to be at their barycenter.
1852 * \param [in] precision - minimal absolute distance between two nodes at which they are
1853 * considered not coincident.
1854 * \param [out] areNodesMerged - is set to \c true if any coincident nodes removed.
1855 * \param [out] newNbOfNodes - number of nodes remaining after the removal.
1856 * \return DataArrayInt * - the permutation array in "Old to New" mode. For more
1857 * info on "Old to New" mode see \ref MEDCouplingArrayRenumbering. The caller
1858 * is to delete this array using decrRef() as it is no more needed.
1859 * \throw If the coordinates array is not set.
1860 * \throw If the nodal connectivity of cells is not defined.
1862 * \ref cpp_mcumesh_mergeNodes "Here is a C++ example".<br>
1863 * \ref py_mcumesh_mergeNodes "Here is a Python example".
1865 DataArrayInt *MEDCouplingUMesh::mergeNodes2(double precision, bool& areNodesMerged, int& newNbOfNodes)
1867 DataArrayInt *ret=buildPermArrayForMergeNode(precision,-1,areNodesMerged,newNbOfNodes);
1869 renumberNodes2(ret->getConstPointer(),newNbOfNodes);
1873 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1876 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1877 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1879 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1880 std::vector<const MEDCouplingUMesh *> ms(2);
1883 return MergeUMeshesOnSameCoords(ms);
1887 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1888 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1889 * cellIds is not given explicitely but by a range python like.
1891 * \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.
1892 * \return a newly allocated
1894 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1895 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1897 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1899 if(getMeshDimension()!=-1)
1900 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1903 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1905 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1907 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1909 return const_cast<MEDCouplingUMesh *>(this);
1914 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1915 * The result mesh shares or not the node coordinates array with \a this mesh depending
1916 * on \a keepCoords parameter.
1917 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1918 * to write this mesh to the MED file, its cells must be sorted using
1919 * sortCellsInMEDFileFrmt().
1920 * \param [in] begin - an array of cell ids to include to the new mesh.
1921 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
1922 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1923 * array of \a this mesh, else "free" nodes are removed from the result mesh
1924 * by calling zipCoords().
1925 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1926 * to delete this mesh using decrRef() as it is no more needed.
1927 * \throw If the coordinates array is not set.
1928 * \throw If the nodal connectivity of cells is not defined.
1929 * \throw If any cell id in the array \a begin is not valid.
1931 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1932 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
1934 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1936 if(getMeshDimension()!=-1)
1937 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1941 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1943 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1945 return const_cast<MEDCouplingUMesh *>(this);
1950 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1952 * 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.
1953 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1954 * The number of cells of \b this will remain the same with this method.
1956 * \param [in] begin begin of cell ids (included) of cells in this to assign
1957 * \param [in] end end of cell ids (excluded) of cells in this to assign
1958 * \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 ).
1959 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1961 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1963 checkConnectivityFullyDefined();
1964 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1965 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1966 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1967 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1969 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1970 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1971 throw INTERP_KERNEL::Exception(oss.str().c_str());
1973 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1974 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1976 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1977 throw INTERP_KERNEL::Exception(oss.str().c_str());
1979 int nbOfCells=getNumberOfCells();
1980 bool easyAssign=true;
1981 const int *connI=_nodal_connec_index->getConstPointer();
1982 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1983 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1985 if(*it>=0 && *it<nbOfCells)
1987 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1991 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1992 throw INTERP_KERNEL::Exception(oss.str().c_str());
1997 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2002 DataArrayInt *arrOut=0,*arrIOut=0;
2003 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2005 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2006 setConnectivity(arrOut,arrIOut,true);
2010 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2012 checkConnectivityFullyDefined();
2013 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2014 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2015 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2016 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2018 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2019 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2020 throw INTERP_KERNEL::Exception(oss.str().c_str());
2022 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2023 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2025 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2026 throw INTERP_KERNEL::Exception(oss.str().c_str());
2028 int nbOfCells=getNumberOfCells();
2029 bool easyAssign=true;
2030 const int *connI=_nodal_connec_index->getConstPointer();
2031 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2033 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2035 if(it>=0 && it<nbOfCells)
2037 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2041 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2042 throw INTERP_KERNEL::Exception(oss.str().c_str());
2047 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2052 DataArrayInt *arrOut=0,*arrIOut=0;
2053 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2055 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2056 setConnectivity(arrOut,arrIOut,true);
2061 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2062 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2063 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2064 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2066 * \param [in] begin input start of array of node ids.
2067 * \param [in] end input end of array of node ids.
2068 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2069 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2071 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2073 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2074 checkConnectivityFullyDefined();
2076 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2077 std::vector<bool> fastFinder(sz,false);
2078 for(const int *work=begin;work!=end;work++)
2079 if(*work>=0 && *work<sz)
2080 fastFinder[*work]=true;
2081 int nbOfCells=getNumberOfCells();
2082 const int *conn=getNodalConnectivity()->getConstPointer();
2083 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2084 for(int i=0;i<nbOfCells;i++)
2086 int ref=0,nbOfHit=0;
2087 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2091 if(fastFinder[*work2])
2094 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2095 cellIdsKept->pushBackSilent(i);
2097 cellIdsKeptArr=cellIdsKept.retn();
2101 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2102 * this->getMeshDimension(), that bound some cells of \a this mesh.
2103 * The cells of lower dimension to include to the result mesh are selected basing on
2104 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2105 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2106 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2107 * created mesh shares the node coordinates array with \a this mesh.
2108 * \param [in] begin - the array of node ids.
2109 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2110 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2111 * array \a begin are added, else cells whose any node is in the
2112 * array \a begin are added.
2113 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2114 * to delete this mesh using decrRef() as it is no more needed.
2115 * \throw If the coordinates array is not set.
2116 * \throw If the nodal connectivity of cells is not defined.
2117 * \throw If any node id in \a begin is not valid.
2119 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2120 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2122 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2124 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2125 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2126 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2127 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2128 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2132 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2133 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2134 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2135 * array of \a this mesh, else "free" nodes are removed from the result mesh
2136 * by calling zipCoords().
2137 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2138 * to delete this mesh using decrRef() as it is no more needed.
2139 * \throw If the coordinates array is not set.
2140 * \throw If the nodal connectivity of cells is not defined.
2142 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2143 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2145 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2147 DataArrayInt *desc=DataArrayInt::New();
2148 DataArrayInt *descIndx=DataArrayInt::New();
2149 DataArrayInt *revDesc=DataArrayInt::New();
2150 DataArrayInt *revDescIndx=DataArrayInt::New();
2152 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2155 descIndx->decrRef();
2156 int nbOfCells=meshDM1->getNumberOfCells();
2157 const int *revDescIndxC=revDescIndx->getConstPointer();
2158 std::vector<int> boundaryCells;
2159 for(int i=0;i<nbOfCells;i++)
2160 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2161 boundaryCells.push_back(i);
2162 revDescIndx->decrRef();
2163 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2168 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2169 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2170 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2172 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2174 checkFullyDefined();
2175 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2176 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2177 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2178 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2180 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2181 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2183 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2184 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2185 const int *revDescPtr=revDesc->getConstPointer();
2186 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2187 int nbOfCells=getNumberOfCells();
2188 std::vector<bool> ret1(nbOfCells,false);
2190 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2191 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2192 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2194 DataArrayInt *ret2=DataArrayInt::New();
2196 int *ret2Ptr=ret2->getPointer();
2198 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2201 ret2->setName("BoundaryCells");
2206 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2207 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2208 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2209 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2211 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2212 * This method method returns cells ids set s = s1 + s2 where :
2214 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2215 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2217 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2218 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2220 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2221 * \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
2222 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2224 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2226 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2227 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2228 checkConnectivityFullyDefined();
2229 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2230 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2231 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2232 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2233 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2234 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2235 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2236 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2237 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2238 DataArrayInt *idsOtherInConsti=0;
2239 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2240 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2242 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2244 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2245 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2246 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2247 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2248 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2249 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2250 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2251 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2252 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2253 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2254 neighThisPartAuto=0;
2255 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2256 const int li[2]={0,1};
2257 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2258 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2259 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2262 cellIdsRk0=s0arr.retn();
2263 cellIdsRk1=s_renum1.retn();
2267 * 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
2268 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2270 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2272 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2274 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2275 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2276 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2277 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2279 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2280 revDesc=0; desc=0; descIndx=0;
2281 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2282 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2283 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2287 * Finds nodes lying on the boundary of \a this mesh.
2288 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2289 * nodes. The caller is to delete this array using decrRef() as it is no
2291 * \throw If the coordinates array is not set.
2292 * \throw If the nodal connectivity of cells is node defined.
2294 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2295 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2297 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2299 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2300 return skin->computeFetchedNodeIds();
2303 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2306 return const_cast<MEDCouplingUMesh *>(this);
2310 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2311 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2312 * 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.
2313 * 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.
2314 * 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.
2316 * \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
2317 * parameter is altered during the call.
2318 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2319 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2320 * \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.
2322 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2324 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2325 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2327 checkFullyDefined();
2328 otherDimM1OnSameCoords.checkFullyDefined();
2329 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2330 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2331 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2332 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2333 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2334 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2335 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2336 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2337 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2338 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2339 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2340 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2341 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2342 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2344 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2345 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2346 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2347 DataArrayInt *idsTmp=0;
2348 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2349 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2351 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2352 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2353 DataArrayInt *tmp0=0,*tmp1=0;
2354 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2355 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2356 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2357 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2358 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2359 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2360 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2362 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2363 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2364 nodeIdsToDuplicate=s3.retn();
2368 * This method operates a modification of the connectivity and coords in \b this.
2369 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2370 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2371 * 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
2372 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2373 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2375 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2377 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2378 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2380 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2382 int nbOfNodes=getNumberOfNodes();
2383 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2384 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2388 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2389 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2390 * This method is a generalization of shiftNodeNumbersInConn().
2391 * \warning This method performs no check of validity of new ids. **Use it with care !**
2392 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2393 * this->getNumberOfNodes(), in "Old to New" mode.
2394 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2395 * \throw If the nodal connectivity of cells is not defined.
2397 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2398 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2400 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2402 checkConnectivityFullyDefined();
2403 int *conn=getNodalConnectivity()->getPointer();
2404 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2405 int nbOfCells=getNumberOfCells();
2406 for(int i=0;i<nbOfCells;i++)
2407 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2409 int& node=conn[iconn];
2410 if(node>=0)//avoid polyhedron separator
2412 node=newNodeNumbersO2N[node];
2415 _nodal_connec->declareAsNew();
2420 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2421 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2422 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2424 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2426 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2428 checkConnectivityFullyDefined();
2429 int *conn=getNodalConnectivity()->getPointer();
2430 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2431 int nbOfCells=getNumberOfCells();
2432 for(int i=0;i<nbOfCells;i++)
2433 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2435 int& node=conn[iconn];
2436 if(node>=0)//avoid polyhedron separator
2441 _nodal_connec->declareAsNew();
2446 * This method operates a modification of the connectivity in \b this.
2447 * 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.
2448 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2449 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2450 * 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
2451 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2452 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2454 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2455 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2457 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2458 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2459 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2461 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2463 checkConnectivityFullyDefined();
2464 std::map<int,int> m;
2466 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2468 int *conn=getNodalConnectivity()->getPointer();
2469 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2470 int nbOfCells=getNumberOfCells();
2471 for(int i=0;i<nbOfCells;i++)
2472 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2474 int& node=conn[iconn];
2475 if(node>=0)//avoid polyhedron separator
2477 std::map<int,int>::iterator it=m.find(node);
2486 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2488 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2489 * After the call of this method the number of cells remains the same as before.
2491 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2492 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2493 * be strictly in [0;this->getNumberOfCells()).
2495 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2496 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2497 * should be contained in[0;this->getNumberOfCells()).
2499 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2501 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2503 checkConnectivityFullyDefined();
2504 int nbCells=getNumberOfCells();
2505 const int *array=old2NewBg;
2507 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2509 const int *conn=_nodal_connec->getConstPointer();
2510 const int *connI=_nodal_connec_index->getConstPointer();
2511 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2512 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2513 const int *n2oPtr=n2o->begin();
2514 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2515 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2516 newConn->copyStringInfoFrom(*_nodal_connec);
2517 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2518 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2519 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2521 int *newC=newConn->getPointer();
2522 int *newCI=newConnI->getPointer();
2525 for(int i=0;i<nbCells;i++)
2528 int nbOfElts=connI[pos+1]-connI[pos];
2529 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2534 setConnectivity(newConn,newConnI);
2536 free(const_cast<int *>(array));
2540 * Finds cells whose bounding boxes intersect a given bounding box.
2541 * \param [in] bbox - an array defining the bounding box via coordinates of its
2542 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2544 * \param [in] eps - a factor used to increase size of the bounding box of cell
2545 * before comparing it with \a bbox. This factor is multiplied by the maximal
2546 * extent of the bounding box of cell to produce an addition to this bounding box.
2547 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2548 * cells. The caller is to delete this array using decrRef() as it is no more
2550 * \throw If the coordinates array is not set.
2551 * \throw If the nodal connectivity of cells is not defined.
2553 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2554 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2556 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2558 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2559 if(getMeshDimension()==-1)
2561 elems->pushBackSilent(0);
2562 return elems.retn();
2564 int dim=getSpaceDimension();
2565 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2566 const int* conn = getNodalConnectivity()->getConstPointer();
2567 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2568 const double* coords = getCoords()->getConstPointer();
2569 int nbOfCells=getNumberOfCells();
2570 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2572 for (int i=0; i<dim; i++)
2574 elem_bb[i*2]=std::numeric_limits<double>::max();
2575 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2578 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2580 int node= conn[inode];
2581 if(node>=0)//avoid polyhedron separator
2583 for (int idim=0; idim<dim; idim++)
2585 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2587 elem_bb[idim*2] = coords[node*dim+idim] ;
2589 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2591 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2596 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2597 elems->pushBackSilent(ielem);
2599 return elems.retn();
2603 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2604 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2605 * added in 'elems' parameter.
2607 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2609 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2610 if(getMeshDimension()==-1)
2612 elems->pushBackSilent(0);
2613 return elems.retn();
2615 int dim=getSpaceDimension();
2616 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2617 const int* conn = getNodalConnectivity()->getConstPointer();
2618 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2619 const double* coords = getCoords()->getConstPointer();
2620 int nbOfCells=getNumberOfCells();
2621 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2623 for (int i=0; i<dim; i++)
2625 elem_bb[i*2]=std::numeric_limits<double>::max();
2626 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2629 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2631 int node= conn[inode];
2632 if(node>=0)//avoid polyhedron separator
2634 for (int idim=0; idim<dim; idim++)
2636 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2638 elem_bb[idim*2] = coords[node*dim+idim] ;
2640 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2642 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2647 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2648 elems->pushBackSilent(ielem);
2650 return elems.retn();
2654 * Returns a type of a cell by its id.
2655 * \param [in] cellId - the id of the cell of interest.
2656 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2657 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2659 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2661 const int *ptI=_nodal_connec_index->getConstPointer();
2662 const int *pt=_nodal_connec->getConstPointer();
2663 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2664 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2667 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2668 throw INTERP_KERNEL::Exception(oss.str().c_str());
2673 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2674 * This method does not throw exception if geometric type \a type is not in \a this.
2675 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2676 * The coordinates array is not considered here.
2678 * \param [in] type the geometric type
2679 * \return cell ids in this having geometric type \a type.
2681 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2684 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2686 checkConnectivityFullyDefined();
2687 int nbCells=getNumberOfCells();
2688 int mdim=getMeshDimension();
2689 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2690 if(mdim!=(int)cm.getDimension())
2691 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2692 const int *ptI=_nodal_connec_index->getConstPointer();
2693 const int *pt=_nodal_connec->getConstPointer();
2694 for(int i=0;i<nbCells;i++)
2696 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2697 ret->pushBackSilent(i);
2703 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2705 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2707 const int *ptI=_nodal_connec_index->getConstPointer();
2708 const int *pt=_nodal_connec->getConstPointer();
2709 int nbOfCells=getNumberOfCells();
2711 for(int i=0;i<nbOfCells;i++)
2712 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2718 * Returns the nodal connectivity of a given cell.
2719 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2720 * all returned node ids can be used in getCoordinatesOfNode().
2721 * \param [in] cellId - an id of the cell of interest.
2722 * \param [in,out] conn - a vector where the node ids are appended. It is not
2723 * cleared before the appending.
2724 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2726 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2728 const int *ptI=_nodal_connec_index->getConstPointer();
2729 const int *pt=_nodal_connec->getConstPointer();
2730 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2735 std::string MEDCouplingUMesh::simpleRepr() const
2737 static const char msg0[]="No coordinates specified !";
2738 std::ostringstream ret;
2739 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2740 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2742 double tt=getTime(tmpp1,tmpp2);
2743 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2744 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2746 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2748 { ret << " Mesh dimension has not been set or is invalid !"; }
2751 const int spaceDim=getSpaceDimension();
2752 ret << spaceDim << "\nInfo attached on space dimension : ";
2753 for(int i=0;i<spaceDim;i++)
2754 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2758 ret << msg0 << "\n";
2759 ret << "Number of nodes : ";
2761 ret << getNumberOfNodes() << "\n";
2763 ret << msg0 << "\n";
2764 ret << "Number of cells : ";
2765 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2766 ret << getNumberOfCells() << "\n";
2768 ret << "No connectivity specified !" << "\n";
2769 ret << "Cell types present : ";
2770 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2772 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2773 ret << cm.getRepr() << " ";
2779 std::string MEDCouplingUMesh::advancedRepr() const
2781 std::ostringstream ret;
2782 ret << simpleRepr();
2783 ret << "\nCoordinates array : \n___________________\n\n";
2785 _coords->reprWithoutNameStream(ret);
2787 ret << "No array set !\n";
2788 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2789 reprConnectivityOfThisLL(ret);
2794 * This method returns a C++ code that is a dump of \a this.
2795 * This method will throw if this is not fully defined.
2797 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2799 static const char coordsName[]="coords";
2800 static const char connName[]="conn";
2801 static const char connIName[]="connI";
2802 checkFullyDefined();
2803 std::ostringstream ret; ret << "// coordinates" << std::endl;
2804 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2805 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2806 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2807 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2808 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2809 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2810 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2814 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2816 std::ostringstream ret;
2817 reprConnectivityOfThisLL(ret);
2822 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2823 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2824 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2827 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2828 * 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
2829 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2831 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2833 int mdim=getMeshDimension();
2835 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2836 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2837 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2838 bool needToCpyCT=true;
2841 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2849 if(!_nodal_connec_index)
2851 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2856 tmp2=_nodal_connec_index;
2859 ret->setConnectivity(tmp1,tmp2,false);
2864 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2865 ret->setCoords(coords);
2868 ret->setCoords(_coords);
2872 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2874 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2876 int nbOfCells=getNumberOfCells();
2877 const int *c=_nodal_connec->getConstPointer();
2878 const int *ci=_nodal_connec_index->getConstPointer();
2879 for(int i=0;i<nbOfCells;i++)
2881 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2882 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2883 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2888 stream << "Connectivity not defined !\n";
2891 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2893 const int *ptI=_nodal_connec_index->getConstPointer();
2894 const int *pt=_nodal_connec->getConstPointer();
2895 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2896 return ptI[cellId+1]-ptI[cellId]-1;
2898 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2902 * Returns types of cells of the specified part of \a this mesh.
2903 * This method avoids computing sub-mesh explicitely to get its types.
2904 * \param [in] begin - an array of cell ids of interest.
2905 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2906 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2907 * describing the cell types.
2908 * \throw If the coordinates array is not set.
2909 * \throw If the nodal connectivity of cells is not defined.
2912 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2914 checkFullyDefined();
2915 std::set<INTERP_KERNEL::NormalizedCellType> ret;
2916 const int *conn=_nodal_connec->getConstPointer();
2917 const int *connIndex=_nodal_connec_index->getConstPointer();
2918 for(const int *w=begin;w!=end;w++)
2919 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2924 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2925 * a set of types of cells constituting \a this mesh.
2926 * This method is for advanced users having prepared their connectivity before. For
2927 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2928 * \param [in] conn - the nodal connectivity array.
2929 * \param [in] connIndex - the nodal connectivity index array.
2930 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2933 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2935 DataArrayInt::SetArrayIn(conn,_nodal_connec);
2936 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2937 if(isComputingTypes)
2943 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2944 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2946 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2947 _nodal_connec(0),_nodal_connec_index(0),
2948 _types(other._types)
2950 if(other._nodal_connec)
2951 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2952 if(other._nodal_connec_index)
2953 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2956 MEDCouplingUMesh::~MEDCouplingUMesh()
2959 _nodal_connec->decrRef();
2960 if(_nodal_connec_index)
2961 _nodal_connec_index->decrRef();
2965 * Recomputes a set of cell types of \a this mesh. For more info see
2966 * \ref MEDCouplingUMeshNodalConnectivity.
2968 void MEDCouplingUMesh::computeTypes()
2970 if(_nodal_connec && _nodal_connec_index)
2973 const int *conn=_nodal_connec->getConstPointer();
2974 const int *connIndex=_nodal_connec_index->getConstPointer();
2975 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2977 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
2978 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2983 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2985 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2987 if(!_nodal_connec_index || !_nodal_connec || !_coords)
2988 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2992 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2994 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2996 if(!_nodal_connec_index || !_nodal_connec)
2997 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
3001 * Returns a number of cells constituting \a this mesh.
3002 * \return int - the number of cells in \a this mesh.
3003 * \throw If the nodal connectivity of cells is not defined.
3005 int MEDCouplingUMesh::getNumberOfCells() const
3007 if(_nodal_connec_index)
3008 return _nodal_connec_index->getNumberOfTuples()-1;
3013 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3017 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3018 * mesh. For more info see \ref MEDCouplingMeshesPage.
3019 * \return int - the dimension of \a this mesh.
3020 * \throw If the mesh dimension is not defined using setMeshDimension().
3022 int MEDCouplingUMesh::getMeshDimension() const
3025 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3030 * Returns a length of the nodal connectivity array.
3031 * This method is for test reason. Normally the integer returned is not useable by
3032 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3033 * \return int - the length of the nodal connectivity array.
3035 int MEDCouplingUMesh::getMeshLength() const
3037 return _nodal_connec->getNbOfElems();
3041 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3043 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3045 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3046 tinyInfo.push_back(getMeshDimension());
3047 tinyInfo.push_back(getNumberOfCells());
3049 tinyInfo.push_back(getMeshLength());
3051 tinyInfo.push_back(-1);
3055 * First step of unserialization process.
3057 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3059 return tinyInfo[6]<=0;
3063 * Second step of serialization process.
3064 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3066 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3068 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3070 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3074 * Third and final step of serialization process.
3076 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3078 MEDCouplingPointSet::serialize(a1,a2);
3079 if(getMeshDimension()>-1)
3081 a1=DataArrayInt::New();
3082 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3083 int *ptA1=a1->getPointer();
3084 const int *conn=getNodalConnectivity()->getConstPointer();
3085 const int *index=getNodalConnectivityIndex()->getConstPointer();
3086 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3087 std::copy(conn,conn+getMeshLength(),ptA1);
3094 * Second and final unserialization process.
3095 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3097 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3099 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3100 setMeshDimension(tinyInfo[5]);
3104 const int *recvBuffer=a1->getConstPointer();
3105 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3106 myConnecIndex->alloc(tinyInfo[6]+1,1);
3107 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3108 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3109 myConnec->alloc(tinyInfo[7],1);
3110 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3111 setConnectivity(myConnec, myConnecIndex);
3116 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3117 * CellIds are given using range specified by a start an end and step.
3119 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3121 checkFullyDefined();
3122 int ncell=getNumberOfCells();
3123 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3124 ret->_mesh_dim=_mesh_dim;
3125 ret->setCoords(_coords);
3126 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3127 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3128 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3130 const int *conn=_nodal_connec->getConstPointer();
3131 const int *connIndex=_nodal_connec_index->getConstPointer();
3132 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3134 if(work>=0 && work<ncell)
3136 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3140 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3141 throw INTERP_KERNEL::Exception(oss.str().c_str());
3144 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3145 int *newConnPtr=newConn->getPointer();
3146 std::set<INTERP_KERNEL::NormalizedCellType> types;
3148 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3150 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3151 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3153 ret->setConnectivity(newConn,newConnI,false);
3155 ret->copyTinyInfoFrom(this);
3160 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3161 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3162 * The return newly allocated mesh will share the same coordinates as \a this.
3164 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3166 checkFullyDefined();
3167 int ncell=getNumberOfCells();
3168 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3169 ret->_mesh_dim=_mesh_dim;
3170 ret->setCoords(_coords);
3171 std::size_t nbOfElemsRet=std::distance(begin,end);
3172 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3174 const int *conn=_nodal_connec->getConstPointer();
3175 const int *connIndex=_nodal_connec_index->getConstPointer();
3177 for(const int *work=begin;work!=end;work++,newNbring++)
3179 if(*work>=0 && *work<ncell)
3180 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3184 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3185 throw INTERP_KERNEL::Exception(oss.str().c_str());
3188 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3189 int *connRetWork=connRet;
3190 std::set<INTERP_KERNEL::NormalizedCellType> types;
3191 for(const int *work=begin;work!=end;work++)
3193 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3194 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3196 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3197 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3198 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3199 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3200 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3202 ret->copyTinyInfoFrom(this);
3207 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3209 * For 1D cells, the returned field contains lengths.<br>
3210 * For 2D cells, the returned field contains areas.<br>
3211 * For 3D cells, the returned field contains volumes.
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 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3215 * and one time . The caller is to delete this field using decrRef() as it is no
3218 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3220 std::string name="MeasureOfMesh_";
3222 int nbelem=getNumberOfCells();
3223 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3224 field->setName(name.c_str());
3225 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3226 array->alloc(nbelem,1);
3227 double *area_vol=array->getPointer();
3228 field->setArray(array) ; array=0;
3229 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3230 field->synchronizeTimeWithMesh();
3231 if(getMeshDimension()!=-1)
3234 INTERP_KERNEL::NormalizedCellType type;
3235 int dim_space=getSpaceDimension();
3236 const double *coords=getCoords()->getConstPointer();
3237 const int *connec=getNodalConnectivity()->getConstPointer();
3238 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3239 for(int iel=0;iel<nbelem;iel++)
3241 ipt=connec_index[iel];
3242 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3243 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);
3246 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3250 area_vol[0]=std::numeric_limits<double>::max();
3252 return field.retn();
3256 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3258 * For 1D cells, the returned array contains lengths.<br>
3259 * For 2D cells, the returned array contains areas.<br>
3260 * For 3D cells, the returned array contains volumes.
3261 * This method avoids building explicitly a part of \a this mesh to perform the work.
3262 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3263 * orientation, i.e. the volume is always positive.
3264 * \param [in] begin - an array of cell ids of interest.
3265 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3266 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3267 * delete this array using decrRef() as it is no more needed.
3269 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3270 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3271 * \sa getMeasureField()
3273 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3275 std::string name="PartMeasureOfMesh_";
3277 int nbelem=(int)std::distance(begin,end);
3278 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3279 array->setName(name.c_str());
3280 array->alloc(nbelem,1);
3281 double *area_vol=array->getPointer();
3282 if(getMeshDimension()!=-1)
3285 INTERP_KERNEL::NormalizedCellType type;
3286 int dim_space=getSpaceDimension();
3287 const double *coords=getCoords()->getConstPointer();
3288 const int *connec=getNodalConnectivity()->getConstPointer();
3289 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3290 for(const int *iel=begin;iel!=end;iel++)
3292 ipt=connec_index[*iel];
3293 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3294 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3297 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3301 area_vol[0]=std::numeric_limits<double>::max();
3303 return array.retn();
3307 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3308 * \a this one. The returned field contains the dual cell volume for each corresponding
3309 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3310 * the dual mesh in P1 sens of \a this.<br>
3311 * For 1D cells, the returned field contains lengths.<br>
3312 * For 2D cells, the returned field contains areas.<br>
3313 * For 3D cells, the returned field contains volumes.
3314 * This method is useful to check "P1*" conservative interpolators.
3315 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3316 * orientation, i.e. the volume is always positive.
3317 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3318 * nodes and one time. The caller is to delete this array using decrRef() as
3319 * it is no more needed.
3321 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3323 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3324 std::string name="MeasureOnNodeOfMesh_";
3326 int nbNodes=getNumberOfNodes();
3327 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3328 double cst=1./((double)getMeshDimension()+1.);
3329 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3330 array->alloc(nbNodes,1);
3331 double *valsToFill=array->getPointer();
3332 std::fill(valsToFill,valsToFill+nbNodes,0.);
3333 const double *values=tmp->getArray()->getConstPointer();
3334 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3335 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3336 getReverseNodalConnectivity(da,daInd);
3337 const int *daPtr=da->getConstPointer();
3338 const int *daIPtr=daInd->getConstPointer();
3339 for(int i=0;i<nbNodes;i++)
3340 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3341 valsToFill[i]+=cst*values[*cell];
3343 ret->setArray(array);
3348 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3349 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3350 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3351 * and are normalized.
3352 * <br> \a this can be either
3353 * - a 2D mesh in 2D or 3D space or
3354 * - an 1D mesh in 2D space.
3356 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3357 * cells and one time. The caller is to delete this field using decrRef() as
3358 * it is no more needed.
3359 * \throw If the nodal connectivity of cells is not defined.
3360 * \throw If the coordinates array is not set.
3361 * \throw If the mesh dimension is not set.
3362 * \throw If the mesh and space dimension is not as specified above.
3364 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3366 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3367 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3368 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3369 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3370 int nbOfCells=getNumberOfCells();
3371 int nbComp=getMeshDimension()+1;
3372 array->alloc(nbOfCells,nbComp);
3373 double *vals=array->getPointer();
3374 const int *connI=_nodal_connec_index->getConstPointer();
3375 const int *conn=_nodal_connec->getConstPointer();
3376 const double *coords=_coords->getConstPointer();
3377 if(getMeshDimension()==2)
3379 if(getSpaceDimension()==3)
3381 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3382 const double *locPtr=loc->getConstPointer();
3383 for(int i=0;i<nbOfCells;i++,vals+=3)
3385 int offset=connI[i];
3386 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3387 double n=INTERP_KERNEL::norm<3>(vals);
3388 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3393 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3394 const double *isAbsPtr=isAbs->getArray()->begin();
3395 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3396 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3399 else//meshdimension==1
3402 for(int i=0;i<nbOfCells;i++)
3404 int offset=connI[i];
3405 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3406 double n=INTERP_KERNEL::norm<2>(tmp);
3407 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3412 ret->setArray(array);
3414 ret->synchronizeTimeWithSupport();
3419 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3420 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3421 * and are normalized.
3422 * <br> \a this can be either
3423 * - a 2D mesh in 2D or 3D space or
3424 * - an 1D mesh in 2D space.
3426 * This method avoids building explicitly a part of \a this mesh to perform the work.
3427 * \param [in] begin - an array of cell ids of interest.
3428 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3429 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3430 * cells and one time. The caller is to delete this field using decrRef() as
3431 * it is no more needed.
3432 * \throw If the nodal connectivity of cells is not defined.
3433 * \throw If the coordinates array is not set.
3434 * \throw If the mesh dimension is not set.
3435 * \throw If the mesh and space dimension is not as specified above.
3436 * \sa buildOrthogonalField()
3438 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3439 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3441 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3443 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3444 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3445 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3446 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3447 std::size_t nbelems=std::distance(begin,end);
3448 int nbComp=getMeshDimension()+1;
3449 array->alloc((int)nbelems,nbComp);
3450 double *vals=array->getPointer();
3451 const int *connI=_nodal_connec_index->getConstPointer();
3452 const int *conn=_nodal_connec->getConstPointer();
3453 const double *coords=_coords->getConstPointer();
3454 if(getMeshDimension()==2)
3456 if(getSpaceDimension()==3)
3458 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3459 const double *locPtr=loc->getConstPointer();
3460 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3462 int offset=connI[*i];
3463 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3464 double n=INTERP_KERNEL::norm<3>(vals);
3465 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3470 for(std::size_t i=0;i<nbelems;i++)
3471 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3474 else//meshdimension==1
3477 for(const int *i=begin;i!=end;i++)
3479 int offset=connI[*i];
3480 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3481 double n=INTERP_KERNEL::norm<2>(tmp);
3482 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3487 ret->setArray(array);
3489 ret->synchronizeTimeWithSupport();
3494 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3495 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3496 * and are \b not normalized.
3497 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3498 * cells and one time. The caller is to delete this field using decrRef() as
3499 * it is no more needed.
3500 * \throw If the nodal connectivity of cells is not defined.
3501 * \throw If the coordinates array is not set.
3502 * \throw If \a this->getMeshDimension() != 1.
3503 * \throw If \a this mesh includes cells of type other than SEG2.
3505 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3507 if(getMeshDimension()!=1)
3508 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3509 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3510 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3511 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3512 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3513 int nbOfCells=getNumberOfCells();
3514 int spaceDim=getSpaceDimension();
3515 array->alloc(nbOfCells,spaceDim);
3516 double *pt=array->getPointer();
3517 const double *coo=getCoords()->getConstPointer();
3518 std::vector<int> conn;
3520 for(int i=0;i<nbOfCells;i++)
3523 getNodeIdsOfCell(i,conn);
3524 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3526 ret->setArray(array);
3528 ret->synchronizeTimeWithSupport();
3533 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3534 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3535 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3536 * from. If a result face is shared by two 3D cells, then the face in included twice in
3538 * \param [in] origin - 3 components of a point defining location of the plane.
3539 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3540 * must be greater than 1e-6.
3541 * \param [in] eps - half-thickness of the plane.
3542 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3543 * producing correspondent 2D cells. The caller is to delete this array
3544 * using decrRef() as it is no more needed.
3545 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3546 * not share the node coordinates array with \a this mesh. The caller is to
3547 * delete this mesh using decrRef() as it is no more needed.
3548 * \throw If the coordinates array is not set.
3549 * \throw If the nodal connectivity of cells is not defined.
3550 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3551 * \throw If magnitude of \a vec is less than 1e-6.
3552 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3553 * \throw If \a this includes quadratic cells.
3555 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3557 checkFullyDefined();
3558 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3559 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3560 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3561 if(candidates->empty())
3562 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3563 std::vector<int> nodes;
3564 DataArrayInt *cellIds1D=0;
3565 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3566 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3567 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3568 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3569 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3570 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3571 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3572 revDesc2=0; revDescIndx2=0;
3573 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3574 revDesc1=0; revDescIndx1=0;
3575 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3576 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3578 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3579 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3581 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3582 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3583 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3584 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3585 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3586 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3587 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3588 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3589 if(cellIds2->empty())
3590 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3591 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3592 ret->setCoords(mDesc1->getCoords());
3593 ret->setConnectivity(conn,connI,true);
3594 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3599 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3600 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
3601 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3603 * \param [in] origin - 3 components of a point defining location of the plane.
3604 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3605 * must be greater than 1e-6.
3606 * \param [in] eps - half-thickness of the plane.
3607 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3608 * producing correspondent segments. The caller is to delete this array
3609 * using decrRef() as it is no more needed.
3610 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3611 * mesh in 3D space. This mesh does not share the node coordinates array with
3612 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3614 * \throw If the coordinates array is not set.
3615 * \throw If the nodal connectivity of cells is not defined.
3616 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3617 * \throw If magnitude of \a vec is less than 1e-6.
3618 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3619 * \throw If \a this includes quadratic cells.
3621 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3623 checkFullyDefined();
3624 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3625 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3626 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3627 if(candidates->empty())
3628 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3629 std::vector<int> nodes;
3630 DataArrayInt *cellIds1D=0;
3631 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3632 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3633 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3634 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3635 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3636 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3637 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3638 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3639 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3641 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3642 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3644 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3645 int ncellsSub=subMesh->getNumberOfCells();
3646 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3647 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3648 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3649 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3650 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3652 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3653 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3654 for(int i=0;i<ncellsSub;i++)
3656 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3658 if(cut3DSurf[i].first!=-2)
3660 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3661 connI->pushBackSilent(conn->getNumberOfTuples());
3662 cellIds2->pushBackSilent(i);
3666 int cellId3DSurf=cut3DSurf[i].second;
3667 int offset=nodalI[cellId3DSurf]+1;
3668 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3669 for(int j=0;j<nbOfEdges;j++)
3671 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3672 connI->pushBackSilent(conn->getNumberOfTuples());
3673 cellIds2->pushBackSilent(cellId3DSurf);
3678 if(cellIds2->empty())
3679 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3680 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3681 ret->setCoords(mDesc1->getCoords());
3682 ret->setConnectivity(conn,connI,true);
3683 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3688 * Finds cells whose bounding boxes intersect a given plane.
3689 * \param [in] origin - 3 components of a point defining location of the plane.
3690 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3691 * must be greater than 1e-6.
3692 * \param [in] eps - half-thickness of the plane.
3693 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3694 * cells. The caller is to delete this array using decrRef() as it is no more
3696 * \throw If the coordinates array is not set.
3697 * \throw If the nodal connectivity of cells is not defined.
3698 * \throw If \a this->getSpaceDimension() != 3.
3699 * \throw If magnitude of \a vec is less than 1e-6.
3700 * \sa buildSlice3D()
3702 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3704 checkFullyDefined();
3705 if(getSpaceDimension()!=3)
3706 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3707 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3709 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3711 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3712 double angle=acos(vec[2]/normm);
3713 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3717 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3718 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3719 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3721 mw->getBoundingBox(bbox);
3722 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3723 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3727 getBoundingBox(bbox);
3728 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3729 cellIds=getCellsInBoundingBox(bbox,eps);
3731 return cellIds.retn();
3735 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3736 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3737 * No consideration of coordinate is done by this method.
3738 * 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)
3739 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3741 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3743 if(getMeshDimension()!=1)
3744 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3745 int nbCells=getNumberOfCells();
3747 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3748 const int *connI=_nodal_connec_index->getConstPointer();
3749 const int *conn=_nodal_connec->getConstPointer();
3750 int ref=conn[connI[0]+2];
3751 for(int i=1;i<nbCells;i++)
3753 if(conn[connI[i]+1]!=ref)
3755 ref=conn[connI[i]+2];
3761 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3762 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3763 * \param pt reference point of the line
3764 * \param v normalized director vector of the line
3765 * \param eps max precision before throwing an exception
3766 * \param res output of size this->getNumberOfCells
3768 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3770 if(getMeshDimension()!=1)
3771 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3772 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3773 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3774 if(getSpaceDimension()!=3)
3775 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3776 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3777 const double *fPtr=f->getArray()->getConstPointer();
3779 for(int i=0;i<getNumberOfCells();i++)
3781 const double *tmp1=fPtr+3*i;
3782 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3783 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3784 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3785 double n1=INTERP_KERNEL::norm<3>(tmp);
3786 n1/=INTERP_KERNEL::norm<3>(tmp1);
3788 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3790 const double *coo=getCoords()->getConstPointer();
3791 for(int i=0;i<getNumberOfNodes();i++)
3793 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3794 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3795 res[i]=std::accumulate(tmp,tmp+3,0.);
3800 * 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.
3801 * \a this is expected to be a mesh so that its space dimension is equal to its
3802 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3803 * 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).
3805 * 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
3806 * 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).
3807 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3809 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3810 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3812 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3813 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3814 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3815 * \return the positive value of the distance.
3816 * \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
3818 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3820 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
3822 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3823 if(meshDim!=spaceDim-1)
3824 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3825 if(meshDim!=2 && meshDim!=1)
3826 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3827 checkFullyDefined();
3828 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3829 { 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()); }
3830 DataArrayInt *ret1=0;
3831 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3832 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3833 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3834 cellId=*ret1Safe->begin();
3835 return *ret0->begin();
3839 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3840 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
3841 * 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
3842 * 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).
3843 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3845 * \a this is expected to be a mesh so that its space dimension is equal to its
3846 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3847 * 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).
3849 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3850 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3852 * \param [in] pts the list of points in which each tuple represents a point
3853 * \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.
3854 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3855 * \throw if number of components of \a pts is not equal to the space dimension.
3856 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3857 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3859 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
3862 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3863 pts->checkAllocated();
3864 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3865 if(meshDim!=spaceDim-1)
3866 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3867 if(meshDim!=2 && meshDim!=1)
3868 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3869 if(pts->getNumberOfComponents()!=spaceDim)
3871 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3872 throw INTERP_KERNEL::Exception(oss.str().c_str());
3874 checkFullyDefined();
3875 int nbCells=getNumberOfCells();
3877 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3878 int nbOfPts=pts->getNumberOfTuples();
3879 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3880 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3881 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3882 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3883 std::vector<double> bbox;
3884 getBoundingBoxForBBTree(bbox);
3889 BBTreeDst<3> myTree(&bbox[0],0,0,nbCells);
3890 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3892 double x=std::numeric_limits<double>::max();
3893 std::vector<int> elems;
3894 myTree.getMinDistanceOfMax(ptsPtr,x);
3895 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3896 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3902 BBTreeDst<2> myTree(&bbox[0],0,0,nbCells);
3903 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3905 double x=std::numeric_limits<double>::max();
3906 std::vector<int> elems;
3907 myTree.getMinDistanceOfMax(ptsPtr,x);
3908 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3909 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3914 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3916 cellIds=ret1.retn();
3921 * \param [in] pt the start pointer (included) of the coordinates of the point
3922 * \param [in] cellIdsBg the start pointer (included) of cellIds
3923 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3924 * \param [in] nc nodal connectivity
3925 * \param [in] ncI nodal connectivity index
3926 * \param [in,out] ret0 the min distance between \a this and the external input point
3927 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3928 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3930 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)
3933 ret0=std::numeric_limits<double>::max();
3934 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3936 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3938 case INTERP_KERNEL::NORM_TRI3:
3940 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3942 { ret0=tmp; cellId=*zeCell; }
3945 case INTERP_KERNEL::NORM_QUAD4:
3946 case INTERP_KERNEL::NORM_POLYGON:
3948 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3950 { ret0=tmp; cellId=*zeCell; }
3954 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3960 * \param [in] pt the start pointer (included) of the coordinates of the point
3961 * \param [in] cellIdsBg the start pointer (included) of cellIds
3962 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3963 * \param [in] nc nodal connectivity
3964 * \param [in] ncI nodal connectivity index
3965 * \param [in,out] ret0 the min distance between \a this and the external input point
3966 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3967 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3969 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)
3972 ret0=std::numeric_limits<double>::max();
3973 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3975 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3977 case INTERP_KERNEL::NORM_SEG2:
3979 std::size_t uselessEntry=0;
3980 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
3983 { ret0=tmp; cellId=*zeCell; }
3987 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3993 * Finds cells in contact with a ball (i.e. a point with precision).
3994 * \warning This method is suitable if the caller intends to evaluate only one
3995 * point, for more points getCellsContainingPoints() is recommended as it is
3997 * \param [in] pos - array of coordinates of the ball central point.
3998 * \param [in] eps - ball radius.
3999 * \return int - a smallest id of cells being in contact with the ball, -1 in case
4000 * if there are no such cells.
4001 * \throw If the coordinates array is not set.
4002 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4004 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4006 std::vector<int> elts;
4007 getCellsContainingPoint(pos,eps,elts);
4010 return elts.front();
4014 * Finds cells in contact with a ball (i.e. a point with precision).
4015 * \warning This method is suitable if the caller intends to evaluate only one
4016 * point, for more points getCellsContainingPoints() is recommended as it is
4018 * \param [in] pos - array of coordinates of the ball central point.
4019 * \param [in] eps - ball radius.
4020 * \param [in,out] elts - vector returning ids of the found cells. It is cleared
4021 * before inserting ids.
4022 * \throw If the coordinates array is not set.
4023 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4025 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4026 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4028 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4030 std::vector<int> eltsIndex;
4031 getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
4036 namespace ParaMEDMEM
4038 template<const int SPACEDIMM>
4042 static const int MY_SPACEDIM=SPACEDIMM;
4043 static const int MY_MESHDIM=8;
4044 typedef int MyConnType;
4045 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4047 // useless, but for windows compilation ...
4048 const double* getCoordinatesPtr() const { return 0; }
4049 const int* getConnectivityPtr() const { return 0; }
4050 const int* getConnectivityIndexPtr() const { return 0; }
4051 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4055 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4057 INTERP_KERNEL::Edge *ret=0;
4060 case INTERP_KERNEL::NORM_SEG2:
4062 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4065 case INTERP_KERNEL::NORM_SEG3:
4067 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4068 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4069 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4070 bool colinearity=inters.areColinears();
4071 delete e1; delete e2;
4073 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4075 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4076 mapp2[bg[2]].second=false;
4080 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4086 * 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'.
4087 * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4088 * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4090 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4093 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.
4094 const double *coo=mDesc->getCoords()->getConstPointer();
4095 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4096 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4098 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4099 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4100 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4102 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4103 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4105 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4106 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4108 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4109 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4111 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4113 if((*it2).second.second)
4114 mapp[(*it2).second.first]=(*it2).first;
4115 ((*it2).second.first)->decrRef();
4120 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4124 int locId=nodeId-offset2;
4125 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4129 int locId=nodeId-offset1;
4130 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4132 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4135 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4136 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4137 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4139 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4141 int eltId1=abs(*desc1)-1;
4142 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4144 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4145 if(it==mappRev.end())
4147 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4158 template<int SPACEDIM>
4159 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4160 double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4162 std::vector<double> bbox;
4163 eltsIndex.resize(nbOfPoints+1);
4166 getBoundingBoxForBBTree(bbox);
4167 int nbOfCells=getNumberOfCells();
4168 const int *conn=_nodal_connec->getConstPointer();
4169 const int *connI=_nodal_connec_index->getConstPointer();
4170 double bb[2*SPACEDIM];
4171 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4172 for(int i=0;i<nbOfPoints;i++)
4174 eltsIndex[i+1]=eltsIndex[i];
4175 for(int j=0;j<SPACEDIM;j++)
4177 bb[2*j]=pos[SPACEDIM*i+j];
4178 bb[2*j+1]=pos[SPACEDIM*i+j];
4180 std::vector<int> candidates;
4181 myTree.getIntersectingElems(bb,candidates);
4182 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4184 int sz=connI[(*iter)+1]-connI[*iter]-1;
4185 if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4186 (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4187 coords,conn+connI[*iter]+1,sz,eps))
4190 elts.push_back(*iter);
4196 * Finds cells in contact with several balls (i.e. points with precision).
4197 * This method is an extension of getCellContainingPoint() and
4198 * getCellsContainingPoint() for the case of multiple points.
4199 * \param [in] pos - an array of coordinates of points in full interlace mode :
4200 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4201 * this->getSpaceDimension() * \a nbOfPoints
4202 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4203 * \param [in] eps - radius of balls (i.e. the precision).
4204 * \param [in,out] elts - vector returning ids of found cells.
4205 * \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4206 * dividing cell ids in \a elts into groups each referring to one
4207 * point. Its every element (except the last one) is an index pointing to the
4208 * first id of a group of cells. For example cells in contact with the *i*-th
4209 * point are described by following range of indices:
4210 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4211 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4212 * Number of cells in contact with the *i*-th point is
4213 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4214 * \throw If the coordinates array is not set.
4215 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4217 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4218 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4220 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4221 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4223 int spaceDim=getSpaceDimension();
4224 int mDim=getMeshDimension();
4229 const double *coords=_coords->getConstPointer();
4230 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4237 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4239 else if(spaceDim==2)
4243 const double *coords=_coords->getConstPointer();
4244 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4247 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4249 else if(spaceDim==1)
4253 const double *coords=_coords->getConstPointer();
4254 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4257 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4260 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4264 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4265 * least two its edges intersect each other anywhere except their extremities. An
4266 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4267 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4268 * cleared before filling in.
4269 * \param [in] eps - precision.
4270 * \throw If \a this->getMeshDimension() != 2.
4271 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4273 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4275 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4276 if(getMeshDimension()!=2)
4277 throw INTERP_KERNEL::Exception(msg);
4278 int spaceDim=getSpaceDimension();
4279 if(spaceDim!=2 && spaceDim!=3)
4280 throw INTERP_KERNEL::Exception(msg);
4281 const int *conn=_nodal_connec->getConstPointer();
4282 const int *connI=_nodal_connec_index->getConstPointer();
4283 int nbOfCells=getNumberOfCells();
4284 std::vector<double> cell2DinS2;
4285 for(int i=0;i<nbOfCells;i++)
4287 int offset=connI[i];
4288 int nbOfNodesForCell=connI[i+1]-offset-1;
4289 if(nbOfNodesForCell<=3)
4291 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4292 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4293 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4300 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4302 * 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.
4303 * 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.
4305 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4306 * This convex envelop is computed using Jarvis march algorithm.
4307 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4308 * 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)
4309 * 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.
4311 * \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.
4313 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4315 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4316 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4317 checkFullyDefined();
4318 const double *coords=getCoords()->getConstPointer();
4319 int nbOfCells=getNumberOfCells();
4320 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4321 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4322 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4323 int *workIndexOut=nodalConnecIndexOut->getPointer();
4325 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4326 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4327 std::set<INTERP_KERNEL::NormalizedCellType> types;
4328 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4329 isChanged->alloc(0,1);
4330 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4332 int pos=nodalConnecOut->getNumberOfTuples();
4333 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4334 isChanged->pushBackSilent(i);
4335 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4336 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4338 if(isChanged->empty())
4340 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4342 return isChanged.retn();
4346 * This method is \b NOT const because it can modify \a this.
4347 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4348 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4349 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4350 * \b 1 for translation and rotation around point of 'mesh1D'.
4351 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4353 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4355 checkFullyDefined();
4356 mesh1D->checkFullyDefined();
4357 if(!mesh1D->isContiguous1D())
4358 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4359 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4360 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4361 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4362 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4363 if(mesh1D->getMeshDimension()!=1)
4364 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4366 if(isPresenceOfQuadratic())
4368 if(mesh1D->isFullyQuadratic())
4371 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4374 int oldNbOfNodes=getNumberOfNodes();
4375 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4380 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4385 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4389 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4391 setCoords(newCoords);
4392 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4398 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4399 * If it is not the case an exception will be thrown.
4400 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4401 * intersection of plane defined by ('origin','vec').
4402 * This method has one in/out parameter : 'cut3DCurve'.
4403 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4404 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4405 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4406 * This method will throw an exception if \a this contains a non linear segment.
4408 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4410 checkFullyDefined();
4411 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4412 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4413 int ncells=getNumberOfCells();
4414 int nnodes=getNumberOfNodes();
4415 double vec2[3],vec3[3],vec4[3];
4416 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4418 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4419 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4420 const int *conn=_nodal_connec->getConstPointer();
4421 const int *connI=_nodal_connec_index->getConstPointer();
4422 const double *coo=_coords->getConstPointer();
4423 std::vector<double> addCoo;
4424 for(int i=0;i<ncells;i++)
4426 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4428 if(cut3DCurve[i]==-2)
4430 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4431 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];
4432 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4433 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4434 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4436 const double *st2=coo+3*st;
4437 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4438 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]));
4439 if(pos>eps && pos<1-eps)
4441 int nNode=((int)addCoo.size())/3;
4442 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4443 addCoo.insert(addCoo.end(),vec4,vec4+3);
4444 cut3DCurve[i]=nnodes+nNode;
4450 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4454 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4455 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4456 coo2->alloc(newNbOfNodes,3);
4457 double *tmp=coo2->getPointer();
4458 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4459 std::copy(addCoo.begin(),addCoo.end(),tmp);
4460 DataArrayDouble::SetArrayIn(coo2,_coords);
4465 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4466 * \param mesh1D is the input 1D mesh used for translation computation.
4467 * \return newCoords new coords filled by this method.
4469 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4471 int oldNbOfNodes=getNumberOfNodes();
4472 int nbOf1DCells=mesh1D->getNumberOfCells();
4473 int spaceDim=getSpaceDimension();
4474 DataArrayDouble *ret=DataArrayDouble::New();
4475 std::vector<bool> isQuads;
4476 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4477 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4478 double *retPtr=ret->getPointer();
4479 const double *coords=getCoords()->getConstPointer();
4480 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4482 std::vector<double> c;
4486 for(int i=0;i<nbOf1DCells;i++)
4489 mesh1D->getNodeIdsOfCell(i,v);
4491 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4492 mesh1D->getCoordinatesOfNode(v[0],c);
4493 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4494 for(int j=0;j<oldNbOfNodes;j++)
4495 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4499 mesh1D->getCoordinatesOfNode(v[1],c);
4500 mesh1D->getCoordinatesOfNode(v[0],c);
4501 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4502 for(int j=0;j<oldNbOfNodes;j++)
4503 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4506 ret->copyStringInfoFrom(*getCoords());
4511 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4512 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4513 * \return newCoords new coords filled by this method.
4515 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4517 if(mesh1D->getSpaceDimension()==2)
4518 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4519 if(mesh1D->getSpaceDimension()==3)
4520 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4521 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4525 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4526 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4527 * \return newCoords new coords filled by this method.
4529 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4532 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4533 int oldNbOfNodes=getNumberOfNodes();
4534 int nbOf1DCells=mesh1D->getNumberOfCells();
4536 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4537 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4538 int nbOfLevsInVec=nbOf1DCells+1;
4539 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4540 double *retPtr=ret->getPointer();
4541 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4542 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4543 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4544 tmp->setCoords(tmp2);
4545 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4546 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4547 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4548 for(int i=1;i<nbOfLevsInVec;i++)
4550 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4551 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4552 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4553 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4554 tmp->translate(vec);
4555 double tmp3[2],radius,alpha,alpha0;
4556 const double *p0=i+1<nbOfLevsInVec?begin:third;
4557 const double *p1=i+1<nbOfLevsInVec?end:begin;
4558 const double *p2=i+1<nbOfLevsInVec?third:end;
4559 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4560 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]);
4561 double angle=acos(cosangle/(radius*radius));
4562 tmp->rotate(end,0,angle);
4563 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4569 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4570 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4571 * \return newCoords new coords filled by this method.
4573 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4576 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4577 int oldNbOfNodes=getNumberOfNodes();
4578 int nbOf1DCells=mesh1D->getNumberOfCells();
4580 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4581 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4582 int nbOfLevsInVec=nbOf1DCells+1;
4583 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4584 double *retPtr=ret->getPointer();
4585 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4586 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4587 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4588 tmp->setCoords(tmp2);
4589 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4590 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4591 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4592 for(int i=1;i<nbOfLevsInVec;i++)
4594 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4595 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4596 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4597 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4598 tmp->translate(vec);
4599 double tmp3[2],radius,alpha,alpha0;
4600 const double *p0=i+1<nbOfLevsInVec?begin:third;
4601 const double *p1=i+1<nbOfLevsInVec?end:begin;
4602 const double *p2=i+1<nbOfLevsInVec?third:end;
4603 double vecPlane[3]={
4604 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4605 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4606 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4608 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4611 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4612 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4613 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4615 double c2=cos(asin(s2));
4617 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4618 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4619 {-vec2[1]*s2, vec2[0]*s2, c2}
4621 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]};
4622 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]};
4623 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]};
4624 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4625 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]);
4626 double angle=acos(cosangle/(radius*radius));
4627 tmp->rotate(end,vecPlane,angle);
4630 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4636 * This method is private because not easy to use for end user. This method is const contrary to
4637 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4638 * the coords sorted slice by slice.
4639 * \param isQuad specifies presence of quadratic cells.
4641 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4643 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4644 int nbOf2DCells=getNumberOfCells();
4645 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4646 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4647 const int *conn=_nodal_connec->getConstPointer();
4648 const int *connI=_nodal_connec_index->getConstPointer();
4649 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4650 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4651 newConnI->alloc(nbOf3DCells+1,1);
4652 int *newConnIPtr=newConnI->getPointer();
4654 std::vector<int> newc;
4655 for(int j=0;j<nbOf2DCells;j++)
4657 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4658 *newConnIPtr++=(int)newc.size();
4660 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4661 int *newConnPtr=newConn->getPointer();
4662 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4663 newConnIPtr=newConnI->getPointer();
4664 for(int iz=0;iz<nbOf1DCells;iz++)
4667 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4668 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4670 int icell=(int)(iter-newc.begin());
4671 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4674 *newConnPtr=(*iter)+iz*deltaPerLev;
4679 *newConnPtr=(*iter);
4682 ret->setConnectivity(newConn,newConnI,true);
4683 ret->setCoords(getCoords());
4688 * Checks if \a this mesh is constituted by only quadratic cells.
4689 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4690 * \throw If the coordinates array is not set.
4691 * \throw If the nodal connectivity of cells is not defined.
4693 bool MEDCouplingUMesh::isFullyQuadratic() const
4695 checkFullyDefined();
4697 int nbOfCells=getNumberOfCells();
4698 for(int i=0;i<nbOfCells && ret;i++)
4700 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4701 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4702 ret=cm.isQuadratic();
4708 * Checks if \a this mesh includes any quadratic cell.
4709 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4710 * \throw If the coordinates array is not set.
4711 * \throw If the nodal connectivity of cells is not defined.
4713 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4715 checkFullyDefined();
4717 int nbOfCells=getNumberOfCells();
4718 for(int i=0;i<nbOfCells && !ret;i++)
4720 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4721 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4722 ret=cm.isQuadratic();
4728 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4729 * this mesh, it remains unchanged.
4730 * \throw If the coordinates array is not set.
4731 * \throw If the nodal connectivity of cells is not defined.
4733 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4735 checkFullyDefined();
4736 int nbOfCells=getNumberOfCells();
4738 const int *iciptr=_nodal_connec_index->getConstPointer();
4739 for(int i=0;i<nbOfCells;i++)
4741 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4742 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4743 if(cm.isQuadratic())
4745 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4746 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4747 if(!cml.isDynamic())
4748 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4750 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4755 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4756 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4757 const int *icptr=_nodal_connec->getConstPointer();
4758 newConn->alloc(getMeshLength()-delta,1);
4759 newConnI->alloc(nbOfCells+1,1);
4760 int *ocptr=newConn->getPointer();
4761 int *ociptr=newConnI->getPointer();
4764 for(int i=0;i<nbOfCells;i++,ociptr++)
4766 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4767 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4768 if(!cm.isQuadratic())
4770 _types.insert(type);
4771 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4772 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4776 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4777 _types.insert(typel);
4778 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4779 int newNbOfNodes=cml.getNumberOfNodes();
4781 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4782 *ocptr++=(int)typel;
4783 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4784 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4787 setConnectivity(newConn,newConnI,false);
4791 * This method converts all linear cell in \a this to quadratic one.
4792 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4793 * 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)
4794 * 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.
4795 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4796 * end of the existing coordinates.
4798 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4799 * corresponding quadratic cells. 1 is those creating the 'most' complex.
4800 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4802 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4804 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4806 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4808 DataArrayInt *conn=0,*connI=0;
4809 DataArrayDouble *coords=0;
4810 std::set<INTERP_KERNEL::NormalizedCellType> types;
4811 checkFullyDefined();
4812 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4813 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4814 int meshDim=getMeshDimension();
4815 switch(conversionType)
4821 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4822 connSafe=conn; connISafe=connI; coordsSafe=coords;
4825 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4826 connSafe=conn; connISafe=connI; coordsSafe=coords;
4829 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4830 connSafe=conn; connISafe=connI; coordsSafe=coords;
4833 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4841 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4842 connSafe=conn; connISafe=connI; coordsSafe=coords;
4845 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4846 connSafe=conn; connISafe=connI; coordsSafe=coords;
4849 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4850 connSafe=conn; connISafe=connI; coordsSafe=coords;
4853 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4858 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4860 setConnectivity(connSafe,connISafe,false);
4862 setCoords(coordsSafe);
4867 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4868 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4869 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4871 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4873 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4874 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4875 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4876 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4877 int nbOfCells=getNumberOfCells();
4878 int nbOfNodes=getNumberOfNodes();
4879 const int *cPtr=_nodal_connec->getConstPointer();
4880 const int *icPtr=_nodal_connec_index->getConstPointer();
4881 int lastVal=0,offset=nbOfNodes;
4882 for(int i=0;i<nbOfCells;i++,icPtr++)
4884 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4885 if(type==INTERP_KERNEL::NORM_SEG2)
4887 types.insert(INTERP_KERNEL::NORM_SEG3);
4888 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4889 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4890 newConn->pushBackSilent(offset++);
4892 newConnI->pushBackSilent(lastVal);
4893 ret->pushBackSilent(i);
4898 lastVal+=(icPtr[1]-icPtr[0]);
4899 newConnI->pushBackSilent(lastVal);
4900 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4903 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4904 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4908 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)
4910 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4911 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4912 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4914 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4915 DataArrayInt *conn1D=0,*conn1DI=0;
4916 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4917 DataArrayDouble *coordsTmp=0;
4918 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4919 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4920 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4921 const int *c1DPtr=conn1D->begin();
4922 const int *c1DIPtr=conn1DI->begin();
4923 int nbOfCells=getNumberOfCells();
4924 const int *cPtr=_nodal_connec->getConstPointer();
4925 const int *icPtr=_nodal_connec_index->getConstPointer();
4927 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4929 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4930 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4931 if(!cm.isQuadratic())
4933 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4934 types.insert(typ2); newConn->pushBackSilent(typ2);
4935 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4936 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4937 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4938 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4939 newConnI->pushBackSilent(lastVal);
4940 ret->pushBackSilent(i);
4945 lastVal+=(icPtr[1]-icPtr[0]);
4946 newConnI->pushBackSilent(lastVal);
4947 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4950 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4955 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4956 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4957 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4959 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4962 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4963 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4964 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4967 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4969 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4970 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4972 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4973 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4974 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4976 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4977 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4978 DataArrayInt *conn1D=0,*conn1DI=0;
4979 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4980 DataArrayDouble *coordsTmp=0;
4981 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4982 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4983 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4984 const int *c1DPtr=conn1D->begin();
4985 const int *c1DIPtr=conn1DI->begin();
4986 int nbOfCells=getNumberOfCells();
4987 const int *cPtr=_nodal_connec->getConstPointer();
4988 const int *icPtr=_nodal_connec_index->getConstPointer();
4989 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4990 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4992 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4993 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4994 if(!cm.isQuadratic())
4996 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
4997 types.insert(typ2); newConn->pushBackSilent(typ2);
4998 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4999 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5000 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5001 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5002 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5003 newConnI->pushBackSilent(lastVal);
5004 ret->pushBackSilent(i);
5009 lastVal+=(icPtr[1]-icPtr[0]);
5010 newConnI->pushBackSilent(lastVal);
5011 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5014 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5015 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5020 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5021 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5022 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5024 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5026 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5027 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5028 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5031 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5033 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5034 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5035 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5036 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5038 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5039 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5040 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5042 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5043 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5044 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5045 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5046 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5047 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5048 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5049 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5050 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5051 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5052 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5053 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5054 int nbOfCells=getNumberOfCells();
5055 const int *cPtr=_nodal_connec->getConstPointer();
5056 const int *icPtr=_nodal_connec_index->getConstPointer();
5057 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5058 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5060 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5061 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5062 if(!cm.isQuadratic())
5064 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5065 if(typ2==INTERP_KERNEL::NORM_ERROR)
5067 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5068 throw INTERP_KERNEL::Exception(oss.str().c_str());
5070 types.insert(typ2); newConn->pushBackSilent(typ2);
5071 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5072 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5073 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5074 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5076 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5077 int tmpPos=newConn->getNumberOfTuples();
5078 newConn->pushBackSilent(nodeId2);
5079 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5081 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5082 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5083 newConnI->pushBackSilent(lastVal);
5084 ret->pushBackSilent(i);
5089 lastVal+=(icPtr[1]-icPtr[0]);
5090 newConnI->pushBackSilent(lastVal);
5091 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5094 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5095 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5096 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5097 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5098 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5099 int *c=newConn->getPointer();
5100 const int *cI(newConnI->begin());
5101 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5102 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5103 offset=coordsTmp2Safe->getNumberOfTuples();
5104 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5105 c[cI[(*elt)+1]-1]+=offset;
5106 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5111 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5112 * so that the number of cells remains the same. Quadratic faces are converted to
5113 * polygons. This method works only for 2D meshes in
5114 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5115 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5116 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5117 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5118 * a polylinized edge constituting the input polygon.
5119 * \throw If the coordinates array is not set.
5120 * \throw If the nodal connectivity of cells is not defined.
5121 * \throw If \a this->getMeshDimension() != 2.
5122 * \throw If \a this->getSpaceDimension() != 2.
5124 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5126 checkFullyDefined();
5127 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5128 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5129 double epsa=fabs(eps);
5130 if(epsa<std::numeric_limits<double>::min())
5131 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 !");
5132 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5133 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5134 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5135 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5136 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5137 revDesc1=0; revDescIndx1=0;
5138 mDesc->tessellate2DCurve(eps);
5139 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5140 setCoords(mDesc->getCoords());
5144 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5145 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5146 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5147 * a sub-divided edge.
5148 * \throw If the coordinates array is not set.
5149 * \throw If the nodal connectivity of cells is not defined.
5150 * \throw If \a this->getMeshDimension() != 1.
5151 * \throw If \a this->getSpaceDimension() != 2.
5153 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5155 checkFullyDefined();
5156 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5157 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5158 double epsa=fabs(eps);
5159 if(epsa<std::numeric_limits<double>::min())
5160 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 !");
5161 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5162 int nbCells=getNumberOfCells();
5163 int nbNodes=getNumberOfNodes();
5164 const int *conn=_nodal_connec->getConstPointer();
5165 const int *connI=_nodal_connec_index->getConstPointer();
5166 const double *coords=_coords->getConstPointer();
5167 std::vector<double> addCoo;
5168 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5169 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5170 newConnI->alloc(nbCells+1,1);
5171 int *newConnIPtr=newConnI->getPointer();
5174 INTERP_KERNEL::Node *tmp2[3];
5175 std::set<INTERP_KERNEL::NormalizedCellType> types;
5176 for(int i=0;i<nbCells;i++,newConnIPtr++)
5178 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5179 if(cm.isQuadratic())
5180 {//assert(connI[i+1]-connI[i]-1==3)
5181 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5182 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5183 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5184 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5185 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5188 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5189 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5191 newConnIPtr[1]=(int)newConn.size();
5195 types.insert(INTERP_KERNEL::NORM_SEG2);
5196 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5197 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5198 newConnIPtr[1]=newConnIPtr[0]+3;
5203 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5204 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5205 newConnIPtr[1]=newConnIPtr[0]+3;
5208 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5211 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5212 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5213 newConnArr->alloc((int)newConn.size(),1);
5214 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5215 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5216 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5217 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5218 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5219 std::copy(addCoo.begin(),addCoo.end(),work);
5220 DataArrayDouble::SetArrayIn(newCoords,_coords);
5225 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5226 * In addition, returns an array mapping new cells to old ones. <br>
5227 * This method typically increases the number of cells in \a this mesh
5228 * but the number of nodes remains \b unchanged.
5229 * That's why the 3D splitting policies
5230 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5231 * \param [in] policy - specifies a pattern used for splitting.
5232 * The semantic of \a policy is:
5233 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5234 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5235 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5236 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5237 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5238 * an id of old cell producing it. The caller is to delete this array using
5239 * decrRef() as it is no more needed.
5240 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5241 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5242 * and \a this->getMeshDimension() != 3.
5243 * \throw If \a policy is not one of the four discussed above.
5244 * \throw If the nodal connectivity of cells is not defined.
5246 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5251 return simplexizePol0();
5253 return simplexizePol1();
5254 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5255 return simplexizePlanarFace5();
5256 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5257 return simplexizePlanarFace6();
5259 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)");
5264 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5265 * - 1D: INTERP_KERNEL::NORM_SEG2
5266 * - 2D: INTERP_KERNEL::NORM_TRI3
5267 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5269 * This method is useful for users that need to use P1 field services as
5270 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5271 * All these methods need mesh support containing only simplex cells.
5272 * \return bool - \c true if there are only simplex cells in \a this mesh.
5273 * \throw If the coordinates array is not set.
5274 * \throw If the nodal connectivity of cells is not defined.
5275 * \throw If \a this->getMeshDimension() < 1.
5277 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5279 checkFullyDefined();
5280 int mdim=getMeshDimension();
5281 if(mdim<1 || mdim>3)
5282 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5283 int nbCells=getNumberOfCells();
5284 const int *conn=_nodal_connec->getConstPointer();
5285 const int *connI=_nodal_connec_index->getConstPointer();
5286 for(int i=0;i<nbCells;i++)
5288 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5296 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5298 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5300 checkConnectivityFullyDefined();
5301 if(getMeshDimension()!=2)
5302 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5303 int nbOfCells=getNumberOfCells();
5304 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5305 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5306 ret->alloc(nbOfCells+nbOfCutCells,1);
5307 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5308 int *retPt=ret->getPointer();
5309 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5310 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5311 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5312 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5313 int *pt=newConn->getPointer();
5314 int *ptI=newConnI->getPointer();
5316 const int *oldc=_nodal_connec->getConstPointer();
5317 const int *ci=_nodal_connec_index->getConstPointer();
5318 for(int i=0;i<nbOfCells;i++,ci++)
5320 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5322 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5323 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5324 pt=std::copy(tmp,tmp+8,pt);
5333 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5334 ptI[1]=ptI[0]+ci[1]-ci[0];
5339 _nodal_connec->decrRef();
5340 _nodal_connec=newConn.retn();
5341 _nodal_connec_index->decrRef();
5342 _nodal_connec_index=newConnI.retn();
5349 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5351 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5353 checkConnectivityFullyDefined();
5354 if(getMeshDimension()!=2)
5355 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5356 int nbOfCells=getNumberOfCells();
5357 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5358 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5359 ret->alloc(nbOfCells+nbOfCutCells,1);
5360 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5361 int *retPt=ret->getPointer();
5362 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5363 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5364 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5365 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5366 int *pt=newConn->getPointer();
5367 int *ptI=newConnI->getPointer();
5369 const int *oldc=_nodal_connec->getConstPointer();
5370 const int *ci=_nodal_connec_index->getConstPointer();
5371 for(int i=0;i<nbOfCells;i++,ci++)
5373 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5375 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5376 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5377 pt=std::copy(tmp,tmp+8,pt);
5386 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5387 ptI[1]=ptI[0]+ci[1]-ci[0];
5392 _nodal_connec->decrRef();
5393 _nodal_connec=newConn.retn();
5394 _nodal_connec_index->decrRef();
5395 _nodal_connec_index=newConnI.retn();
5402 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5404 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5406 checkConnectivityFullyDefined();
5407 if(getMeshDimension()!=3)
5408 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5409 int nbOfCells=getNumberOfCells();
5410 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5411 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5412 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5413 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5414 int *retPt=ret->getPointer();
5415 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5416 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5417 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5418 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5419 int *pt=newConn->getPointer();
5420 int *ptI=newConnI->getPointer();
5422 const int *oldc=_nodal_connec->getConstPointer();
5423 const int *ci=_nodal_connec_index->getConstPointer();
5424 for(int i=0;i<nbOfCells;i++,ci++)
5426 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5428 for(int j=0;j<5;j++,pt+=5,ptI++)
5430 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5431 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];
5438 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5439 ptI[1]=ptI[0]+ci[1]-ci[0];
5444 _nodal_connec->decrRef();
5445 _nodal_connec=newConn.retn();
5446 _nodal_connec_index->decrRef();
5447 _nodal_connec_index=newConnI.retn();
5454 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5456 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5458 checkConnectivityFullyDefined();
5459 if(getMeshDimension()!=3)
5460 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5461 int nbOfCells=getNumberOfCells();
5462 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5463 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5464 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5465 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5466 int *retPt=ret->getPointer();
5467 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5468 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5469 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5470 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5471 int *pt=newConn->getPointer();
5472 int *ptI=newConnI->getPointer();
5474 const int *oldc=_nodal_connec->getConstPointer();
5475 const int *ci=_nodal_connec_index->getConstPointer();
5476 for(int i=0;i<nbOfCells;i++,ci++)
5478 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5480 for(int j=0;j<6;j++,pt+=5,ptI++)
5482 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5483 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];
5490 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5491 ptI[1]=ptI[0]+ci[1]-ci[0];
5496 _nodal_connec->decrRef();
5497 _nodal_connec=newConn.retn();
5498 _nodal_connec_index->decrRef();
5499 _nodal_connec_index=newConnI.retn();
5506 * 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.
5507 * This method completly ignore coordinates.
5508 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5509 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5510 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5511 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5513 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5515 checkFullyDefined();
5516 if(getMeshDimension()!=2)
5517 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5518 int nbOfCells=getNumberOfCells();
5519 int *connI=_nodal_connec_index->getPointer();
5521 for(int i=0;i<nbOfCells;i++,connI++)
5523 int offset=descIndex[i];
5524 int nbOfEdges=descIndex[i+1]-offset;
5526 bool ddirect=desc[offset+nbOfEdges-1]>0;
5527 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5528 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5529 for(int j=0;j<nbOfEdges;j++)
5531 bool direct=desc[offset+j]>0;
5532 int edgeId=std::abs(desc[offset+j])-1;
5533 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5535 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5536 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5537 int ref2=direct?id1:id2;
5540 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5541 newConnLgth+=nbOfSubNodes-1;
5546 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5547 throw INTERP_KERNEL::Exception(oss.str().c_str());
5552 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5555 newConnLgth++;//+1 is for cell type
5556 connI[1]=newConnLgth;
5559 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5560 newConn->alloc(newConnLgth,1);
5561 int *work=newConn->getPointer();
5562 for(int i=0;i<nbOfCells;i++)
5564 *work++=INTERP_KERNEL::NORM_POLYGON;
5565 int offset=descIndex[i];
5566 int nbOfEdges=descIndex[i+1]-offset;
5567 for(int j=0;j<nbOfEdges;j++)
5569 bool direct=desc[offset+j]>0;
5570 int edgeId=std::abs(desc[offset+j])-1;
5572 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5575 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5576 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5577 work=std::copy(it,it+nbOfSubNodes-1,work);
5581 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5584 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5588 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5589 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5590 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5591 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5592 * so it can be useful to call mergeNodes() before calling this method.
5593 * \throw If \a this->getMeshDimension() <= 1.
5594 * \throw If the coordinates array is not set.
5595 * \throw If the nodal connectivity of cells is not defined.
5597 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5599 checkFullyDefined();
5600 if(getMeshDimension()<=1)
5601 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5602 int nbOfCells=getNumberOfCells();
5605 int initMeshLgth=getMeshLength();
5606 int *conn=_nodal_connec->getPointer();
5607 int *index=_nodal_connec_index->getPointer();
5611 for(int i=0;i<nbOfCells;i++)
5613 lgthOfCurCell=index[i+1]-posOfCurCell;
5614 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5616 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5617 conn+newPos+1,newLgth);
5618 conn[newPos]=newType;
5620 posOfCurCell=index[i+1];
5623 if(newPos!=initMeshLgth)
5624 _nodal_connec->reAlloc(newPos);
5629 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5630 * A cell is considered to be oriented correctly if an angle between its
5631 * normal vector and a given vector is less than \c PI / \c 2.
5632 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5634 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5636 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5637 * is not cleared before filling in.
5638 * \throw If \a this->getMeshDimension() != 2.
5639 * \throw If \a this->getSpaceDimension() != 3.
5641 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5642 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5644 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5646 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5647 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5648 int nbOfCells=getNumberOfCells();
5649 const int *conn=_nodal_connec->getConstPointer();
5650 const int *connI=_nodal_connec_index->getConstPointer();
5651 const double *coordsPtr=_coords->getConstPointer();
5652 for(int i=0;i<nbOfCells;i++)
5654 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5655 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5657 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5658 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5665 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5666 * considered to be oriented correctly if an angle between its normal vector and a
5667 * given vector is less than \c PI / \c 2.
5668 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5670 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5672 * \throw If \a this->getMeshDimension() != 2.
5673 * \throw If \a this->getSpaceDimension() != 3.
5675 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5676 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5678 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5680 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5681 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5682 int nbOfCells=getNumberOfCells();
5683 int *conn=_nodal_connec->getPointer();
5684 const int *connI=_nodal_connec_index->getConstPointer();
5685 const double *coordsPtr=_coords->getConstPointer();
5686 bool isModified=false;
5687 for(int i=0;i<nbOfCells;i++)
5689 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5690 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5692 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5693 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5696 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5697 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5698 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5703 _nodal_connec->declareAsNew();
5708 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5709 * oriented facets. The normal vector of the facet should point out of the cell.
5710 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5711 * is not cleared before filling in.
5712 * \throw If \a this->getMeshDimension() != 3.
5713 * \throw If \a this->getSpaceDimension() != 3.
5714 * \throw If the coordinates array is not set.
5715 * \throw If the nodal connectivity of cells is not defined.
5717 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5718 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5720 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5722 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5723 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5724 int nbOfCells=getNumberOfCells();
5725 const int *conn=_nodal_connec->getConstPointer();
5726 const int *connI=_nodal_connec_index->getConstPointer();
5727 const double *coordsPtr=_coords->getConstPointer();
5728 for(int i=0;i<nbOfCells;i++)
5730 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5731 if(type==INTERP_KERNEL::NORM_POLYHED)
5733 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5740 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5742 * \throw If \a this->getMeshDimension() != 3.
5743 * \throw If \a this->getSpaceDimension() != 3.
5744 * \throw If the coordinates array is not set.
5745 * \throw If the nodal connectivity of cells is not defined.
5746 * \throw If the reparation fails.
5748 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5749 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5750 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5752 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5754 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5755 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5756 int nbOfCells=getNumberOfCells();
5757 int *conn=_nodal_connec->getPointer();
5758 const int *connI=_nodal_connec_index->getConstPointer();
5759 const double *coordsPtr=_coords->getConstPointer();
5760 for(int i=0;i<nbOfCells;i++)
5762 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5763 if(type==INTERP_KERNEL::NORM_POLYHED)
5767 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5768 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5770 catch(INTERP_KERNEL::Exception& e)
5772 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5773 throw INTERP_KERNEL::Exception(oss.str().c_str());
5781 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5782 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5783 * according to which the first facet of the cell should be oriented to have the normal vector
5784 * pointing out of cell.
5785 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5786 * cells. The caller is to delete this array using decrRef() as it is no more
5788 * \throw If \a this->getMeshDimension() != 3.
5789 * \throw If \a this->getSpaceDimension() != 3.
5790 * \throw If the coordinates array is not set.
5791 * \throw If the nodal connectivity of cells is not defined.
5793 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5794 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5795 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5797 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5799 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5800 if(getMeshDimension()!=3)
5801 throw INTERP_KERNEL::Exception(msg);
5802 int spaceDim=getSpaceDimension();
5804 throw INTERP_KERNEL::Exception(msg);
5806 int nbOfCells=getNumberOfCells();
5807 int *conn=_nodal_connec->getPointer();
5808 const int *connI=_nodal_connec_index->getConstPointer();
5809 const double *coo=getCoords()->getConstPointer();
5810 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5811 for(int i=0;i<nbOfCells;i++)
5813 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5814 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5816 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5818 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5819 cells->pushBackSilent(i);
5823 return cells.retn();
5827 * This method is a faster method to correct orientation of all 3D cells in \a this.
5828 * 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.
5829 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5831 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5832 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
5834 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5836 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5837 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5838 int nbOfCells=getNumberOfCells();
5839 int *conn=_nodal_connec->getPointer();
5840 const int *connI=_nodal_connec_index->getConstPointer();
5841 const double *coordsPtr=_coords->getConstPointer();
5842 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5843 for(int i=0;i<nbOfCells;i++)
5845 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5848 case INTERP_KERNEL::NORM_TETRA4:
5850 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5852 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5853 ret->pushBackSilent(i);
5857 case INTERP_KERNEL::NORM_PYRA5:
5859 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5861 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5862 ret->pushBackSilent(i);
5866 case INTERP_KERNEL::NORM_PENTA6:
5867 case INTERP_KERNEL::NORM_HEXA8:
5868 case INTERP_KERNEL::NORM_HEXGP12:
5870 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5872 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5873 ret->pushBackSilent(i);
5877 case INTERP_KERNEL::NORM_POLYHED:
5879 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5881 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5882 ret->pushBackSilent(i);
5887 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 !");
5895 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5896 * If it is not the case an exception will be thrown.
5897 * This method is fast because the first cell of \a this is used to compute the plane.
5898 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5899 * \param pos output of size at least 3 used to store a point owned of searched plane.
5901 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5903 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5904 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5905 const int *conn=_nodal_connec->getConstPointer();
5906 const int *connI=_nodal_connec_index->getConstPointer();
5907 const double *coordsPtr=_coords->getConstPointer();
5908 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5909 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5913 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5914 * cells. Currently cells of the following types are treated:
5915 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5916 * For a cell of other type an exception is thrown.
5917 * Space dimension of a 2D mesh can be either 2 or 3.
5918 * The Edge Ratio of a cell \f$t\f$ is:
5919 * \f$\frac{|t|_\infty}{|t|_0}\f$,
5920 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5921 * the smallest edge lengths of \f$t\f$.
5922 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5923 * cells and one time, lying on \a this mesh. The caller is to delete this
5924 * field using decrRef() as it is no more needed.
5925 * \throw If the coordinates array is not set.
5926 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5927 * \throw If the connectivity data array has more than one component.
5928 * \throw If the connectivity data array has a named component.
5929 * \throw If the connectivity index data array has more than one component.
5930 * \throw If the connectivity index data array has a named component.
5931 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
5932 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5933 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
5935 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5938 int spaceDim=getSpaceDimension();
5939 int meshDim=getMeshDimension();
5940 if(spaceDim!=2 && spaceDim!=3)
5941 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5942 if(meshDim!=2 && meshDim!=3)
5943 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5944 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5946 int nbOfCells=getNumberOfCells();
5947 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5948 arr->alloc(nbOfCells,1);
5949 double *pt=arr->getPointer();
5950 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5951 const int *conn=_nodal_connec->getConstPointer();
5952 const int *connI=_nodal_connec_index->getConstPointer();
5953 const double *coo=_coords->getConstPointer();
5955 for(int i=0;i<nbOfCells;i++,pt++)
5957 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5960 case INTERP_KERNEL::NORM_TRI3:
5962 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5963 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5966 case INTERP_KERNEL::NORM_QUAD4:
5968 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5969 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5972 case INTERP_KERNEL::NORM_TETRA4:
5974 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5975 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5979 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5981 conn+=connI[i+1]-connI[i];
5983 ret->setName("EdgeRatio");
5984 ret->synchronizeTimeWithSupport();
5989 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5990 * cells. Currently cells of the following types are treated:
5991 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5992 * For a cell of other type an exception is thrown.
5993 * Space dimension of a 2D mesh can be either 2 or 3.
5994 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5995 * cells and one time, lying on \a this mesh. The caller is to delete this
5996 * field using decrRef() as it is no more needed.
5997 * \throw If the coordinates array is not set.
5998 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5999 * \throw If the connectivity data array has more than one component.
6000 * \throw If the connectivity data array has a named component.
6001 * \throw If the connectivity index data array has more than one component.
6002 * \throw If the connectivity index data array has a named component.
6003 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6004 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6005 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6007 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6010 int spaceDim=getSpaceDimension();
6011 int meshDim=getMeshDimension();
6012 if(spaceDim!=2 && spaceDim!=3)
6013 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6014 if(meshDim!=2 && meshDim!=3)
6015 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6016 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6018 int nbOfCells=getNumberOfCells();
6019 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6020 arr->alloc(nbOfCells,1);
6021 double *pt=arr->getPointer();
6022 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6023 const int *conn=_nodal_connec->getConstPointer();
6024 const int *connI=_nodal_connec_index->getConstPointer();
6025 const double *coo=_coords->getConstPointer();
6027 for(int i=0;i<nbOfCells;i++,pt++)
6029 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6032 case INTERP_KERNEL::NORM_TRI3:
6034 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6035 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6038 case INTERP_KERNEL::NORM_QUAD4:
6040 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6041 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6044 case INTERP_KERNEL::NORM_TETRA4:
6046 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6047 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6051 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6053 conn+=connI[i+1]-connI[i];
6055 ret->setName("AspectRatio");
6056 ret->synchronizeTimeWithSupport();
6061 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6062 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6063 * treated: INTERP_KERNEL::NORM_QUAD4.
6064 * For a cell of other type an exception is thrown.
6065 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6066 * cells and one time, lying on \a this mesh. The caller is to delete this
6067 * field using decrRef() as it is no more needed.
6068 * \throw If the coordinates array is not set.
6069 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6070 * \throw If the connectivity data array has more than one component.
6071 * \throw If the connectivity data array has a named component.
6072 * \throw If the connectivity index data array has more than one component.
6073 * \throw If the connectivity index data array has a named component.
6074 * \throw If \a this->getMeshDimension() != 2.
6075 * \throw If \a this->getSpaceDimension() != 3.
6076 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6078 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6081 int spaceDim=getSpaceDimension();
6082 int meshDim=getMeshDimension();
6084 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6086 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6087 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6089 int nbOfCells=getNumberOfCells();
6090 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6091 arr->alloc(nbOfCells,1);
6092 double *pt=arr->getPointer();
6093 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6094 const int *conn=_nodal_connec->getConstPointer();
6095 const int *connI=_nodal_connec_index->getConstPointer();
6096 const double *coo=_coords->getConstPointer();
6098 for(int i=0;i<nbOfCells;i++,pt++)
6100 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6103 case INTERP_KERNEL::NORM_QUAD4:
6105 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6106 *pt=INTERP_KERNEL::quadWarp(tmp);
6110 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6112 conn+=connI[i+1]-connI[i];
6114 ret->setName("Warp");
6115 ret->synchronizeTimeWithSupport();
6121 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6122 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6123 * treated: INTERP_KERNEL::NORM_QUAD4.
6124 * For a cell of other type an exception is thrown.
6125 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6126 * cells and one time, lying on \a this mesh. The caller is to delete this
6127 * field using decrRef() as it is no more needed.
6128 * \throw If the coordinates array is not set.
6129 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6130 * \throw If the connectivity data array has more than one component.
6131 * \throw If the connectivity data array has a named component.
6132 * \throw If the connectivity index data array has more than one component.
6133 * \throw If the connectivity index data array has a named component.
6134 * \throw If \a this->getMeshDimension() != 2.
6135 * \throw If \a this->getSpaceDimension() != 3.
6136 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6138 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6141 int spaceDim=getSpaceDimension();
6142 int meshDim=getMeshDimension();
6144 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6146 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6147 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6149 int nbOfCells=getNumberOfCells();
6150 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6151 arr->alloc(nbOfCells,1);
6152 double *pt=arr->getPointer();
6153 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6154 const int *conn=_nodal_connec->getConstPointer();
6155 const int *connI=_nodal_connec_index->getConstPointer();
6156 const double *coo=_coords->getConstPointer();
6158 for(int i=0;i<nbOfCells;i++,pt++)
6160 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6163 case INTERP_KERNEL::NORM_QUAD4:
6165 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6166 *pt=INTERP_KERNEL::quadSkew(tmp);
6170 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6172 conn+=connI[i+1]-connI[i];
6174 ret->setName("Skew");
6175 ret->synchronizeTimeWithSupport();
6180 * This method aggregate the bbox of each cell and put it into bbox parameter.
6181 * \param bbox out parameter of size 2*spacedim*nbOfcells.
6183 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6185 int spaceDim=getSpaceDimension();
6186 int nbOfCells=getNumberOfCells();
6187 bbox.resize(2*nbOfCells*spaceDim);
6188 for(int i=0;i<nbOfCells*spaceDim;i++)
6190 bbox[2*i]=std::numeric_limits<double>::max();
6191 bbox[2*i+1]=-std::numeric_limits<double>::max();
6193 const double *coordsPtr=_coords->getConstPointer();
6194 const int *conn=_nodal_connec->getConstPointer();
6195 const int *connI=_nodal_connec_index->getConstPointer();
6196 for(int i=0;i<nbOfCells;i++)
6198 int offset=connI[i]+1;
6199 int nbOfNodesForCell=connI[i+1]-offset;
6200 for(int j=0;j<nbOfNodesForCell;j++)
6202 int nodeId=conn[offset+j];
6204 for(int k=0;k<spaceDim;k++)
6206 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6207 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6215 namespace ParaMEDMEMImpl
6220 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6221 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6230 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6231 bool operator() (const int& pos) { return _conn[pos]==_val; }
6241 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6242 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6243 * \a this is composed in cell types.
6244 * The returned array is of size 3*n where n is the number of different types present in \a this.
6245 * For every k in [0,n] ret[3*k+2]==0 because it has no sense here.
6246 * This parameter is kept only for compatibility with other methode listed above.
6248 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6250 checkConnectivityFullyDefined();
6251 const int *conn=_nodal_connec->getConstPointer();
6252 const int *connI=_nodal_connec_index->getConstPointer();
6253 const int *work=connI;
6254 int nbOfCells=getNumberOfCells();
6255 std::size_t n=getAllTypes().size();
6256 std::vector<int> ret(3*n,0); //ret[3*k+2]==0 because it has no sense here
6257 std::set<INTERP_KERNEL::NormalizedCellType> types;
6258 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6260 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6261 if(types.find(typ)!=types.end())
6263 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6264 oss << " is not contiguous !";
6265 throw INTERP_KERNEL::Exception(oss.str().c_str());
6269 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6270 ret[3*i+1]=(int)std::distance(work,work2);
6277 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6278 * only for types cell, type node is not managed.
6279 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6280 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6281 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6282 * If 2 or more same geometric type is in \a code and exception is thrown too.
6284 * This method firstly checks
6285 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6286 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6287 * an exception is thrown too.
6289 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6290 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6291 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6293 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6296 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6297 std::size_t sz=code.size();
6300 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6301 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6303 for(std::size_t i=0;i<n;i++)
6304 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6306 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6308 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6309 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6312 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6313 if(idsPerType.empty())
6315 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6316 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6317 if(types.size()==_types.size())
6320 DataArrayInt *ret=DataArrayInt::New();
6322 int *retPtr=ret->getPointer();
6323 const int *connI=_nodal_connec_index->getConstPointer();
6324 const int *conn=_nodal_connec->getConstPointer();
6325 int nbOfCells=getNumberOfCells();
6328 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6330 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6331 int offset=(int)std::distance(connI,i);
6332 if(code[3*kk+2]==-1)
6334 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6335 std::size_t pos2=std::distance(i,j);
6336 for(std::size_t k=0;k<pos2;k++)
6337 *retPtr++=(int)k+offset;
6342 retPtr=std::transform(idsPerType[code[3*kk+2]]->getConstPointer(),idsPerType[code[3*kk+2]]->getConstPointer()+idsPerType[code[3*kk+2]]->getNbOfElems(),
6343 retPtr,std::bind2nd(std::plus<int>(),offset));
6350 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6351 * 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.
6352 * 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.
6353 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6355 * \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.
6356 * \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,
6357 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6358 * \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.
6359 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6360 * \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
6362 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6365 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6366 if(profile->getNumberOfComponents()!=1)
6367 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6368 checkConnectivityFullyDefined();
6369 const int *conn=_nodal_connec->getConstPointer();
6370 const int *connI=_nodal_connec_index->getConstPointer();
6371 int nbOfCells=getNumberOfCells();
6372 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6373 std::vector<int> typeRangeVals(1);
6374 for(const int *i=connI;i!=connI+nbOfCells;)
6376 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6377 if(std::find(types.begin(),types.end(),curType)!=types.end())
6379 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6381 types.push_back(curType);
6382 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6383 typeRangeVals.push_back((int)std::distance(connI,i));
6386 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6387 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6389 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6390 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6392 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6393 code.resize(3*nbOfCastsFinal);
6394 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6395 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6396 for(int i=0;i<nbOfCastsFinal;i++)
6398 int castId=castsPresent->getIJ(i,0);
6399 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6400 idsInPflPerType2.push_back(tmp3);
6401 code[3*i]=(int)types[castId];
6402 code[3*i+1]=tmp3->getNumberOfTuples();
6403 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6404 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6406 tmp4->copyStringInfoFrom(*profile);
6407 idsPerType2.push_back(tmp4);
6408 code[3*i+2]=(int)idsPerType2.size()-1;
6415 std::size_t sz2=idsInPflPerType2.size();
6416 idsInPflPerType.resize(sz2);
6417 for(std::size_t i=0;i<sz2;i++)
6419 DataArrayInt *locDa=idsInPflPerType2[i];
6421 idsInPflPerType[i]=locDa;
6423 std::size_t sz=idsPerType2.size();
6424 idsPerType.resize(sz);
6425 for(std::size_t i=0;i<sz;i++)
6427 DataArrayInt *locDa=idsPerType2[i];
6429 idsPerType[i]=locDa;
6434 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6435 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6436 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6437 * 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.
6439 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6441 checkFullyDefined();
6442 nM1LevMesh->checkFullyDefined();
6443 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6444 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6445 if(_coords!=nM1LevMesh->getCoords())
6446 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6447 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6448 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6449 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6450 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6451 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6452 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6453 tmp->setConnectivity(tmp0,tmp1);
6454 tmp->renumberCells(ret0->getConstPointer(),false);
6455 revDesc=tmp->getNodalConnectivity();
6456 revDescIndx=tmp->getNodalConnectivityIndex();
6457 DataArrayInt *ret=0;
6458 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6461 ret->getMaxValue(tmp2);
6463 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6464 throw INTERP_KERNEL::Exception(oss.str().c_str());
6469 revDescIndx->incrRef();
6472 meshnM1Old2New=ret0;
6477 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6478 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6479 * in "Old to New" mode.
6480 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6481 * this array using decrRef() as it is no more needed.
6482 * \throw If the nodal connectivity of cells is not defined.
6484 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6486 checkConnectivityFullyDefined();
6487 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6488 renumberCells(ret->getConstPointer(),false);
6493 * This methods checks that cells are sorted by their types.
6494 * This method makes asumption (no check) that connectivity is correctly set before calling.
6496 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6498 checkFullyDefined();
6499 const int *conn=_nodal_connec->getConstPointer();
6500 const int *connI=_nodal_connec_index->getConstPointer();
6501 int nbOfCells=getNumberOfCells();
6502 std::set<INTERP_KERNEL::NormalizedCellType> types;
6503 for(const int *i=connI;i!=connI+nbOfCells;)
6505 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6506 if(types.find(curType)!=types.end())
6508 types.insert(curType);
6509 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6515 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6516 * The geometric type order is specified by MED file.
6518 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6520 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6522 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6526 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6527 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6528 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6529 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6531 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6533 checkFullyDefined();
6534 const int *conn=_nodal_connec->getConstPointer();
6535 const int *connI=_nodal_connec_index->getConstPointer();
6536 int nbOfCells=getNumberOfCells();
6540 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6541 for(const int *i=connI;i!=connI+nbOfCells;)
6543 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6544 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6545 if(isTypeExists!=orderEnd)
6547 int pos=(int)std::distance(orderBg,isTypeExists);
6551 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6555 if(sg.find(curType)==sg.end())
6557 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6568 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6569 * 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
6570 * 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'.
6572 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6574 checkConnectivityFullyDefined();
6575 int nbOfCells=getNumberOfCells();
6576 const int *conn=_nodal_connec->getConstPointer();
6577 const int *connI=_nodal_connec_index->getConstPointer();
6578 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6579 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6580 tmpa->alloc(nbOfCells,1);
6581 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6582 tmpb->fillWithZero();
6583 int *tmp=tmpa->getPointer();
6584 int *tmp2=tmpb->getPointer();
6585 for(const int *i=connI;i!=connI+nbOfCells;i++)
6587 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6590 int pos=(int)std::distance(orderBg,where);
6592 tmp[std::distance(connI,i)]=pos;
6596 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6597 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6598 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6599 throw INTERP_KERNEL::Exception(oss.str().c_str());
6602 nbPerType=tmpb.retn();
6607 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6609 * \return a new object containing the old to new correspondance.
6611 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6613 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6615 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6619 * 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.
6620 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6621 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6622 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6624 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6626 DataArrayInt *nbPerType=0;
6627 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6628 nbPerType->decrRef();
6629 return tmpa->buildPermArrPerLevel();
6633 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6634 * The number of cells remains unchanged after the call of this method.
6635 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6636 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6638 * \return the array giving the correspondance old to new.
6640 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6642 checkFullyDefined();
6644 const int *conn=_nodal_connec->getConstPointer();
6645 const int *connI=_nodal_connec_index->getConstPointer();
6646 int nbOfCells=getNumberOfCells();
6647 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6648 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6649 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6651 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6652 types.push_back(curType);
6653 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6655 DataArrayInt *ret=DataArrayInt::New();
6656 ret->alloc(nbOfCells,1);
6657 int *retPtr=ret->getPointer();
6658 std::fill(retPtr,retPtr+nbOfCells,-1);
6660 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6662 for(const int *i=connI;i!=connI+nbOfCells;i++)
6663 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6664 retPtr[std::distance(connI,i)]=newCellId++;
6666 renumberCells(retPtr,false);
6671 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6672 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6673 * This method makes asumption that connectivity is correctly set before calling.
6675 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6677 checkFullyDefined();
6678 const int *conn=_nodal_connec->getConstPointer();
6679 const int *connI=_nodal_connec_index->getConstPointer();
6680 int nbOfCells=getNumberOfCells();
6681 std::vector<MEDCouplingUMesh *> ret;
6682 for(const int *i=connI;i!=connI+nbOfCells;)
6684 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6685 int beginCellId=(int)std::distance(connI,i);
6686 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6687 int endCellId=(int)std::distance(connI,i);
6688 int sz=endCellId-beginCellId;
6689 int *cells=new int[sz];
6690 for(int j=0;j<sz;j++)
6691 cells[j]=beginCellId+j;
6692 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6700 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6701 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6702 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6704 * \return a newly allocated instance, that the caller must manage.
6705 * \throw If \a this contains more than one geometric type.
6706 * \throw If the nodal connectivity of \a this is not fully defined.
6707 * \throw If the internal data is not coherent.
6709 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6711 checkConnectivityFullyDefined();
6712 if(_types.size()!=1)
6713 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6714 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6716 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6717 ret->setCoords(getCoords());
6718 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6721 int nbCells=getNumberOfCells();
6722 int nbNodesPerCell=retC->getNumberOfNodesPerCell();
6723 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6724 int *outPtr=connOut->getPointer();
6725 const int *conn=_nodal_connec->begin();
6726 const int *connI=_nodal_connec_index->begin();
6728 for(int i=0;i<nbCells;i++,connI++)
6730 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6731 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6734 std::ostringstream oss; oss << "MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : there something wrong in cell #" << i << " ! The type of cell is not those expected, or the length of nodal connectivity is not those expected (" << nbNodesPerCell-1 << ") !";
6735 throw INTERP_KERNEL::Exception(oss.str().c_str());
6738 retC->setNodalConnectivity(connOut);
6741 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : not implemented yet for non static geometric type !");
6746 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6747 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6748 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6749 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6750 * are not used here to avoid the build of big permutation array.
6752 * \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
6753 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6754 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6755 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6756 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6757 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
6758 * \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
6759 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6761 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6762 DataArrayInt *&szOfCellGrpOfSameType,
6763 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6765 std::vector<const MEDCouplingUMesh *> ms2;
6766 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6769 (*it)->checkConnectivityFullyDefined();
6773 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6774 const DataArrayDouble *refCoo=ms2[0]->getCoords();
6775 int meshDim=ms2[0]->getMeshDimension();
6776 std::vector<const MEDCouplingUMesh *> m1ssm;
6777 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6779 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6780 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6782 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6783 ret1->alloc(0,1); ret2->alloc(0,1);
6784 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6786 if(meshDim!=(*it)->getMeshDimension())
6787 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6788 if(refCoo!=(*it)->getCoords())
6789 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6790 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6791 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6792 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6793 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6795 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6796 m1ssmSingleAuto.push_back(singleCell);
6797 m1ssmSingle.push_back(singleCell);
6798 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6801 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6802 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6803 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6804 for(std::size_t i=0;i<m1ssm.size();i++)
6805 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6806 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6807 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6808 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6813 * This method returns a newly created DataArrayInt instance.
6814 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6816 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6818 checkFullyDefined();
6819 const int *conn=_nodal_connec->getConstPointer();
6820 const int *connIndex=_nodal_connec_index->getConstPointer();
6821 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6822 for(const int *w=begin;w!=end;w++)
6823 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6824 ret->pushBackSilent(*w);
6829 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6830 * are in [0:getNumberOfCells())
6832 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6834 checkFullyDefined();
6835 const int *conn=_nodal_connec->getConstPointer();
6836 const int *connI=_nodal_connec_index->getConstPointer();
6837 int nbOfCells=getNumberOfCells();
6838 std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6839 int *tmp=new int[nbOfCells];
6840 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6843 for(const int *i=connI;i!=connI+nbOfCells;i++)
6844 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6845 tmp[std::distance(connI,i)]=j++;
6847 DataArrayInt *ret=DataArrayInt::New();
6848 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6849 ret->copyStringInfoFrom(*da);
6850 int *retPtr=ret->getPointer();
6851 const int *daPtr=da->getConstPointer();
6852 int nbOfElems=da->getNbOfElems();
6853 for(int k=0;k<nbOfElems;k++)
6854 retPtr[k]=tmp[daPtr[k]];
6860 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6861 * This method \b works \b for mesh sorted by type.
6862 * cells whose ids is in 'idsPerGeoType' array.
6863 * This method conserves coords and name of mesh.
6865 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6867 std::vector<int> code=getDistributionOfTypes();
6868 std::size_t nOfTypesInThis=code.size()/3;
6869 int sz=0,szOfType=0;
6870 for(std::size_t i=0;i<nOfTypesInThis;i++)
6875 szOfType=code[3*i+1];
6877 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6878 if(*work<0 || *work>=szOfType)
6880 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6881 oss << ". It should be in [0," << szOfType << ") !";
6882 throw INTERP_KERNEL::Exception(oss.str().c_str());
6884 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6885 int *idsPtr=idsTokeep->getPointer();
6887 for(std::size_t i=0;i<nOfTypesInThis;i++)
6890 for(int j=0;j<code[3*i+1];j++)
6893 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6894 offset+=code[3*i+1];
6896 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6897 ret->copyTinyInfoFrom(this);
6902 * This method returns a vector of size 'this->getNumberOfCells()'.
6903 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6905 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
6907 int ncell=getNumberOfCells();
6908 std::vector<bool> ret(ncell);
6909 const int *cI=getNodalConnectivityIndex()->getConstPointer();
6910 const int *c=getNodalConnectivity()->getConstPointer();
6911 for(int i=0;i<ncell;i++)
6913 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6914 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6915 ret[i]=cm.isQuadratic();
6921 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6923 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6925 if(other->getType()!=UNSTRUCTURED)
6926 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6927 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6928 return MergeUMeshes(this,otherC);
6932 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6933 * computed by averaging coordinates of cell nodes, so this method is not a right
6934 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
6935 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6936 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6937 * components. The caller is to delete this array using decrRef() as it is
6939 * \throw If the coordinates array is not set.
6940 * \throw If the nodal connectivity of cells is not defined.
6941 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6943 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
6945 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6946 int spaceDim=getSpaceDimension();
6947 int nbOfCells=getNumberOfCells();
6948 ret->alloc(nbOfCells,spaceDim);
6949 ret->copyStringInfoFrom(*getCoords());
6950 double *ptToFill=ret->getPointer();
6951 const int *nodal=_nodal_connec->getConstPointer();
6952 const int *nodalI=_nodal_connec_index->getConstPointer();
6953 const double *coor=_coords->getConstPointer();
6954 for(int i=0;i<nbOfCells;i++)
6956 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6957 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
6964 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
6965 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
6967 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
6968 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
6970 * \sa MEDCouplingUMesh::getBarycenterAndOwner
6971 * \throw If \a this is not fully defined (coordinates and connectivity)
6972 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
6974 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
6976 checkFullyDefined();
6977 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
6978 int spaceDim=getSpaceDimension();
6979 int nbOfCells=getNumberOfCells();
6980 int nbOfNodes=getNumberOfNodes();
6981 ret->alloc(nbOfCells,spaceDim);
6982 double *ptToFill=ret->getPointer();
6983 const int *nodal=_nodal_connec->getConstPointer();
6984 const int *nodalI=_nodal_connec_index->getConstPointer();
6985 const double *coor=_coords->getConstPointer();
6986 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
6988 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
6989 std::fill(ptToFill,ptToFill+spaceDim,0.);
6990 if(type!=INTERP_KERNEL::NORM_POLYHED)
6992 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
6994 if(*conn>=0 && *conn<nbOfNodes)
6995 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
6998 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
6999 throw INTERP_KERNEL::Exception(oss.str().c_str());
7002 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7003 if(nbOfNodesInCell>0)
7004 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7007 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7008 throw INTERP_KERNEL::Exception(oss.str().c_str());
7013 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7015 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7017 if(*it>=0 && *it<nbOfNodes)
7018 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7021 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7022 throw INTERP_KERNEL::Exception(oss.str().c_str());
7026 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7029 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7030 throw INTERP_KERNEL::Exception(oss.str().c_str());
7038 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7039 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7040 * are specified via an array of cell ids.
7041 * \warning Validity of the specified cell ids is not checked!
7042 * Valid range is [ 0, \a this->getNumberOfCells() ).
7043 * \param [in] begin - an array of cell ids of interest.
7044 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7045 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7046 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7047 * caller is to delete this array using decrRef() as it is no more needed.
7048 * \throw If the coordinates array is not set.
7049 * \throw If the nodal connectivity of cells is not defined.
7051 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7052 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7054 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7056 DataArrayDouble *ret=DataArrayDouble::New();
7057 int spaceDim=getSpaceDimension();
7058 int nbOfTuple=(int)std::distance(begin,end);
7059 ret->alloc(nbOfTuple,spaceDim);
7060 double *ptToFill=ret->getPointer();
7061 double *tmp=new double[spaceDim];
7062 const int *nodal=_nodal_connec->getConstPointer();
7063 const int *nodalI=_nodal_connec_index->getConstPointer();
7064 const double *coor=_coords->getConstPointer();
7065 for(const int *w=begin;w!=end;w++)
7067 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7068 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7076 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7079 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7082 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7083 da->checkAllocated();
7084 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7086 int nbOfTuples=da->getNumberOfTuples();
7087 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7088 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7089 c->alloc(2*nbOfTuples,1);
7090 cI->alloc(nbOfTuples+1,1);
7091 int *cp=c->getPointer();
7092 int *cip=cI->getPointer();
7094 for(int i=0;i<nbOfTuples;i++)
7096 *cp++=INTERP_KERNEL::NORM_POINT1;
7100 ret->setConnectivity(c,cI,true);
7104 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7105 * Cells and nodes of
7106 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7107 * \param [in] mesh1 - the first mesh.
7108 * \param [in] mesh2 - the second mesh.
7109 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7110 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7111 * is no more needed.
7112 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7113 * \throw If the coordinates array is not set in none of the meshes.
7114 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7115 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7117 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7119 std::vector<const MEDCouplingUMesh *> tmp(2);
7120 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7121 return MergeUMeshes(tmp);
7125 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7126 * Cells and nodes of
7127 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7128 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7129 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7130 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7131 * is no more needed.
7132 * \throw If \a a.size() == 0.
7133 * \throw If \a a[ *i* ] == NULL.
7134 * \throw If the coordinates array is not set in none of the meshes.
7135 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7136 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7138 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7140 std::size_t sz=a.size();
7142 return MergeUMeshesLL(a);
7143 for(std::size_t ii=0;ii<sz;ii++)
7146 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7147 throw INTERP_KERNEL::Exception(oss.str().c_str());
7149 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7150 std::vector< const MEDCouplingUMesh * > aa(sz);
7152 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7154 const MEDCouplingUMesh *cur=a[i];
7155 const DataArrayDouble *coo=cur->getCoords();
7157 spaceDim=coo->getNumberOfComponents();
7160 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7161 for(std::size_t i=0;i<sz;i++)
7163 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7166 return MergeUMeshesLL(aa);
7171 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7174 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7175 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7176 int meshDim=(*it)->getMeshDimension();
7177 int nbOfCells=(*it)->getNumberOfCells();
7178 int meshLgth=(*it++)->getMeshLength();
7179 for(;it!=a.end();it++)
7181 if(meshDim!=(*it)->getMeshDimension())
7182 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7183 nbOfCells+=(*it)->getNumberOfCells();
7184 meshLgth+=(*it)->getMeshLength();
7186 std::vector<const MEDCouplingPointSet *> aps(a.size());
7187 std::copy(a.begin(),a.end(),aps.begin());
7188 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7189 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7190 ret->setCoords(pts);
7191 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7192 c->alloc(meshLgth,1);
7193 int *cPtr=c->getPointer();
7194 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7195 cI->alloc(nbOfCells+1,1);
7196 int *cIPtr=cI->getPointer();
7200 for(it=a.begin();it!=a.end();it++)
7202 int curNbOfCell=(*it)->getNumberOfCells();
7203 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7204 const int *curC=(*it)->_nodal_connec->getConstPointer();
7205 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7206 for(int j=0;j<curNbOfCell;j++)
7208 const int *src=curC+curCI[j];
7210 for(;src!=curC+curCI[j+1];src++,cPtr++)
7218 offset+=curCI[curNbOfCell];
7219 offset2+=(*it)->getNumberOfNodes();
7222 ret->setConnectivity(c,cI,true);
7229 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7230 * dimension and sharing the node coordinates array.
7231 * All cells of the first mesh precede all cells of the second mesh
7232 * within the result mesh.
7233 * \param [in] mesh1 - the first mesh.
7234 * \param [in] mesh2 - the second mesh.
7235 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7236 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7237 * is no more needed.
7238 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7239 * \throw If the meshes do not share the node coordinates array.
7240 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7241 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7243 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7245 std::vector<const MEDCouplingUMesh *> tmp(2);
7246 tmp[0]=mesh1; tmp[1]=mesh2;
7247 return MergeUMeshesOnSameCoords(tmp);
7251 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7252 * dimension and sharing the node coordinates array.
7253 * All cells of the *i*-th mesh precede all cells of the
7254 * (*i*+1)-th mesh within the result mesh.
7255 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7256 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7257 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7258 * is no more needed.
7259 * \throw If \a a.size() == 0.
7260 * \throw If \a a[ *i* ] == NULL.
7261 * \throw If the meshes do not share the node coordinates array.
7262 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7263 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7265 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7268 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7269 for(std::size_t ii=0;ii<meshes.size();ii++)
7272 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7273 throw INTERP_KERNEL::Exception(oss.str().c_str());
7275 const DataArrayDouble *coords=meshes.front()->getCoords();
7276 int meshDim=meshes.front()->getMeshDimension();
7277 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7279 int meshIndexLgth=0;
7280 for(;iter!=meshes.end();iter++)
7282 if(coords!=(*iter)->getCoords())
7283 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7284 if(meshDim!=(*iter)->getMeshDimension())
7285 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7286 meshLgth+=(*iter)->getMeshLength();
7287 meshIndexLgth+=(*iter)->getNumberOfCells();
7289 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7290 nodal->alloc(meshLgth,1);
7291 int *nodalPtr=nodal->getPointer();
7292 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7293 nodalIndex->alloc(meshIndexLgth+1,1);
7294 int *nodalIndexPtr=nodalIndex->getPointer();
7296 for(iter=meshes.begin();iter!=meshes.end();iter++)
7298 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7299 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7300 int nbOfCells=(*iter)->getNumberOfCells();
7301 int meshLgth2=(*iter)->getMeshLength();
7302 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7303 if(iter!=meshes.begin())
7304 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7306 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7309 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7310 ret->setName("merge");
7311 ret->setMeshDimension(meshDim);
7312 ret->setConnectivity(nodal,nodalIndex,true);
7313 ret->setCoords(coords);
7318 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7319 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7320 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7321 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7322 * New" mode are returned for each input mesh.
7323 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7324 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7325 * valid values [0,1,2], see zipConnectivityTraducer().
7326 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7327 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7328 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7330 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7331 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7332 * is no more needed.
7333 * \throw If \a meshes.size() == 0.
7334 * \throw If \a meshes[ *i* ] == NULL.
7335 * \throw If the meshes do not share the node coordinates array.
7336 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7337 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7338 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7339 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7341 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7343 //All checks are delegated to MergeUMeshesOnSameCoords
7344 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7345 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7346 corr.resize(meshes.size());
7347 std::size_t nbOfMeshes=meshes.size();
7349 const int *o2nPtr=o2n->getConstPointer();
7350 for(std::size_t i=0;i<nbOfMeshes;i++)
7352 DataArrayInt *tmp=DataArrayInt::New();
7353 int curNbOfCells=meshes[i]->getNumberOfCells();
7354 tmp->alloc(curNbOfCells,1);
7355 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7356 offset+=curNbOfCells;
7357 tmp->setName(meshes[i]->getName());
7364 * Makes all given meshes share the nodal connectivity array. The common connectivity
7365 * array is created by concatenating the connectivity arrays of all given meshes. All
7366 * the given meshes must be of the same space dimension but dimension of cells **can
7367 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7368 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7369 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7370 * \param [in,out] meshes - a vector of meshes to update.
7371 * \throw If any of \a meshes is NULL.
7372 * \throw If the coordinates array is not set in any of \a meshes.
7373 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7374 * \throw If \a meshes are of different space dimension.
7376 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7378 std::size_t sz=meshes.size();
7381 std::vector< const DataArrayDouble * > coords(meshes.size());
7382 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7383 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7387 (*it)->checkConnectivityFullyDefined();
7388 const DataArrayDouble *coo=(*it)->getCoords();
7393 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7394 oss << " has no coordinate array defined !";
7395 throw INTERP_KERNEL::Exception(oss.str().c_str());
7400 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7401 oss << " is null !";
7402 throw INTERP_KERNEL::Exception(oss.str().c_str());
7405 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7406 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7407 int offset=(*it)->getNumberOfNodes();
7408 (*it++)->setCoords(res);
7409 for(;it!=meshes.end();it++)
7411 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7412 (*it)->setCoords(res);
7413 (*it)->shiftNodeNumbersInConn(offset);
7414 offset+=oldNumberOfNodes;
7419 * Merges nodes coincident with a given precision within all given meshes that share
7420 * the nodal connectivity array. The given meshes **can be of different** mesh
7421 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7422 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7423 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7424 * \param [in,out] meshes - a vector of meshes to update.
7425 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7426 * \throw If any of \a meshes is NULL.
7427 * \throw If the \a meshes do not share the same node coordinates array.
7428 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7430 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7434 std::set<const DataArrayDouble *> s;
7435 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7438 s.insert((*it)->getCoords());
7441 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 !";
7442 throw INTERP_KERNEL::Exception(oss.str().c_str());
7447 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 !";
7448 throw INTERP_KERNEL::Exception(oss.str().c_str());
7450 const DataArrayDouble *coo=*(s.begin());
7454 DataArrayInt *comm,*commI;
7455 coo->findCommonTuples(eps,-1,comm,commI);
7456 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7457 int oldNbOfNodes=coo->getNumberOfTuples();
7459 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7460 if(oldNbOfNodes==newNbOfNodes)
7462 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7463 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7465 (*it)->renumberNodesInConn(o2n->getConstPointer());
7466 (*it)->setCoords(newCoords);
7471 * 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.
7472 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7473 * \param isQuad specifies the policy of connectivity.
7474 * @ret in/out parameter in which the result will be append
7476 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7478 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7479 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7480 ret.push_back(cm.getExtrudedType());
7481 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7484 case INTERP_KERNEL::NORM_POINT1:
7486 ret.push_back(connBg[1]);
7487 ret.push_back(connBg[1]+nbOfNodesPerLev);
7490 case INTERP_KERNEL::NORM_SEG2:
7492 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7493 ret.insert(ret.end(),conn,conn+4);
7496 case INTERP_KERNEL::NORM_SEG3:
7498 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7499 ret.insert(ret.end(),conn,conn+8);
7502 case INTERP_KERNEL::NORM_QUAD4:
7504 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7505 ret.insert(ret.end(),conn,conn+8);
7508 case INTERP_KERNEL::NORM_TRI3:
7510 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7511 ret.insert(ret.end(),conn,conn+6);
7514 case INTERP_KERNEL::NORM_TRI6:
7516 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,
7517 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7518 ret.insert(ret.end(),conn,conn+15);
7521 case INTERP_KERNEL::NORM_QUAD8:
7524 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7525 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7526 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7528 ret.insert(ret.end(),conn,conn+20);
7531 case INTERP_KERNEL::NORM_POLYGON:
7533 std::back_insert_iterator< std::vector<int> > ii(ret);
7534 std::copy(connBg+1,connEnd,ii);
7536 std::reverse_iterator<const int *> rConnBg(connEnd);
7537 std::reverse_iterator<const int *> rConnEnd(connBg+1);
7538 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7539 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7540 for(std::size_t i=0;i<nbOfRadFaces;i++)
7543 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7544 std::copy(conn,conn+4,ii);
7549 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7554 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7556 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7558 double v[3]={0.,0.,0.};
7559 std::size_t sz=std::distance(begin,end);
7562 for(std::size_t i=0;i<sz;i++)
7564 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];
7565 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7566 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7568 return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7572 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7574 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7576 std::vector<std::pair<int,int> > edges;
7577 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7578 const int *bgFace=begin;
7579 for(std::size_t i=0;i<nbOfFaces;i++)
7581 const int *endFace=std::find(bgFace+1,end,-1);
7582 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7583 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7585 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7586 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7588 edges.push_back(p1);
7592 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7596 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7598 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7600 double vec0[3],vec1[3];
7601 std::size_t sz=std::distance(begin,end);
7603 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7604 int nbOfNodes=(int)sz/2;
7605 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7606 const double *pt0=coords+3*begin[0];
7607 const double *pt1=coords+3*begin[nbOfNodes];
7608 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7609 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7612 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7614 std::size_t sz=std::distance(begin,end);
7615 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7616 std::size_t nbOfNodes(sz/2);
7617 std::copy(begin,end,(int *)tmp);
7618 for(std::size_t j=1;j<nbOfNodes;j++)
7620 begin[j]=tmp[nbOfNodes-j];
7621 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7625 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7627 std::size_t sz=std::distance(begin,end);
7629 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7630 double vec0[3],vec1[3];
7631 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7632 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];
7633 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;
7636 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7638 std::size_t sz=std::distance(begin,end);
7640 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7642 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7643 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7644 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7648 * 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 )
7649 * 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
7652 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7653 * \param [in] coords the coordinates with nb of components exactly equal to 3
7654 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7655 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7656 * \param [out] res the result is put at the end of the vector without any alteration of the data.
7658 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7660 int nbFaces=std::count(begin+1,end,-1)+1;
7661 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7662 double *vPtr=v->getPointer();
7663 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7664 double *pPtr=p->getPointer();
7665 const int *stFaceConn=begin+1;
7666 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7668 const int *endFaceConn=std::find(stFaceConn,end,-1);
7669 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7670 stFaceConn=endFaceConn+1;
7672 pPtr=p->getPointer(); vPtr=v->getPointer();
7673 DataArrayInt *comm1=0,*commI1=0;
7674 v->findCommonTuples(eps,-1,comm1,commI1);
7675 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7676 const int *comm1Ptr=comm1->getConstPointer();
7677 const int *commI1Ptr=commI1->getConstPointer();
7678 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7679 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7681 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7682 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7683 mm->finishInsertingCells();
7685 for(int i=0;i<nbOfGrps1;i++)
7687 int vecId=comm1Ptr[commI1Ptr[i]];
7688 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7689 DataArrayInt *comm2=0,*commI2=0;
7690 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7691 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7692 const int *comm2Ptr=comm2->getConstPointer();
7693 const int *commI2Ptr=commI2->getConstPointer();
7694 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7695 for(int j=0;j<nbOfGrps2;j++)
7697 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7699 res->insertAtTheEnd(begin,end);
7700 res->pushBackSilent(-1);
7704 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7705 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7706 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7707 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7708 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7709 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7710 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7711 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7712 const int *idsNodePtr=idsNode->getConstPointer();
7713 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];
7714 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7715 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7716 if(std::abs(norm)>eps)
7718 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7719 mm3->rotate(center,vec,angle);
7721 mm3->changeSpaceDimension(2);
7722 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7723 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7724 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7725 int nbOfCells=mm4->getNumberOfCells();
7726 for(int k=0;k<nbOfCells;k++)
7729 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7730 res->pushBackSilent(idsNodePtr[*work]);
7731 res->pushBackSilent(-1);
7736 res->popBackSilent();
7740 * 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
7741 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7743 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7744 * \param [in] coords coordinates expected to have 3 components.
7745 * \param [in] begin start of the nodal connectivity of the face.
7746 * \param [in] end end of the nodal connectivity (excluded) of the face.
7747 * \param [out] v the normalized vector of size 3
7748 * \param [out] p the pos of plane
7750 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7752 std::size_t nbPoints=std::distance(begin,end);
7754 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7755 double vec[3]={0.,0.,0.};
7757 bool refFound=false;
7758 for(;j<nbPoints-1 && !refFound;j++)
7760 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7761 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7762 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7763 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7767 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7770 for(std::size_t i=j;i<nbPoints-1;i++)
7773 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7774 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7775 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7776 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7779 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7780 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];
7781 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7784 v[0]/=norm; v[1]/=norm; v[2]/=norm;
7785 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7789 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7793 * This method tries to obtain a well oriented polyhedron.
7794 * If the algorithm fails, an exception will be thrown.
7796 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7798 std::list< std::pair<int,int> > edgesOK,edgesFinished;
7799 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7800 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7802 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7803 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7804 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7806 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7809 std::size_t smthChanged=0;
7810 for(std::size_t i=0;i<nbOfFaces;i++)
7812 endFace=std::find(bgFace+1,end,-1);
7813 nbOfEdgesInFace=std::distance(bgFace,endFace);
7817 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7819 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7820 std::pair<int,int> p2(p1.second,p1.first);
7821 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7822 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7823 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7828 std::reverse(bgFace+1,endFace);
7829 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7831 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7832 std::pair<int,int> p2(p1.second,p1.first);
7833 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7834 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7835 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7836 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7837 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7838 if(it!=edgesOK.end())
7841 edgesFinished.push_back(p1);
7844 edgesOK.push_back(p1);
7851 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7853 if(!edgesOK.empty())
7854 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7855 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7856 {//not lucky ! The first face was not correctly oriented : reorient all faces...
7858 for(std::size_t i=0;i<nbOfFaces;i++)
7860 endFace=std::find(bgFace+1,end,-1);
7861 std::reverse(bgFace+1,endFace);
7868 * This method makes the assumption spacedimension == meshdimension == 2.
7869 * This method works only for linear cells.
7871 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7873 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7875 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7876 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7877 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7878 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7879 int nbOfNodesExpected=m->getNumberOfNodes();
7880 if(m->getNumberOfCells()!=nbOfNodesExpected)
7881 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7882 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7883 const int *n2oPtr=n2o->getConstPointer();
7884 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7885 m->getReverseNodalConnectivity(revNodal,revNodalI);
7886 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7887 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7888 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7889 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7890 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
7891 if(nbOfNodesExpected<1)
7894 int prevNode=nodalPtr[nodalIPtr[0]+1];
7895 *work++=n2oPtr[prevNode];
7896 for(int i=1;i<nbOfNodesExpected;i++)
7898 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7900 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
7901 conn.erase(prevNode);
7904 int curNode=*(conn.begin());
7905 *work++=n2oPtr[curNode];
7906 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
7907 shar.erase(prevCell);
7910 prevCell=*(shar.begin());
7914 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
7917 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
7920 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
7926 * This method makes the assumption spacedimension == meshdimension == 3.
7927 * This method works only for linear cells.
7929 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7931 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
7933 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7934 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7935 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7936 const int *conn=m->getNodalConnectivity()->getConstPointer();
7937 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
7938 int nbOfCells=m->getNumberOfCells();
7939 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7940 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
7943 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7944 for(int i=1;i<nbOfCells;i++)
7947 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
7953 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
7954 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
7956 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
7960 for(int i=0;i<nbOfNodesInCell;i++)
7961 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
7962 else if(spaceDim==2)
7964 for(int i=0;i<nbOfNodesInCell;i++)
7966 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
7971 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
7974 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
7976 int nbOfCells=getNumberOfCells();
7978 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
7979 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};
7980 ofs << " <" << getVTKDataSetType() << ">\n";
7981 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
7982 ofs << " <PointData>\n" << pointData << std::endl;
7983 ofs << " </PointData>\n";
7984 ofs << " <CellData>\n" << cellData << std::endl;
7985 ofs << " </CellData>\n";
7986 ofs << " <Points>\n";
7987 if(getSpaceDimension()==3)
7988 _coords->writeVTK(ofs,8,"Points");
7991 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
7992 coo->writeVTK(ofs,8,"Points");
7994 ofs << " </Points>\n";
7995 ofs << " <Cells>\n";
7996 const int *cPtr=_nodal_connec->getConstPointer();
7997 const int *cIPtr=_nodal_connec_index->getConstPointer();
7998 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
7999 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8000 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8001 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8002 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8003 int szFaceOffsets=0,szConn=0;
8004 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8007 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8010 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8011 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8015 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8016 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8017 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8018 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8019 w4=std::copy(c.begin(),c.end(),w4);
8022 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8023 types->writeVTK(ofs,8,"UInt8","types");
8024 offsets->writeVTK(ofs,8,"Int32","offsets");
8025 if(szFaceOffsets!=0)
8026 {//presence of Polyhedra
8027 connectivity->reAlloc(szConn);
8028 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8029 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8030 w1=faces->getPointer();
8031 for(int i=0;i<nbOfCells;i++)
8032 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8034 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8036 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8037 for(int j=0;j<nbFaces;j++)
8039 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8040 *w1++=(int)std::distance(w6,w5);
8041 w1=std::copy(w6,w5,w1);
8045 faces->writeVTK(ofs,8,"Int32","faces");
8047 connectivity->writeVTK(ofs,8,"Int32","connectivity");
8048 ofs << " </Cells>\n";
8049 ofs << " </Piece>\n";
8050 ofs << " </" << getVTKDataSetType() << ">\n";
8053 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8055 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8057 { stream << " Not set !"; return ; }
8058 stream << " Mesh dimension : " << _mesh_dim << ".";
8062 { stream << " No coordinates set !"; return ; }
8063 if(!_coords->isAllocated())
8064 { stream << " Coordinates set but not allocated !"; return ; }
8065 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8066 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8067 if(!_nodal_connec_index)
8068 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8069 if(!_nodal_connec_index->isAllocated())
8070 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8071 int lgth=_nodal_connec_index->getNumberOfTuples();
8072 int cpt=_nodal_connec_index->getNumberOfComponents();
8073 if(cpt!=1 || lgth<1)
8075 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8078 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8080 return std::string("UnstructuredGrid");
8084 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8085 * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8086 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8088 * \param [in] m1 - the first input mesh which is a partitioned object.
8089 * \param [in] m2 - the second input mesh which is a partition tool.
8090 * \param [in] eps - precision used to detect coincident mesh entities.
8091 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8092 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8093 * this array using decrRef() as it is no more needed.
8094 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8095 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8096 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8097 * any cell of \a m2. The caller is to delete this array using decrRef() as
8098 * it is no more needed.
8099 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8100 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8101 * is no more needed.
8102 * \throw If the coordinates array is not set in any of the meshes.
8103 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8104 * \throw If any of the meshes is not a 2D mesh in 2D space.
8106 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8108 m1->checkFullyDefined();
8109 m2->checkFullyDefined();
8110 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8111 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8112 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8113 MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8114 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8115 std::vector<double> addCoo,addCoordsQuadratic;
8116 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8117 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8118 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8119 m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8120 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8121 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8122 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8123 std::vector< std::vector<int> > intersectEdge2;
8124 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8125 subDiv2.clear(); dd5=0; dd6=0;
8126 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8127 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8128 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8129 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8131 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8132 addCooDa->alloc((int)(addCoo.size())/2,2);
8133 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8134 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8135 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8136 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8137 std::vector<const DataArrayDouble *> coordss(4);
8138 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8139 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8140 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8141 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8142 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8143 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8144 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8145 ret->setConnectivity(conn,connI,true);
8146 ret->setCoords(coo);
8147 cellNb1=c1.retn(); cellNb2=c2.retn();
8151 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8152 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8153 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8154 const std::vector<double>& addCoords,
8155 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8157 static const int SPACEDIM=2;
8158 std::vector<double> bbox1,bbox2;
8159 const double *coo1=m1->getCoords()->getConstPointer();
8160 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8161 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8162 int offset1=m1->getNumberOfNodes();
8163 const double *coo2=m2->getCoords()->getConstPointer();
8164 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8165 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8166 int offset2=offset1+m2->getNumberOfNodes();
8167 int offset3=offset2+((int)addCoords.size())/2;
8168 m1->getBoundingBoxForBBTree(bbox1);
8169 m2->getBoundingBoxForBBTree(bbox2);
8170 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8171 int ncell1=m1->getNumberOfCells();
8173 for(int i=0;i<ncell1;i++)
8175 std::vector<int> candidates2;
8176 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8177 std::map<INTERP_KERNEL::Node *,int> mapp;
8178 std::map<int,INTERP_KERNEL::Node *> mappRev;
8179 INTERP_KERNEL::QuadraticPolygon pol1;
8180 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8181 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8182 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8183 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8184 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8186 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
8187 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8188 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8189 for(it1.first();!it1.finished();it1.next())
8190 edges1.insert(it1.current()->getPtr());
8192 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8193 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8195 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8197 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8198 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8199 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8200 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8201 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8204 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8206 pol1.initLocationsWithOther(pol2s[ii]);
8207 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8208 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8209 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8215 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8217 catch(INTERP_KERNEL::Exception& e)
8219 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();
8220 throw INTERP_KERNEL::Exception(oss.str().c_str());
8223 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8224 (*it).second->decrRef();
8229 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8232 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8233 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8234 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8235 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8236 std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8238 static const int SPACEDIM=2;
8239 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8240 desc2=DataArrayInt::New();
8241 descIndx2=DataArrayInt::New();
8242 revDesc2=DataArrayInt::New();
8243 revDescIndx2=DataArrayInt::New();
8244 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8245 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8246 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8247 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8248 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8249 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8250 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8251 std::vector<double> bbox1,bbox2;
8252 m1Desc->getBoundingBoxForBBTree(bbox1);
8253 m2Desc->getBoundingBoxForBBTree(bbox2);
8254 int ncell1=m1Desc->getNumberOfCells();
8255 int ncell2=m2Desc->getNumberOfCells();
8256 intersectEdge1.resize(ncell1);
8257 colinear2.resize(ncell2);
8258 subDiv2.resize(ncell2);
8259 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8260 std::vector<int> candidates1(1);
8261 int offset1=m1->getNumberOfNodes();
8262 int offset2=offset1+m2->getNumberOfNodes();
8263 for(int i=0;i<ncell1;i++)
8265 std::vector<int> candidates2;
8266 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8267 if(!candidates2.empty())
8269 std::map<INTERP_KERNEL::Node *,int> map1,map2;
8270 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8272 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8273 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8278 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8280 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8281 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8285 * This method performs the 2nd step of Partition of 2D mesh.
8286 * This method has 4 inputs :
8287 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8288 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8289 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8290 * 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'
8291 * \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'
8292 * \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.
8293 * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8295 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)
8297 int offset1=m1->getNumberOfNodes();
8298 int ncell=m2->getNumberOfCells();
8299 const int *c=m2->getNodalConnectivity()->getConstPointer();
8300 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8301 const double *coo=m2->getCoords()->getConstPointer();
8302 const double *cooBis=m1->getCoords()->getConstPointer();
8303 int offset2=offset1+m2->getNumberOfNodes();
8304 intersectEdge.resize(ncell);
8305 for(int i=0;i<ncell;i++,cI++)
8307 const std::vector<int>& divs=subDiv[i];
8308 int nnode=cI[1]-cI[0]-1;
8309 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8310 std::map<INTERP_KERNEL::Node *, int> mapp22;
8311 for(int j=0;j<nnode;j++)
8313 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8314 int nnid=c[(*cI)+j+1];
8315 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8316 mapp22[nn]=nnid+offset1;
8318 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8319 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8320 ((*it).second.first)->decrRef();
8321 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8322 std::map<INTERP_KERNEL::Node *,int> mapp3;
8323 for(std::size_t j=0;j<divs.size();j++)
8326 INTERP_KERNEL::Node *tmp=0;
8328 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8330 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8332 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8336 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8337 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8344 * 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).
8345 * 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
8346 * with a plane. The result will be put in 'cut3DSuf' out parameter.
8347 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8348 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8349 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8350 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8351 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8352 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8353 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8354 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8355 * \param [out] cut3DSuf input/output param.
8357 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8358 const int *nodal3DCurve, const int *nodalIndx3DCurve,
8359 const int *desc, const int *descIndx,
8360 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8362 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8363 int nbOf3DSurfCell=(int)cut3DSurf.size();
8364 for(int i=0;i<nbOf3DSurfCell;i++)
8366 std::vector<int> res;
8367 int offset=descIndx[i];
8368 int nbOfSeg=descIndx[i+1]-offset;
8369 for(int j=0;j<nbOfSeg;j++)
8371 int edgeId=desc[offset+j];
8372 int status=cut3DCurve[edgeId];
8376 res.push_back(status);
8379 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8380 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8388 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8394 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8395 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8398 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8402 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8407 {// case when plane is on a multi colinear edge of a polyhedron
8408 if((int)res.size()==2*nbOfSeg)
8410 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8413 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8420 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8421 * 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).
8422 * 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
8423 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8424 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8425 * \param desc is the descending connectivity 3D->3DSurf
8426 * \param descIndx is the descending connectivity index 3D->3DSurf
8428 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8429 const int *desc, const int *descIndx,
8430 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8432 checkFullyDefined();
8433 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8434 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8435 const int *nodal3D=_nodal_connec->getConstPointer();
8436 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8437 int nbOfCells=getNumberOfCells();
8438 for(int i=0;i<nbOfCells;i++)
8440 std::map<int, std::set<int> > m;
8441 int offset=descIndx[i];
8442 int nbOfFaces=descIndx[i+1]-offset;
8445 for(int j=0;j<nbOfFaces;j++)
8447 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8448 if(p.first!=-1 && p.second!=-1)
8452 start=p.first; end=p.second;
8453 m[p.first].insert(p.second);
8454 m[p.second].insert(p.first);
8458 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8459 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8460 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8461 INTERP_KERNEL::NormalizedCellType cmsId;
8462 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8463 start=tmp[0]; end=tmp[nbOfNodesSon-1];
8464 for(unsigned k=0;k<nbOfNodesSon;k++)
8466 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8467 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8474 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8478 std::map<int, std::set<int> >::const_iterator it=m.find(start);
8479 const std::set<int>& s=(*it).second;
8480 std::set<int> s2; s2.insert(prev);
8482 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8485 int val=*s3.begin();
8486 conn.push_back(start);
8493 conn.push_back(end);
8496 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8497 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8498 cellIds->pushBackSilent(i);
8504 * 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
8505 * 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
8506 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8507 * 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
8508 * 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.
8510 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8512 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8514 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8517 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8518 if(cm.getDimension()==2)
8520 const int *node=nodalConnBg+1;
8521 int startNode=*node++;
8522 double refX=coords[2*startNode];
8523 for(;node!=nodalConnEnd;node++)
8525 if(coords[2*(*node)]<refX)
8528 refX=coords[2*startNode];
8531 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8535 double angle0=-M_PI/2;
8540 double angleNext=0.;
8541 while(nextNode!=startNode)
8545 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8547 if(*node!=tmpOut.back() && *node!=prevNode)
8549 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8550 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8555 res=angle0-angleM+2.*M_PI;
8564 if(nextNode!=startNode)
8566 angle0=angleNext-M_PI;
8569 prevNode=tmpOut.back();
8570 tmpOut.push_back(nextNode);
8573 std::vector<int> tmp3(2*(sz-1));
8574 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8575 std::copy(nodalConnBg+1,nodalConnEnd,it);
8576 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8578 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8581 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8583 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8588 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8589 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8594 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8597 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8601 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8602 * 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.
8604 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8605 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8606 * \param [in,out] arr array in which the remove operation will be done.
8607 * \param [in,out] arrIndx array in the remove operation will modify
8608 * \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])
8609 * \return true if \b arr and \b arrIndx have been modified, false if not.
8611 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8613 if(!arrIndx || !arr)
8614 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8615 if(offsetForRemoval<0)
8616 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8617 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8618 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8619 int *arrIPtr=arrIndx->getPointer();
8622 const int *arrPtr=arr->getConstPointer();
8623 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8624 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8626 if(*arrIPtr-previousArrI>offsetForRemoval)
8628 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8630 if(s.find(*work)==s.end())
8631 arrOut.push_back(*work);
8634 previousArrI=*arrIPtr;
8635 *arrIPtr=(int)arrOut.size();
8637 if(arr->getNumberOfTuples()==(int)arrOut.size())
8639 arr->alloc((int)arrOut.size(),1);
8640 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8645 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8646 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8647 * The selection of extraction is done standardly in new2old format.
8648 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8650 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8651 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8652 * \param [in] arrIn arr origin array from which the extraction will be done.
8653 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8654 * \param [out] arrOut the resulting array
8655 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8657 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8658 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8660 if(!arrIn || !arrIndxIn)
8661 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8662 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8663 const int *arrInPtr=arrIn->getConstPointer();
8664 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8665 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8666 int maxSizeOfArr=arrIn->getNumberOfTuples();
8667 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8668 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8669 arrIo->alloc((int)(sz+1),1);
8670 const int *idsIt=idsOfSelectBg;
8671 int *work=arrIo->getPointer();
8674 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8676 if(*idsIt>=0 && *idsIt<nbOfGrps)
8677 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8680 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8681 throw INTERP_KERNEL::Exception(oss.str().c_str());
8687 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8688 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8689 throw INTERP_KERNEL::Exception(oss.str().c_str());
8692 arro->alloc(lgth,1);
8693 work=arro->getPointer();
8694 idsIt=idsOfSelectBg;
8695 for(std::size_t i=0;i<sz;i++,idsIt++)
8697 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8698 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8701 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8702 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8703 throw INTERP_KERNEL::Exception(oss.str().c_str());
8707 arrIndexOut=arrIo.retn();
8711 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8712 * 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
8713 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8714 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8716 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8717 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8718 * \param [in] arrIn arr origin array from which the extraction will be done.
8719 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8720 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8721 * \param [in] srcArrIndex index array of \b srcArr
8722 * \param [out] arrOut the resulting array
8723 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8725 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8727 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8728 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8729 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8731 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8732 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8733 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8734 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8735 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8736 std::vector<bool> v(nbOfTuples,true);
8738 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8739 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8740 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8742 if(*it>=0 && *it<nbOfTuples)
8745 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8749 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8750 throw INTERP_KERNEL::Exception(oss.str().c_str());
8753 srcArrIndexPtr=srcArrIndex->getConstPointer();
8754 arrIo->alloc(nbOfTuples+1,1);
8755 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8756 const int *arrInPtr=arrIn->getConstPointer();
8757 const int *srcArrPtr=srcArr->getConstPointer();
8758 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8759 int *arroPtr=arro->getPointer();
8760 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8764 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8765 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8769 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8770 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8771 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8775 arrIndexOut=arrIo.retn();
8779 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8780 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8782 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8783 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8784 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8785 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8786 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8787 * \param [in] srcArrIndex index array of \b srcArr
8789 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8791 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8792 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8794 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8795 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8796 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8797 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8798 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8799 int *arrInOutPtr=arrInOut->getPointer();
8800 const int *srcArrPtr=srcArr->getConstPointer();
8801 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8803 if(*it>=0 && *it<nbOfTuples)
8805 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8806 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8809 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] !";
8810 throw INTERP_KERNEL::Exception(oss.str().c_str());
8815 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8816 throw INTERP_KERNEL::Exception(oss.str().c_str());
8822 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8823 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8824 * 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]].
8825 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8826 * A negative value in \b arrIn means that it is ignored.
8827 * 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.
8829 * \param [in] arrIn arr origin array from which the extraction will be done.
8830 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8831 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8832 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8834 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
8836 int seed=0,nbOfDepthPeelingPerformed=0;
8837 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
8841 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8842 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8843 * 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]].
8844 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8845 * A negative value in \b arrIn means that it is ignored.
8846 * 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.
8847 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
8848 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
8849 * \param [in] arrIn arr origin array from which the extraction will be done.
8850 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8851 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8852 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8853 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8854 * \sa MEDCouplingUMesh::partitionBySpreadZone
8856 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8858 nbOfDepthPeelingPerformed=0;
8860 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8861 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8864 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
8868 std::vector<bool> fetched(nbOfTuples,false);
8869 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
8872 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)
8874 nbOfDepthPeelingPerformed=0;
8875 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
8876 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
8877 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8878 std::vector<bool> fetched2(nbOfTuples,false);
8880 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
8882 if(*seedElt>=0 && *seedElt<nbOfTuples)
8883 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
8885 { 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()); }
8887 const int *arrInPtr=arrIn->getConstPointer();
8888 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8889 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
8890 std::vector<int> idsToFetch1(seedBg,seedEnd);
8891 std::vector<int> idsToFetch2;
8892 std::vector<int> *idsToFetch=&idsToFetch1;
8893 std::vector<int> *idsToFetchOther=&idsToFetch2;
8894 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
8896 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
8897 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
8899 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
8900 std::swap(idsToFetch,idsToFetchOther);
8901 idsToFetchOther->clear();
8902 nbOfDepthPeelingPerformed++;
8904 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
8906 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
8907 int *retPtr=ret->getPointer();
8908 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
8915 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8916 * 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
8917 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8918 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8920 * \param [in] start begin of set of ids of the input extraction (included)
8921 * \param [in] end end of set of ids of the input extraction (excluded)
8922 * \param [in] step step of the set of ids in range mode.
8923 * \param [in] arrIn arr origin array from which the extraction will be done.
8924 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8925 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8926 * \param [in] srcArrIndex index array of \b srcArr
8927 * \param [out] arrOut the resulting array
8928 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8930 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
8932 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8933 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8934 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8936 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8937 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
8938 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8939 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8940 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8942 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8943 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8944 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
8946 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
8948 if(it>=0 && it<nbOfTuples)
8949 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
8952 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
8953 throw INTERP_KERNEL::Exception(oss.str().c_str());
8956 srcArrIndexPtr=srcArrIndex->getConstPointer();
8957 arrIo->alloc(nbOfTuples+1,1);
8958 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8959 const int *arrInPtr=arrIn->getConstPointer();
8960 const int *srcArrPtr=srcArr->getConstPointer();
8961 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8962 int *arroPtr=arro->getPointer();
8963 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8965 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
8968 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8969 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8973 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8974 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8978 arrIndexOut=arrIo.retn();
8982 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8983 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8985 * \param [in] start begin of set of ids of the input extraction (included)
8986 * \param [in] end end of set of ids of the input extraction (excluded)
8987 * \param [in] step step of the set of ids in range mode.
8988 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8989 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8990 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
8991 * \param [in] srcArrIndex index array of \b srcArr
8993 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8995 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8996 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8998 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8999 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9000 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9001 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9002 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9003 int *arrInOutPtr=arrInOut->getPointer();
9004 const int *srcArrPtr=srcArr->getConstPointer();
9005 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9007 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9009 if(it>=0 && it<nbOfTuples)
9011 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9012 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9015 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9016 throw INTERP_KERNEL::Exception(oss.str().c_str());
9021 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9022 throw INTERP_KERNEL::Exception(oss.str().c_str());
9028 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9029 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9030 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9031 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9032 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9034 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9036 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9038 checkFullyDefined();
9039 int mdim=getMeshDimension();
9040 int spaceDim=getSpaceDimension();
9042 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9043 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9044 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9045 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9046 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9047 ret->setCoords(getCoords());
9048 ret->allocateCells((int)partition.size());
9050 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9052 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9053 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9057 cell=tmp->buildUnionOf2DMesh();
9060 cell=tmp->buildUnionOf3DMesh();
9063 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9066 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9069 ret->finishInsertingCells();
9074 * This method partitions \b this into contiguous zone.
9075 * This method only needs a well defined connectivity. Coordinates are not considered here.
9076 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9078 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9081 int nbOfCellsCur=getNumberOfCells();
9082 std::vector<DataArrayInt *> ret;
9085 DataArrayInt *neigh=0,*neighI=0;
9086 computeNeighborsOfCells(neigh,neighI);
9087 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9088 std::vector<bool> fetchedCells(nbOfCellsCur,false);
9089 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9091 while(seed<nbOfCellsCur)
9093 int nbOfPeelPerformed=0;
9094 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9095 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9097 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9098 ret.push_back((*it).retn());
9102 int nbOfCellsCur=getNumberOfCells();
9103 DataArrayInt *neigh=0,*neighI=0;
9104 computeNeighborsOfCells(neigh,neighI);
9105 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9106 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9107 std::vector<DataArrayInt *> ret;
9108 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9109 while(nbOfCellsCur>0)
9111 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9112 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9113 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9114 ret2.push_back(tmp2); ret.push_back(tmp2);
9115 nbOfCellsCur=tmp3->getNumberOfTuples();
9118 ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9119 MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9122 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9123 neighAuto->transformWithIndArr(renum->begin(),renum->end());
9126 for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9133 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9134 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9136 * \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.
9137 * \return a newly allocated DataArrayInt to be managed by the caller.
9138 * \throw In case of \a code has not the right format (typically of size 3*n)
9140 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9142 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9143 std::size_t nb=code.size()/3;
9144 if(code.size()%3!=0)
9145 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9146 ret->alloc((int)nb,2);
9147 int *retPtr=ret->getPointer();
9148 for(std::size_t i=0;i<nb;i++,retPtr+=2)
9150 retPtr[0]=code[3*i+2];
9151 retPtr[1]=code[3*i+2]+code[3*i+1];
9156 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9157 _own_cell(true),_cell_id(-1),_nb_cell(0)
9162 _nb_cell=mesh->getNumberOfCells();
9166 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9174 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9175 _own_cell(false),_cell_id(bg-1),
9182 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9185 if(_cell_id<_nb_cell)
9194 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9200 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9202 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9205 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9211 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9219 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9225 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9230 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9235 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9237 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9240 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9245 _nb_cell=mesh->getNumberOfCells();
9249 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9256 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9258 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9259 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9260 if(_cell_id<_nb_cell)
9262 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9263 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9264 int startId=_cell_id;
9265 _cell_id+=nbOfElems;
9266 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9272 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9276 _conn=mesh->getNodalConnectivity()->getPointer();
9277 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9281 void MEDCouplingUMeshCell::next()
9283 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9288 _conn_lgth=_conn_indx[1]-_conn_indx[0];
9291 std::string MEDCouplingUMeshCell::repr() const
9293 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9295 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9297 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9301 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9304 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9306 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9307 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9309 return INTERP_KERNEL::NORM_ERROR;
9312 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9315 if(_conn_lgth!=NOTICABLE_FIRST_VAL)