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);
93 * This method behaves mostly like MEDCouplingUMesh::deepCpy method, except that only nodal connectivity arrays are deeply copied.
94 * The coordinates are shared between \a this and the returned instance.
96 * \return MEDCouplingUMesh * - A new object instance holding the copy of \a this (deep for connectivity, shallow for coordiantes)
97 * \sa MEDCouplingUMesh::deepCpy
99 MEDCouplingPointSet *MEDCouplingUMesh::deepCpyConnectivityOnly() const throw(INTERP_KERNEL::Exception)
101 checkConnectivityFullyDefined();
102 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=clone(false);
103 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(getNodalConnectivity()->deepCpy()),ci(getNodalConnectivityIndex()->deepCpy());
104 ret->setConnectivity(c,ci);
108 void MEDCouplingUMesh::shallowCopyConnectivityFrom(const MEDCouplingPointSet *other) throw(INTERP_KERNEL::Exception)
111 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is null !");
112 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
114 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::shallowCopyConnectivityFrom : input pointer is not an MEDCouplingUMesh instance !");
115 MEDCouplingUMesh *otherC2=const_cast<MEDCouplingUMesh *>(otherC);//sorry :(
116 setConnectivity(otherC2->getNodalConnectivity(),otherC2->getNodalConnectivityIndex(),true);
119 std::size_t MEDCouplingUMesh::getHeapMemorySize() const
123 ret+=_nodal_connec->getHeapMemorySize();
124 if(_nodal_connec_index)
125 ret+=_nodal_connec_index->getHeapMemorySize();
126 return MEDCouplingPointSet::getHeapMemorySize()+ret;
129 void MEDCouplingUMesh::updateTime() const
131 MEDCouplingPointSet::updateTime();
134 updateTimeWith(*_nodal_connec);
136 if(_nodal_connec_index)
138 updateTimeWith(*_nodal_connec_index);
142 MEDCouplingUMesh::MEDCouplingUMesh():_mesh_dim(-2),_nodal_connec(0),_nodal_connec_index(0)
147 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
148 * then \a this mesh is most probably is writable, exchangeable and available for most
149 * of algorithms. When a mesh is constructed from scratch, it is a good habit to call
150 * this method to check that all is in order with \a this mesh.
151 * \throw If the mesh dimension is not set.
152 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
153 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
154 * \throw If the connectivity data array has more than one component.
155 * \throw If the connectivity data array has a named component.
156 * \throw If the connectivity index data array has more than one component.
157 * \throw If the connectivity index data array has a named component.
159 void MEDCouplingUMesh::checkCoherency() const throw(INTERP_KERNEL::Exception)
162 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
164 MEDCouplingPointSet::checkCoherency();
165 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
167 if((int)INTERP_KERNEL::CellModel::GetCellModel(*iter).getDimension()!=_mesh_dim)
169 std::ostringstream message;
170 message << "Mesh invalid because dimension is " << _mesh_dim << " and there is presence of cell(s) with type " << (*iter);
171 throw INTERP_KERNEL::Exception(message.str().c_str());
176 if(_nodal_connec->getNumberOfComponents()!=1)
177 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to be with number of components set to one !");
178 if(_nodal_connec->getInfoOnComponent(0)!="")
179 throw INTERP_KERNEL::Exception("Nodal connectivity array is expected to have no info on its single component !");
183 throw INTERP_KERNEL::Exception("Nodal connectivity array is not defined !");
184 if(_nodal_connec_index)
186 if(_nodal_connec_index->getNumberOfComponents()!=1)
187 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to be with number of components set to one !");
188 if(_nodal_connec_index->getInfoOnComponent(0)!="")
189 throw INTERP_KERNEL::Exception("Nodal connectivity index array is expected to have no info on its single component !");
193 throw INTERP_KERNEL::Exception("Nodal connectivity index array is not defined !");
197 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
198 * then \a this mesh is most probably is writable, exchangeable and available for all
199 * algorithms. <br> In addition to the checks performed by checkCoherency(), this
200 * method thoroughly checks the nodal connectivity.
201 * \param [in] eps - a not used parameter.
202 * \throw If the mesh dimension is not set.
203 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
204 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
205 * \throw If the connectivity data array has more than one component.
206 * \throw If the connectivity data array has a named component.
207 * \throw If the connectivity index data array has more than one component.
208 * \throw If the connectivity index data array has a named component.
209 * \throw If number of nodes defining an element does not correspond to the type of element.
210 * \throw If the nodal connectivity includes an invalid node id.
212 void MEDCouplingUMesh::checkCoherency1(double eps) const throw(INTERP_KERNEL::Exception)
217 int meshDim=getMeshDimension();
218 int nbOfNodes=getNumberOfNodes();
219 int nbOfCells=getNumberOfCells();
220 const int *ptr=_nodal_connec->getConstPointer();
221 const int *ptrI=_nodal_connec_index->getConstPointer();
222 for(int i=0;i<nbOfCells;i++)
224 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)ptr[ptrI[i]]);
225 if((int)cm.getDimension()!=meshDim)
227 std::ostringstream oss;
228 oss << "MEDCouplingUMesh::checkCoherency1 : cell << #" << i<< " with type Type " << cm.getRepr() << " in 'this' whereas meshdim == " << meshDim << " !";
229 throw INTERP_KERNEL::Exception(oss.str().c_str());
231 int nbOfNodesInCell=ptrI[i+1]-ptrI[i]-1;
233 if(nbOfNodesInCell!=(int)cm.getNumberOfNodes())
235 std::ostringstream oss;
236 oss << "MEDCouplingUMesh::checkCoherency1 : cell #" << i << " with static Type '" << cm.getRepr() << "' has " << cm.getNumberOfNodes();
237 oss << " nodes whereas in connectivity there is " << nbOfNodesInCell << " nodes ! Looks very bad !";
238 throw INTERP_KERNEL::Exception(oss.str().c_str());
240 for(const int *w=ptr+ptrI[i]+1;w!=ptr+ptrI[i+1];w++)
245 if(nodeId>=nbOfNodes)
247 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " whereas there are only " << nbOfNodes << " nodes !";
248 throw INTERP_KERNEL::Exception(oss.str().c_str());
253 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #" << nodeId << " in connectivity ! sounds bad !";
254 throw INTERP_KERNEL::Exception(oss.str().c_str());
258 if((INTERP_KERNEL::NormalizedCellType)(ptr[ptrI[i]])!=INTERP_KERNEL::NORM_POLYHED)
260 std::ostringstream oss; oss << "Cell #" << i << " is consituted of node #-1 in connectivity ! sounds bad !";
261 throw INTERP_KERNEL::Exception(oss.str().c_str());
270 * Checks if \a this mesh is well defined. If no exception is thrown by this method,
271 * then \a this mesh is most probably is writable, exchangeable and available for all
272 * algorithms. <br> This method performs the same checks as checkCoherency1() does.
273 * \param [in] eps - a not used parameter.
274 * \throw If the mesh dimension is not set.
275 * \throw If the coordinates array is not set (if mesh dimension != -1 ).
276 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
277 * \throw If the connectivity data array has more than one component.
278 * \throw If the connectivity data array has a named component.
279 * \throw If the connectivity index data array has more than one component.
280 * \throw If the connectivity index data array has a named component.
281 * \throw If number of nodes defining an element does not correspond to the type of element.
282 * \throw If the nodal connectivity includes an invalid node id.
284 void MEDCouplingUMesh::checkCoherency2(double eps) const throw(INTERP_KERNEL::Exception)
286 checkCoherency1(eps);
290 * Sets dimension of \a this mesh. The mesh dimension in general depends on types of
291 * elements contained in the mesh. For more info on the mesh dimension see
292 * \ref MEDCouplingUMeshPage.
293 * \param [in] meshDim - a new mesh dimension.
294 * \throw If \a meshDim is invalid. A valid range is <em> -1 <= meshDim <= 3</em>.
296 void MEDCouplingUMesh::setMeshDimension(int meshDim)
298 if(meshDim<-1 || meshDim>3)
299 throw INTERP_KERNEL::Exception("Invalid meshDim specified ! Must be greater or equal to -1 and lower or equal to 3 !");
305 * Allocates memory to store an estimation of the given number of cells. Closer is the estimation to the number of cells effectively inserted,
306 * less will be the needs to realloc. If the number of cells to be inserted is not known simply put 0 to this parameter.
307 * If a nodal connectivity previouly existed before the call of this method, it will be reset.
309 * \param [in] nbOfCells - estimation of the number of cell \a this mesh will contain.
311 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
312 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
314 void MEDCouplingUMesh::allocateCells(int nbOfCells)
317 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::allocateCells : the input number of cells should be >= 0 !");
318 if(_nodal_connec_index)
320 _nodal_connec_index->decrRef();
324 _nodal_connec->decrRef();
326 _nodal_connec_index=DataArrayInt::New();
327 _nodal_connec_index->reserve(nbOfCells+1);
328 _nodal_connec_index->pushBackSilent(0);
329 _nodal_connec=DataArrayInt::New();
330 _nodal_connec->reserve(2*nbOfCells);
336 * Appends a cell to the connectivity array. For deeper understanding what is
337 * happening see \ref MEDCouplingUMeshNodalConnectivity.
338 * \param [in] type - type of cell to add.
339 * \param [in] size - number of nodes constituting this cell.
340 * \param [in] nodalConnOfCell - the connectivity of the cell to add.
342 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
343 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
345 void MEDCouplingUMesh::insertNextCell(INTERP_KERNEL::NormalizedCellType type, int size, const int *nodalConnOfCell) throw(INTERP_KERNEL::Exception)
347 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
348 if(_nodal_connec_index==0)
349 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::insertNextCell : nodal connectivity not set ! invoke allocateCells before calling insertNextCell !");
350 if((int)cm.getDimension()==_mesh_dim)
353 if(size!=(int)cm.getNumberOfNodes())
355 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : Trying to push a " << cm.getRepr() << " cell with a size of " << size;
356 oss << " ! Expecting " << cm.getNumberOfNodes() << " !";
357 throw INTERP_KERNEL::Exception(oss.str().c_str());
359 int idx=_nodal_connec_index->back();
361 _nodal_connec_index->pushBackSilent(val);
362 _nodal_connec->writeOnPlace(idx,type,nodalConnOfCell,size);
367 std::ostringstream oss; oss << "MEDCouplingUMesh::insertNextCell : cell type " << cm.getRepr() << " has a dimension " << cm.getDimension();
368 oss << " whereas Mesh Dimension of current UMesh instance is set to " << _mesh_dim << " ! Please invoke \"setMeshDimension\" method before or invoke ";
369 oss << "\"MEDCouplingUMesh::New\" static method with 2 parameters name and meshDimension !";
370 throw INTERP_KERNEL::Exception(oss.str().c_str());
375 * Compacts data arrays to release unused memory. This method is to be called after
376 * finishing cell insertion using \a this->insertNextCell().
378 * \ref medcouplingcppexamplesUmeshStdBuild1 "Here is a C++ example".<br>
379 * \ref medcouplingpyexamplesUmeshStdBuild1 "Here is a Python example".
381 void MEDCouplingUMesh::finishInsertingCells()
383 _nodal_connec->pack();
384 _nodal_connec_index->pack();
385 _nodal_connec->declareAsNew();
386 _nodal_connec_index->declareAsNew();
391 * Entry point for iteration over cells of this. Warning the returned cell iterator should be deallocated.
392 * Useful for python users.
394 MEDCouplingUMeshCellIterator *MEDCouplingUMesh::cellIterator()
396 return new MEDCouplingUMeshCellIterator(this);
400 * Entry point for iteration over cells groups geo types per geotypes. Warning the returned cell iterator should be deallocated.
401 * If \a this is not so that that cells are grouped by geo types this method will throw an exception.
402 * In this case MEDCouplingUMesh::sortCellsInMEDFileFrmt or MEDCouplingUMesh::rearrange2ConsecutiveCellTypes methods for example can be called before invoking this method.
403 * Useful for python users.
405 MEDCouplingUMeshCellByTypeEntry *MEDCouplingUMesh::cellsByType() throw(INTERP_KERNEL::Exception)
407 if(!checkConsecutiveCellTypes())
408 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::cellsByType : this mesh is not sorted by type !");
409 return new MEDCouplingUMeshCellByTypeEntry(this);
413 * Returns a set of all cell types available in \a this mesh.
414 * \return std::set<INTERP_KERNEL::NormalizedCellType> - the set of cell types.
415 * \warning this method does not throw any exception even if \a this is not defined.
417 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getAllGeoTypes() const
423 * This method is a method that compares \a this and \a other.
424 * This method compares \b all attributes, even names and component names.
426 bool MEDCouplingUMesh::isEqualIfNotWhy(const MEDCouplingMesh *other, double prec, std::string& reason) const throw(INTERP_KERNEL::Exception)
429 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isEqualIfNotWhy : input other pointer is null !");
430 std::ostringstream oss; oss.precision(15);
431 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
434 reason="mesh given in input is not castable in MEDCouplingUMesh !";
437 if(!MEDCouplingPointSet::isEqualIfNotWhy(other,prec,reason))
439 if(_mesh_dim!=otherC->_mesh_dim)
441 oss << "umesh dimension mismatch : this mesh dimension=" << _mesh_dim << " other mesh dimension=" << otherC->_mesh_dim;
445 if(_types!=otherC->_types)
447 oss << "umesh geometric type mismatch :\nThis geometric types are :";
448 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
449 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
450 oss << "\nOther geometric types are :";
451 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=otherC->_types.begin();iter!=otherC->_types.end();iter++)
452 { const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter); oss << cm.getRepr() << ", "; }
456 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
457 if(_nodal_connec==0 || otherC->_nodal_connec==0)
459 reason="Only one UMesh between the two this and other has its nodal connectivity DataArrayInt defined !";
462 if(_nodal_connec!=otherC->_nodal_connec)
463 if(!_nodal_connec->isEqualIfNotWhy(*otherC->_nodal_connec,reason))
465 reason.insert(0,"Nodal connectivity DataArrayInt differ : ");
468 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
469 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
471 reason="Only one UMesh between the two this and other has its nodal connectivity index DataArrayInt defined !";
474 if(_nodal_connec_index!=otherC->_nodal_connec_index)
475 if(!_nodal_connec_index->isEqualIfNotWhy(*otherC->_nodal_connec_index,reason))
477 reason.insert(0,"Nodal connectivity index DataArrayInt differ : ");
484 * Checks if data arrays of this mesh (node coordinates, nodal
485 * connectivity of cells, etc) of two meshes are same. Textual data like name etc. are
487 * \param [in] other - the mesh to compare with.
488 * \param [in] prec - precision value used to compare node coordinates.
489 * \return bool - \a true if the two meshes are same.
491 bool MEDCouplingUMesh::isEqualWithoutConsideringStr(const MEDCouplingMesh *other, double prec) const
493 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
496 if(!MEDCouplingPointSet::isEqualWithoutConsideringStr(other,prec))
498 if(_mesh_dim!=otherC->_mesh_dim)
500 if(_types!=otherC->_types)
502 if(_nodal_connec!=0 || otherC->_nodal_connec!=0)
503 if(_nodal_connec==0 || otherC->_nodal_connec==0)
505 if(_nodal_connec!=otherC->_nodal_connec)
506 if(!_nodal_connec->isEqualWithoutConsideringStr(*otherC->_nodal_connec))
508 if(_nodal_connec_index!=0 || otherC->_nodal_connec_index!=0)
509 if(_nodal_connec_index==0 || otherC->_nodal_connec_index==0)
511 if(_nodal_connec_index!=otherC->_nodal_connec_index)
512 if(!_nodal_connec_index->isEqualWithoutConsideringStr(*otherC->_nodal_connec_index))
518 * Checks if \a this and \a other meshes are geometrically equivalent with high
519 * probability, else an exception is thrown. The meshes are considered equivalent if
520 * (1) meshes contain the same number of nodes and the same number of elements of the
521 * same types (2) three cells of the two meshes (first, last and middle) are based
522 * on coincident nodes (with a specified precision).
523 * \param [in] other - the mesh to compare with.
524 * \param [in] prec - the precision used to compare nodes of the two meshes.
525 * \throw If the two meshes do not match.
527 void MEDCouplingUMesh::checkFastEquivalWith(const MEDCouplingMesh *other, double prec) const throw(INTERP_KERNEL::Exception)
529 MEDCouplingPointSet::checkFastEquivalWith(other,prec);
530 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
532 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkFastEquivalWith : Two meshes are not not unstructured !");
536 * Returns the reverse nodal connectivity. The reverse nodal connectivity enumerates
537 * cells each node belongs to.
538 * \warning For speed reasons, this method does not check if node ids in the nodal
539 * connectivity correspond to the size of node coordinates array.
540 * \param [in,out] revNodal - an array holding ids of cells sharing each node.
541 * \param [in,out] revNodalIndx - an array, of length \a this->getNumberOfNodes() + 1,
542 * dividing cell ids in \a revNodal into groups each referring to one
543 * node. Its every element (except the last one) is an index pointing to the
544 * first id of a group of cells. For example cells sharing the node #1 are
545 * described by following range of indices:
546 * [ \a revNodalIndx[1], \a revNodalIndx[2] ) and the cell ids are
547 * \a revNodal[ \a revNodalIndx[1] ], \a revNodal[ \a revNodalIndx[1] + 1], ...
548 * Number of cells sharing the *i*-th node is
549 * \a revNodalIndx[ *i*+1 ] - \a revNodalIndx[ *i* ].
550 * \throw If the coordinates array is not set.
551 * \throw If the nodal connectivity of cells is not defined.
553 * \ref cpp_mcumesh_getReverseNodalConnectivity "Here is a C++ example".<br>
554 * \ref py_mcumesh_getReverseNodalConnectivity "Here is a Python example".
556 void MEDCouplingUMesh::getReverseNodalConnectivity(DataArrayInt *revNodal, DataArrayInt *revNodalIndx) const throw(INTERP_KERNEL::Exception)
559 int nbOfNodes=getNumberOfNodes();
560 int *revNodalIndxPtr=(int *)malloc((nbOfNodes+1)*sizeof(int));
561 revNodalIndx->useArray(revNodalIndxPtr,true,C_DEALLOC,nbOfNodes+1,1);
562 std::fill(revNodalIndxPtr,revNodalIndxPtr+nbOfNodes+1,0);
563 const int *conn=_nodal_connec->getConstPointer();
564 const int *connIndex=_nodal_connec_index->getConstPointer();
565 int nbOfCells=getNumberOfCells();
566 int nbOfEltsInRevNodal=0;
567 for(int eltId=0;eltId<nbOfCells;eltId++)
569 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
570 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
571 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
572 if(*iter>=0)//for polyhedrons
574 nbOfEltsInRevNodal++;
575 revNodalIndxPtr[(*iter)+1]++;
578 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
579 int *revNodalPtr=(int *)malloc((nbOfEltsInRevNodal)*sizeof(int));
580 revNodal->useArray(revNodalPtr,true,C_DEALLOC,nbOfEltsInRevNodal,1);
581 std::fill(revNodalPtr,revNodalPtr+nbOfEltsInRevNodal,-1);
582 for(int eltId=0;eltId<nbOfCells;eltId++)
584 const int *strtNdlConnOfCurCell=conn+connIndex[eltId]+1;
585 const int *endNdlConnOfCurCell=conn+connIndex[eltId+1];
586 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
587 if(*iter>=0)//for polyhedrons
588 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
594 int MEDCouplingFastNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
599 int MEDCouplingOrientationSensitiveNbrer(int id, unsigned nb, const INTERP_KERNEL::CellModel& cm, bool compute, const int *conn1, const int *conn2)
605 if(cm.getOrientationStatus(nb,conn1,conn2))
612 class MinusOneSonsGenerator
615 MinusOneSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
616 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
617 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity2(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
618 static const int DELTA=1;
620 const INTERP_KERNEL::CellModel& _cm;
623 class MinusOneSonsGeneratorBiQuadratic
626 MinusOneSonsGeneratorBiQuadratic(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
627 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfSons2(conn,lgth); }
628 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonCellNodalConnectivity4(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
629 static const int DELTA=1;
631 const INTERP_KERNEL::CellModel& _cm;
634 class MinusTwoSonsGenerator
637 MinusTwoSonsGenerator(const INTERP_KERNEL::CellModel& cm):_cm(cm) { }
638 unsigned getNumberOfSons2(const int *conn, int lgth) const { return _cm.getNumberOfEdgesIn3D(conn,lgth); }
639 unsigned fillSonCellNodalConnectivity2(int sonId, const int *nodalConn, int lgth, int *sonNodalConn, INTERP_KERNEL::NormalizedCellType& typeOfSon) const { return _cm.fillSonEdgesNodalConnectivity3D(sonId,nodalConn,lgth,sonNodalConn,typeOfSon); }
640 static const int DELTA=2;
642 const INTERP_KERNEL::CellModel& _cm;
648 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
649 * this->getMeshDimension(), that bound cells of \a this mesh. In addition arrays
650 * describing correspondence between cells of \a this and the result meshes are
651 * returned. The arrays \a desc and \a descIndx describe the descending connectivity,
652 * i.e. enumerate cells of the result mesh bounding each cell of \a this mesh. The
653 * arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
654 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
655 * \warning For speed reasons, this method does not check if node ids in the nodal
656 * connectivity correspond to the size of node coordinates array.
657 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
658 * to write this mesh to the MED file, its cells must be sorted using
659 * sortCellsInMEDFileFrmt().
660 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
661 * each cell of \a this mesh.
662 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
663 * dividing cell ids in \a desc into groups each referring to one
664 * cell of \a this mesh. Its every element (except the last one) is an index
665 * pointing to the first id of a group of cells. For example cells of the
666 * result mesh bounding the cell #1 of \a this mesh are described by following
668 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
669 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
670 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
671 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
672 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
673 * by each cell of the result mesh.
674 * \param [in,out] revDescIndx - the array, of length one more than number of cells
675 * in the result mesh,
676 * dividing cell ids in \a revDesc into groups each referring to one
677 * cell of the result mesh the same way as \a descIndx divides \a desc.
678 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. The caller is to
679 * delete this mesh using decrRef() as it is no more needed.
680 * \throw If the coordinates array is not set.
681 * \throw If the nodal connectivity of cells is node defined.
682 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
683 * revDescIndx == NULL.
685 * \ref cpp_mcumesh_buildDescendingConnectivity "Here is a C++ example".<br>
686 * \ref py_mcumesh_buildDescendingConnectivity "Here is a Python example".
687 * \sa buildDescendingConnectivity2()
689 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
691 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
695 * \a this has to have a mesh dimension equal to 3. If it is not the case an INTERP_KERNEL::Exception will be thrown.
696 * This behaves exactly as MEDCouplingUMesh::buildDescendingConnectivity does except that this method compute directly the transition from mesh dimension 3 to sub edges (dimension 1)
697 * in one shot. That is to say that this method is equivalent to 2 successive calls to MEDCouplingUMesh::buildDescendingConnectivity.
698 * This method returns 4 arrays and a mesh as MEDCouplingUMesh::buildDescendingConnectivity does.
699 * \sa MEDCouplingUMesh::buildDescendingConnectivity
701 MEDCouplingUMesh *MEDCouplingUMesh::explode3DMeshTo1D(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
704 if(getMeshDimension()!=3)
705 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::explode3DMeshTo1D : This has to have a mesh dimension to 3 !");
706 return buildDescendingConnectivityGen<MinusTwoSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingFastNbrer);
710 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
711 * this->getMeshDimension(), that bound cells of \a this mesh. In
712 * addition arrays describing correspondence between cells of \a this and the result
713 * meshes are returned. The arrays \a desc and \a descIndx describe the descending
714 * connectivity, i.e. enumerate cells of the result mesh bounding each cell of \a this
715 * mesh. This method differs from buildDescendingConnectivity() in that apart
716 * from cell ids, \a desc returns mutual orientation of cells in \a this and the
717 * result meshes. So a positive id means that order of nodes in corresponding cells
718 * of two meshes is same, and a negative id means a reverse order of nodes. Since a
719 * cell with id #0 can't be negative, the array \a desc returns ids in FORTRAN mode,
720 * i.e. cell ids are one-based.
721 * Arrays \a revDesc and \a revDescIndx describe the reverse descending connectivity,
722 * i.e. enumerate cells of \a this mesh bounded by each cell of the result mesh.
723 * \warning For speed reasons, this method does not check if node ids in the nodal
724 * connectivity correspond to the size of node coordinates array.
725 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
726 * to write this mesh to the MED file, its cells must be sorted using
727 * sortCellsInMEDFileFrmt().
728 * \param [in,out] desc - the array containing cell ids of the result mesh bounding
729 * each cell of \a this mesh.
730 * \param [in,out] descIndx - the array, of length \a this->getNumberOfCells() + 1,
731 * dividing cell ids in \a desc into groups each referring to one
732 * cell of \a this mesh. Its every element (except the last one) is an index
733 * pointing to the first id of a group of cells. For example cells of the
734 * result mesh bounding the cell #1 of \a this mesh are described by following
736 * [ \a descIndx[1], \a descIndx[2] ) and the cell ids are
737 * \a desc[ \a descIndx[1] ], \a desc[ \a descIndx[1] + 1], ...
738 * Number of cells of the result mesh sharing the *i*-th cell of \a this mesh is
739 * \a descIndx[ *i*+1 ] - \a descIndx[ *i* ].
740 * \param [in,out] revDesc - the array containing cell ids of \a this mesh bounded
741 * by each cell of the result mesh.
742 * \param [in,out] revDescIndx - the array, of length one more than number of cells
743 * in the result mesh,
744 * dividing cell ids in \a revDesc into groups each referring to one
745 * cell of the result mesh the same way as \a descIndx divides \a desc.
746 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This result mesh
747 * shares the node coordinates array with \a this mesh. The caller is to
748 * delete this mesh using decrRef() as it is no more needed.
749 * \throw If the coordinates array is not set.
750 * \throw If the nodal connectivity of cells is node defined.
751 * \throw If \a desc == NULL || \a descIndx == NULL || \a revDesc == NULL || \a
752 * revDescIndx == NULL.
754 * \ref cpp_mcumesh_buildDescendingConnectivity2 "Here is a C++ example".<br>
755 * \ref py_mcumesh_buildDescendingConnectivity2 "Here is a Python example".
756 * \sa buildDescendingConnectivity()
758 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivity2(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx) const throw(INTERP_KERNEL::Exception)
760 return buildDescendingConnectivityGen<MinusOneSonsGenerator>(desc,descIndx,revDesc,revDescIndx,MEDCouplingOrientationSensitiveNbrer);
764 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
765 * For speed reasons no check of this will be done. This method calls MEDCouplingUMesh::buildDescendingConnectivity to compute the result.
766 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
767 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
769 * \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
770 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
771 * \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.
773 void MEDCouplingUMesh::computeNeighborsOfCells(DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) const throw(INTERP_KERNEL::Exception)
775 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
776 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
777 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
778 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
779 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
781 ComputeNeighborsOfCellsAdv(desc,descIndx,revDesc,revDescIndx,neighbors,neighborsIndx);
785 * This method is called by MEDCouplingUMesh::computeNeighborsOfCells. This methods performs the algorithm of MEDCouplingUMesh::computeNeighborsOfCells.
786 * 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,
787 * excluding a set of meshdim-1 cells in input descending connectivity.
788 * Typically \b desc, \b descIndx, \b revDesc and \b revDescIndx input params are the result of MEDCouplingUMesh::buildDescendingConnectivity.
789 * This method lists cell by cell in \b this which are its neighbors. To compute the result only connectivities are considered.
790 * The a cell with id 'cellId' its neighbors are neighbors[neighborsIndx[cellId]:neighborsIndx[cellId+1]].
792 * \param [in] desc descending connectivity array.
793 * \param [in] descIndx descending connectivity index array used to walk through \b desc.
794 * \param [in] revDesc reverse descending connectivity array.
795 * \param [in] revDescIndx reverse descending connectivity index array used to walk through \b revDesc.
796 * \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
797 * parameter allows to select the right part in this array. The number of tuples is equal to the last values in \b neighborsIndx.
798 * \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.
800 void MEDCouplingUMesh::ComputeNeighborsOfCellsAdv(const DataArrayInt *desc, const DataArrayInt *descIndx, const DataArrayInt *revDesc, const DataArrayInt *revDescIndx,
801 DataArrayInt *&neighbors, DataArrayInt *&neighborsIndx) throw(INTERP_KERNEL::Exception)
803 if(!desc || !descIndx || !revDesc || !revDescIndx)
804 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeNeighborsOfCellsAdv some input array is empty !");
805 const int *descPtr=desc->getConstPointer();
806 const int *descIPtr=descIndx->getConstPointer();
807 const int *revDescPtr=revDesc->getConstPointer();
808 const int *revDescIPtr=revDescIndx->getConstPointer();
810 int nbCells=descIndx->getNumberOfTuples()-1;
811 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out0=DataArrayInt::New();
812 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> out1=DataArrayInt::New(); out1->alloc(nbCells+1,1);
813 int *out1Ptr=out1->getPointer();
815 out0->reserve(desc->getNumberOfTuples());
816 for(int i=0;i<nbCells;i++,descIPtr++,out1Ptr++)
818 for(const int *w1=descPtr+descIPtr[0];w1!=descPtr+descIPtr[1];w1++)
820 std::set<int> s(revDescPtr+revDescIPtr[*w1],revDescPtr+revDescIPtr[(*w1)+1]);
822 out0->insertAtTheEnd(s.begin(),s.end());
824 *out1Ptr=out0->getNumberOfTuples();
826 neighbors=out0.retn();
827 neighborsIndx=out1.retn();
833 * \b WARNING this method do the assumption that connectivity lies on the coordinates set.
834 * For speed reasons no check of this will be done.
836 template<class SonsGenerator>
837 MEDCouplingUMesh *MEDCouplingUMesh::buildDescendingConnectivityGen(DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *revDesc, DataArrayInt *revDescIndx, DimM1DescNbrer nbrer) const throw(INTERP_KERNEL::Exception)
839 if(!desc || !descIndx || !revDesc || !revDescIndx)
840 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildDescendingConnectivityGen : present of a null pointer in input !");
841 checkConnectivityFullyDefined();
842 int nbOfCells=getNumberOfCells();
843 int nbOfNodes=getNumberOfNodes();
844 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodalIndx=DataArrayInt::New(); revNodalIndx->alloc(nbOfNodes+1,1); revNodalIndx->fillWithZero();
845 int *revNodalIndxPtr=revNodalIndx->getPointer();
846 const int *conn=_nodal_connec->getConstPointer();
847 const int *connIndex=_nodal_connec_index->getConstPointer();
848 std::string name="Mesh constituent of "; name+=getName();
849 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(name.c_str(),getMeshDimension()-SonsGenerator::DELTA);
850 ret->setCoords(getCoords());
851 ret->allocateCells(2*nbOfCells);
852 descIndx->alloc(nbOfCells+1,1);
853 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc2(DataArrayInt::New()); revDesc2->reserve(2*nbOfCells);
854 int *descIndxPtr=descIndx->getPointer(); *descIndxPtr++=0;
855 for(int eltId=0;eltId<nbOfCells;eltId++,descIndxPtr++)
857 int pos=connIndex[eltId];
858 int posP1=connIndex[eltId+1];
859 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[pos]);
860 SonsGenerator sg(cm);
861 unsigned nbOfSons=sg.getNumberOfSons2(conn+pos+1,posP1-pos-1);
862 INTERP_KERNEL::AutoPtr<int> tmp=new int[posP1-pos];
863 for(unsigned i=0;i<nbOfSons;i++)
865 INTERP_KERNEL::NormalizedCellType cmsId;
866 unsigned nbOfNodesSon=sg.fillSonCellNodalConnectivity2(i,conn+pos+1,posP1-pos-1,tmp,cmsId);
867 for(unsigned k=0;k<nbOfNodesSon;k++)
869 revNodalIndxPtr[tmp[k]+1]++;
870 ret->insertNextCell(cmsId,nbOfNodesSon,tmp);
871 revDesc2->pushBackSilent(eltId);
873 descIndxPtr[0]=descIndxPtr[-1]+(int)nbOfSons;
875 int nbOfCellsM1=ret->getNumberOfCells();
876 std::transform(revNodalIndxPtr+1,revNodalIndxPtr+nbOfNodes+1,revNodalIndxPtr,revNodalIndxPtr+1,std::plus<int>());
877 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(); revNodal->alloc(revNodalIndx->back(),1);
878 std::fill(revNodal->getPointer(),revNodal->getPointer()+revNodalIndx->back(),-1);
879 int *revNodalPtr=revNodal->getPointer();
880 const int *connM1=ret->getNodalConnectivity()->getConstPointer();
881 const int *connIndexM1=ret->getNodalConnectivityIndex()->getConstPointer();
882 for(int eltId=0;eltId<nbOfCellsM1;eltId++)
884 const int *strtNdlConnOfCurCell=connM1+connIndexM1[eltId]+1;
885 const int *endNdlConnOfCurCell=connM1+connIndexM1[eltId+1];
886 for(const int *iter=strtNdlConnOfCurCell;iter!=endNdlConnOfCurCell;iter++)
887 if(*iter>=0)//for polyhedrons
888 *std::find_if(revNodalPtr+revNodalIndxPtr[*iter],revNodalPtr+revNodalIndxPtr[*iter+1],std::bind2nd(std::equal_to<int>(),-1))=eltId;
891 DataArrayInt *commonCells=0,*commonCellsI=0;
892 FindCommonCellsAlg(3,0,ret->getNodalConnectivity(),ret->getNodalConnectivityIndex(),revNodal,revNodalIndx,commonCells,commonCellsI);
893 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
894 const int *commonCellsPtr(commonCells->getConstPointer()),*commonCellsIPtr(commonCellsI->getConstPointer());
895 int newNbOfCellsM1=-1;
896 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nM1=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(nbOfCellsM1,commonCells->begin(),
897 commonCellsI->begin(),commonCellsI->end(),newNbOfCellsM1);
898 std::vector<bool> isImpacted(nbOfCellsM1,false);
899 for(const int *work=commonCellsI->begin();work!=commonCellsI->end()-1;work++)
900 for(int work2=work[0];work2!=work[1];work2++)
901 isImpacted[commonCellsPtr[work2]]=true;
902 const int *o2nM1Ptr=o2nM1->getConstPointer();
903 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2oM1=o2nM1->invertArrayO2N2N2OBis(newNbOfCellsM1);
904 const int *n2oM1Ptr=n2oM1->getConstPointer();
905 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret2=static_cast<MEDCouplingUMesh *>(ret->buildPartOfMySelf(n2oM1->begin(),n2oM1->end(),true));
906 ret2->copyTinyInfoFrom(this);
907 desc->alloc(descIndx->back(),1);
908 int *descPtr=desc->getPointer();
909 const INTERP_KERNEL::CellModel& cmsDft=INTERP_KERNEL::CellModel::GetCellModel(INTERP_KERNEL::NORM_POINT1);
910 for(int i=0;i<nbOfCellsM1;i++,descPtr++)
913 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
916 if(i!=n2oM1Ptr[o2nM1Ptr[i]])
918 const INTERP_KERNEL::CellModel& cms=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connM1[connIndexM1[i]]);
919 *descPtr=nbrer(o2nM1Ptr[i],connIndexM1[i+1]-connIndexM1[i]-1,cms,true,connM1+connIndexM1[n2oM1Ptr[o2nM1Ptr[i]]]+1,connM1+connIndexM1[i]+1);
922 *descPtr=nbrer(o2nM1Ptr[i],0,cmsDft,false,0,0);
925 revDesc->reserve(newNbOfCellsM1);
926 revDescIndx->alloc(newNbOfCellsM1+1,1);
927 int *revDescIndxPtr=revDescIndx->getPointer(); *revDescIndxPtr++=0;
928 const int *revDesc2Ptr=revDesc2->getConstPointer();
929 for(int i=0;i<newNbOfCellsM1;i++,revDescIndxPtr++)
931 int oldCellIdM1=n2oM1Ptr[i];
932 if(!isImpacted[oldCellIdM1])
934 revDesc->pushBackSilent(revDesc2Ptr[oldCellIdM1]);
935 revDescIndxPtr[0]=revDescIndxPtr[-1]+1;
939 for(int j=commonCellsIPtr[0];j<commonCellsIPtr[1];j++)
940 revDesc->pushBackSilent(revDesc2Ptr[commonCellsPtr[j]]);
941 revDescIndxPtr[0]=revDescIndxPtr[-1]+commonCellsIPtr[1]-commonCellsIPtr[0];
949 struct MEDCouplingAccVisit
951 MEDCouplingAccVisit():_new_nb_of_nodes(0) { }
952 int operator()(int val) { if(val!=-1) return _new_nb_of_nodes++; else return -1; }
953 int _new_nb_of_nodes;
959 * Converts specified cells to either polygons (if \a this is a 2D mesh) or
960 * polyhedrons (if \a this is a 3D mesh). The cells to convert are specified by an
961 * array of cell ids. Pay attention that after conversion all algorithms work slower
962 * with \a this mesh than before conversion. <br> If an exception is thrown during the
963 * conversion due presence of invalid ids in the array of cells to convert, as a
964 * result \a this mesh contains some already converted elements. In this case the 2D
965 * mesh remains valid but 3D mesh becomes \b inconsistent!
966 * \warning This method can significantly modify the order of geometric types in \a this,
967 * hence, to write this mesh to the MED file, its cells must be sorted using
968 * sortCellsInMEDFileFrmt().
969 * \param [in] cellIdsToConvertBg - the array holding ids of cells to convert.
970 * \param [in] cellIdsToConvertEnd - a pointer to the last-plus-one-th element of \a
971 * cellIdsToConvertBg.
972 * \throw If the coordinates array is not set.
973 * \throw If the nodal connectivity of cells is node defined.
974 * \throw If dimension of \a this mesh is not either 2 or 3.
976 * \ref cpp_mcumesh_convertToPolyTypes "Here is a C++ example".<br>
977 * \ref py_mcumesh_convertToPolyTypes "Here is a Python example".
979 void MEDCouplingUMesh::convertToPolyTypes(const int *cellIdsToConvertBg, const int *cellIdsToConvertEnd)
982 int dim=getMeshDimension();
984 throw INTERP_KERNEL::Exception("Invalid mesh dimension : must be 2 or 3 !");
985 int nbOfCells=getNumberOfCells();
988 const int *connIndex=_nodal_connec_index->getConstPointer();
989 int *conn=_nodal_connec->getPointer();
990 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
992 if(*iter>=0 && *iter<nbOfCells)
994 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*iter]]);
995 if(!cm.isQuadratic())
996 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_POLYGON;
998 conn[connIndex[*iter]]=INTERP_KERNEL::NORM_QPOLYG;
1002 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1003 oss << " in range [0," << nbOfCells << ") !";
1004 throw INTERP_KERNEL::Exception(oss.str().c_str());
1010 int *connIndex=_nodal_connec_index->getPointer();
1011 int connIndexLgth=_nodal_connec_index->getNbOfElems();
1012 const int *connOld=_nodal_connec->getConstPointer();
1013 int connOldLgth=_nodal_connec->getNbOfElems();
1014 std::vector<int> connNew(connOld,connOld+connOldLgth);
1015 for(const int *iter=cellIdsToConvertBg;iter!=cellIdsToConvertEnd;iter++)
1017 if(*iter>=0 && *iter<nbOfCells)
1019 int pos=connIndex[*iter];
1020 int posP1=connIndex[(*iter)+1];
1021 int lgthOld=posP1-pos-1;
1022 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)connNew[pos]);
1023 connNew[pos]=INTERP_KERNEL::NORM_POLYHED;
1024 unsigned nbOfFaces=cm.getNumberOfSons2(&connNew[pos+1],lgthOld);
1025 int *tmp=new int[nbOfFaces*lgthOld];
1027 for(int j=0;j<(int)nbOfFaces;j++)
1029 INTERP_KERNEL::NormalizedCellType type;
1030 unsigned offset=cm.fillSonCellNodalConnectivity2(j,&connNew[pos+1],lgthOld,work,type);
1034 std::size_t newLgth=std::distance(tmp,work)-1;
1035 std::size_t delta=newLgth-lgthOld;
1036 std::transform(connIndex+(*iter)+1,connIndex+connIndexLgth,connIndex+(*iter)+1,std::bind2nd(std::plus<int>(),delta));
1037 connNew.insert(connNew.begin()+posP1,tmp+lgthOld,tmp+newLgth);
1038 std::copy(tmp,tmp+lgthOld,connNew.begin()+pos+1);
1043 std::ostringstream oss; oss << "MEDCouplingUMesh::convertToPolyTypes : On rank #" << std::distance(cellIdsToConvertBg,iter) << " value is " << *iter << " which is not";
1044 oss << " in range [0," << nbOfCells << ") !";
1045 throw INTERP_KERNEL::Exception(oss.str().c_str());
1048 _nodal_connec->alloc((int)connNew.size(),1);
1049 int *newConnPtr=_nodal_connec->getPointer();
1050 std::copy(connNew.begin(),connNew.end(),newConnPtr);
1056 * Converts all cells to either polygons (if \a this is a 2D mesh) or
1057 * polyhedrons (if \a this is a 3D mesh).
1058 * \warning As this method is purely for user-friendliness and no optimization is
1059 * done to avoid construction of a useless vector, this method can be costly
1061 * \throw If the coordinates array is not set.
1062 * \throw If the nodal connectivity of cells is node defined.
1063 * \throw If dimension of \a this mesh is not either 2 or 3.
1065 void MEDCouplingUMesh::convertAllToPoly()
1067 int nbOfCells=getNumberOfCells();
1068 std::vector<int> cellIds(nbOfCells);
1069 for(int i=0;i<nbOfCells;i++)
1071 convertToPolyTypes(&cellIds[0],&cellIds[0]+cellIds.size());
1075 * Fixes nodal connectivity of invalid cells of type NORM_POLYHED. This method
1076 * expects that all NORM_POLYHED cells have connectivity similar to that of prismatic
1077 * volumes like NORM_HEXA8, NORM_PENTA6 etc., i.e. the first half of nodes describes a
1078 * base facet of the volume and the second half of nodes describes an opposite facet
1079 * having the same number of nodes as the base one. This method converts such
1080 * connectivity to a valid polyhedral format where connectivity of each facet is
1081 * explicitly described and connectivity of facets are separated by -1. If \a this mesh
1082 * contains a NORM_POLYHED cell with a valid connectivity, or an invalid connectivity is
1083 * not as expected, an exception is thrown and the mesh remains unchanged. Care of
1084 * a correct orientation of the first facet of a polyhedron, else orientation of a
1085 * corrected cell is reverse.<br>
1086 * This method is useful to build an extruded unstructured mesh with polyhedrons as
1087 * it releases the user from boring description of polyhedra connectivity in the valid
1089 * \throw If \a this->getMeshDimension() != 3.
1090 * \throw If \a this->getSpaceDimension() != 3.
1091 * \throw If the nodal connectivity of cells is not defined.
1092 * \throw If the coordinates array is not set.
1093 * \throw If \a this mesh contains polyhedrons with the valid connectivity.
1094 * \throw If \a this mesh contains polyhedrons with odd number of nodes.
1096 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
1097 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
1099 void MEDCouplingUMesh::convertExtrudedPolyhedra() throw(INTERP_KERNEL::Exception)
1101 checkFullyDefined();
1102 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1103 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertExtrudedPolyhedra works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
1104 int nbOfCells=getNumberOfCells();
1105 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newCi=DataArrayInt::New();
1106 newCi->alloc(nbOfCells+1,1);
1107 int *newci=newCi->getPointer();
1108 const int *ci=_nodal_connec_index->getConstPointer();
1109 const int *c=_nodal_connec->getConstPointer();
1111 for(int i=0;i<nbOfCells;i++)
1113 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1114 if(type==INTERP_KERNEL::NORM_POLYHED)
1116 if(std::count(c+ci[i]+1,c+ci[i+1],-1)!=0)
1118 std::ostringstream oss; oss << "MEDCouplingUMesh::convertExtrudedPolyhedra : cell # " << i << " is a polhedron BUT it has NOT exactly 1 face !";
1119 throw INTERP_KERNEL::Exception(oss.str().c_str());
1121 std::size_t n2=std::distance(c+ci[i]+1,c+ci[i+1]);
1124 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 !";
1125 throw INTERP_KERNEL::Exception(oss.str().c_str());
1128 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)
1131 newci[i+1]=(ci[i+1]-ci[i])+newci[i];
1133 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newC=DataArrayInt::New();
1134 newC->alloc(newci[nbOfCells],1);
1135 int *newc=newC->getPointer();
1136 for(int i=0;i<nbOfCells;i++)
1138 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[i]];
1139 if(type==INTERP_KERNEL::NORM_POLYHED)
1141 std::size_t n1=std::distance(c+ci[i]+1,c+ci[i+1])/2;
1142 newc=std::copy(c+ci[i],c+ci[i]+n1+1,newc);
1144 for(std::size_t j=0;j<n1;j++)
1146 newc[j]=c[ci[i]+1+n1+(n1-j)%n1];
1148 newc[n1+5*j+1]=c[ci[i]+1+j];
1149 newc[n1+5*j+2]=c[ci[i]+1+j+n1];
1150 newc[n1+5*j+3]=c[ci[i]+1+(j+1)%n1+n1];
1151 newc[n1+5*j+4]=c[ci[i]+1+(j+1)%n1];
1156 newc=std::copy(c+ci[i],c+ci[i+1],newc);
1158 _nodal_connec_index->decrRef(); _nodal_connec_index=newCi.retn();
1159 _nodal_connec->decrRef(); _nodal_connec=newC.retn();
1164 * Converts all polygons (if \a this is a 2D mesh) or polyhedrons (if \a this is a 3D
1165 * mesh) to cells of classical types. This method is opposite to convertToPolyTypes().
1166 * \warning Cells of the result mesh are \b not sorted by geometric type, hence,
1167 * to write this mesh to the MED file, its cells must be sorted using
1168 * sortCellsInMEDFileFrmt().
1169 * \return \c true if at least one cell has been converted, \c false else. In the
1170 * last case the nodal connectivity remains unchanged.
1171 * \throw If the coordinates array is not set.
1172 * \throw If the nodal connectivity of cells is not defined.
1173 * \throw If \a this->getMeshDimension() < 0.
1175 bool MEDCouplingUMesh::unPolyze()
1177 checkFullyDefined();
1178 int mdim=getMeshDimension();
1180 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::unPolyze works on umeshes with meshdim equals to 0, 1 2 or 3 !");
1183 int nbOfCells=getNumberOfCells();
1186 int initMeshLgth=getMeshLength();
1187 int *conn=_nodal_connec->getPointer();
1188 int *index=_nodal_connec_index->getPointer();
1193 for(int i=0;i<nbOfCells;i++)
1195 lgthOfCurCell=index[i+1]-posOfCurCell;
1196 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
1197 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
1198 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::NORM_ERROR;
1202 switch(cm.getDimension())
1206 INTERP_KERNEL::AutoPtr<int> tmp=new int[lgthOfCurCell-1];
1207 std::copy(conn+posOfCurCell+1,conn+posOfCurCell+lgthOfCurCell,(int *)tmp);
1208 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly2D(cm.isQuadratic(),tmp,lgthOfCurCell-1,conn+newPos+1,newLgth);
1213 int nbOfFaces,lgthOfPolyhConn;
1214 INTERP_KERNEL::AutoPtr<int> zipFullReprOfPolyh=INTERP_KERNEL::CellSimplify::getFullPolyh3DCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,nbOfFaces,lgthOfPolyhConn);
1215 newType=INTERP_KERNEL::CellSimplify::tryToUnPoly3D(zipFullReprOfPolyh,nbOfFaces,lgthOfPolyhConn,conn+newPos+1,newLgth);
1220 newType=(lgthOfCurCell==3)?INTERP_KERNEL::NORM_SEG2:INTERP_KERNEL::NORM_POLYL;
1224 ret=ret || (newType!=type);
1225 conn[newPos]=newType;
1227 posOfCurCell=index[i+1];
1232 std::copy(conn+posOfCurCell,conn+posOfCurCell+lgthOfCurCell,conn+newPos);
1233 newPos+=lgthOfCurCell;
1234 posOfCurCell+=lgthOfCurCell;
1238 if(newPos!=initMeshLgth)
1239 _nodal_connec->reAlloc(newPos);
1246 * This method expects that spaceDimension is equal to 3 and meshDimension equal to 3.
1247 * This method performs operation only on polyhedrons in \b this. If no polyhedrons exists in \b this, \b this remains unchanged.
1248 * This method allows to merge if any coplanar 3DSurf cells that may appear in some polyhedrons cells.
1250 * \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
1253 void MEDCouplingUMesh::simplifyPolyhedra(double eps) throw(INTERP_KERNEL::Exception)
1255 checkFullyDefined();
1256 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
1257 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplifyPolyhedra : works on meshdimension 3 and spaceDimension 3 !");
1258 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=getCoords()->deepCpy();
1259 coords->recenterForMaxPrecision(eps);
1261 int nbOfCells=getNumberOfCells();
1262 const int *conn=_nodal_connec->getConstPointer();
1263 const int *index=_nodal_connec_index->getConstPointer();
1264 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connINew=DataArrayInt::New();
1265 connINew->alloc(nbOfCells+1,1);
1266 int *connINewPtr=connINew->getPointer(); *connINewPtr++=0;
1267 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connNew=DataArrayInt::New(); connNew->alloc(0,1);
1269 for(int i=0;i<nbOfCells;i++,connINewPtr++)
1271 if(conn[index[i]]==(int)INTERP_KERNEL::NORM_POLYHED)
1273 SimplifyPolyhedronCell(eps,coords,conn+index[i],conn+index[i+1],connNew);
1277 connNew->insertAtTheEnd(conn+index[i],conn+index[i+1]);
1278 *connINewPtr=connNew->getNumberOfTuples();
1281 setConnectivity(connNew,connINew,false);
1285 * This method returns all node ids used in \b this. The data array returned has to be dealt by the caller.
1286 * The returned node ids are sortes ascendingly. This method is closed to MEDCouplingUMesh::getNodeIdsInUse except
1287 * the format of returned DataArrayInt instance.
1289 * \return a newly allocated DataArrayInt sorted ascendingly of fetched node ids.
1290 * \sa MEDCouplingUMesh::getNodeIdsInUse
1292 DataArrayInt *MEDCouplingUMesh::computeFetchedNodeIds() const throw(INTERP_KERNEL::Exception)
1294 checkConnectivityFullyDefined();
1295 int nbOfCells=getNumberOfCells();
1296 const int *connIndex=_nodal_connec_index->getConstPointer();
1297 const int *conn=_nodal_connec->getConstPointer();
1298 const int *maxEltPt=std::max_element(_nodal_connec->begin(),_nodal_connec->end());
1299 int maxElt=maxEltPt==_nodal_connec->end()?0:std::abs(*maxEltPt)+1;
1300 std::vector<bool> retS(maxElt,false);
1301 for(int i=0;i<nbOfCells;i++)
1302 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1306 for(int i=0;i<maxElt;i++)
1309 DataArrayInt *ret=DataArrayInt::New();
1311 int *retPtr=ret->getPointer();
1312 for(int i=0;i<maxElt;i++)
1319 * \param [in,out] nodeIdsInUse an array of size typically equal to nbOfNodes.
1320 * \sa MEDCouplingUMesh::getNodeIdsInUse
1322 void MEDCouplingUMesh::computeNodeIdsAlg(std::vector<bool>& nodeIdsInUse) const throw(INTERP_KERNEL::Exception)
1324 int nbOfNodes=(int)nodeIdsInUse.size();
1325 int nbOfCells=getNumberOfCells();
1326 const int *connIndex=_nodal_connec_index->getConstPointer();
1327 const int *conn=_nodal_connec->getConstPointer();
1328 for(int i=0;i<nbOfCells;i++)
1329 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1332 if(conn[j]<nbOfNodes)
1333 nodeIdsInUse[conn[j]]=true;
1336 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1337 throw INTERP_KERNEL::Exception(oss.str().c_str());
1343 * Finds nodes not used in any cell and returns an array giving a new id to every node
1344 * by excluding the unused nodes, for which the array holds -1. The result array is
1345 * a mapping in "Old to New" mode.
1346 * \param [out] nbrOfNodesInUse - number of node ids present in the nodal connectivity.
1347 * \return DataArrayInt * - a new instance of DataArrayInt. Its length is \a
1348 * this->getNumberOfNodes(). It holds for each node of \a this mesh either -1
1349 * if the node is unused or a new id else. The caller is to delete this
1350 * array using decrRef() as it is no more needed.
1351 * \throw If the coordinates array is not set.
1352 * \throw If the nodal connectivity of cells is not defined.
1353 * \throw If the nodal connectivity includes an invalid id.
1355 * \ref cpp_mcumesh_getNodeIdsInUse "Here is a C++ example".<br>
1356 * \ref py_mcumesh_getNodeIdsInUse "Here is a Python example".
1357 * \sa computeNodeIdsAlg()
1359 DataArrayInt *MEDCouplingUMesh::getNodeIdsInUse(int& nbrOfNodesInUse) const throw(INTERP_KERNEL::Exception)
1362 int nbOfNodes=getNumberOfNodes();
1363 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1364 ret->alloc(nbOfNodes,1);
1365 int *traducer=ret->getPointer();
1366 std::fill(traducer,traducer+nbOfNodes,-1);
1367 int nbOfCells=getNumberOfCells();
1368 const int *connIndex=_nodal_connec_index->getConstPointer();
1369 const int *conn=_nodal_connec->getConstPointer();
1370 for(int i=0;i<nbOfCells;i++)
1371 for(int j=connIndex[i]+1;j<connIndex[i+1];j++)
1374 if(conn[j]<nbOfNodes)
1375 traducer[conn[j]]=1;
1378 std::ostringstream oss; oss << "MEDCouplingUMesh::getNodeIdsInUse : In cell #" << i << " presence of node id " << conn[j] << " not in [0," << nbOfNodes << ") !";
1379 throw INTERP_KERNEL::Exception(oss.str().c_str());
1382 nbrOfNodesInUse=(int)std::count(traducer,traducer+nbOfNodes,1);
1383 std::transform(traducer,traducer+nbOfNodes,traducer,MEDCouplingAccVisit());
1388 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1389 * For each cell in \b this the number of nodes constituting cell is computed.
1390 * For each polyhedron cell, the sum of the number of nodes of each face constituting polyhedron cell is returned.
1391 * So for pohyhedrons some nodes can be counted several times in the returned result.
1393 * \return a newly allocated array
1395 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1397 checkConnectivityFullyDefined();
1398 int nbOfCells=getNumberOfCells();
1399 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1400 ret->alloc(nbOfCells,1);
1401 int *retPtr=ret->getPointer();
1402 const int *conn=getNodalConnectivity()->getConstPointer();
1403 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1404 for(int i=0;i<nbOfCells;i++,retPtr++)
1406 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1407 *retPtr=connI[i+1]-connI[i]-1;
1409 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1415 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1416 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1418 * \return a newly allocated array
1420 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception)
1422 checkConnectivityFullyDefined();
1423 int nbOfCells=getNumberOfCells();
1424 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1425 ret->alloc(nbOfCells,1);
1426 int *retPtr=ret->getPointer();
1427 const int *conn=getNodalConnectivity()->getConstPointer();
1428 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1429 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1431 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1432 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1438 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1439 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1440 * array mean that the corresponding old node is no more used.
1441 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1442 * this->getNumberOfNodes() before call of this method. The caller is to
1443 * delete this array using decrRef() as it is no more needed.
1444 * \throw If the coordinates array is not set.
1445 * \throw If the nodal connectivity of cells is not defined.
1446 * \throw If the nodal connectivity includes an invalid id.
1448 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1449 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1451 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1453 return MEDCouplingPointSet::zipCoordsTraducer();
1457 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1458 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1460 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1465 return AreCellsEqual0(conn,connI,cell1,cell2);
1467 return AreCellsEqual1(conn,connI,cell1,cell2);
1469 return AreCellsEqual2(conn,connI,cell1,cell2);
1471 return AreCellsEqual3(conn,connI,cell1,cell2);
1473 return AreCellsEqual7(conn,connI,cell1,cell2);
1475 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1479 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1481 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1483 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1484 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1489 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1491 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1493 int sz=connI[cell1+1]-connI[cell1];
1494 if(sz==connI[cell2+1]-connI[cell2])
1496 if(conn[connI[cell1]]==conn[connI[cell2]])
1498 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1499 unsigned dim=cm.getDimension();
1505 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1506 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1507 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1508 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1509 return work!=tmp+sz1?1:0;
1512 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1515 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1522 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1524 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1526 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1528 if(conn[connI[cell1]]==conn[connI[cell2]])
1530 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1531 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1539 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1541 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1543 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1545 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1546 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1553 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1555 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1557 int sz=connI[cell1+1]-connI[cell1];
1558 if(sz==connI[cell2+1]-connI[cell2])
1560 if(conn[connI[cell1]]==conn[connI[cell2]])
1562 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1563 unsigned dim=cm.getDimension();
1569 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1570 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1571 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1572 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1577 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1578 std::reverse_iterator<int *> it2((int *)tmp);
1579 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1585 return work!=tmp+sz1?1:0;
1588 {//case of SEG2 and SEG3
1589 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1591 if(!cm.isQuadratic())
1593 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1594 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1595 if(std::equal(it1,it2,conn+connI[cell2]+1))
1601 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])
1608 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1615 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1616 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1617 * and result remains unchanged.
1618 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1619 * If in 'candidates' pool -1 value is considered as an empty value.
1620 * WARNING this method returns only ONE set of result !
1622 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1624 if(candidates.size()<1)
1627 std::vector<int>::const_iterator iter=candidates.begin();
1628 int start=(*iter++);
1629 for(;iter!=candidates.end();iter++)
1631 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1636 result->pushBackSilent(start);
1640 result->pushBackSilent(*iter);
1642 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1649 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1650 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1652 * \param [in] compType input specifying the technique used to compare cells each other.
1653 * - 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.
1654 * - 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)
1655 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1656 * - 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
1657 * can be used for users not sensitive to orientation of cell
1658 * \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.
1659 * \param [out] commonCells
1660 * \param [out] commonCellsI
1661 * \return the correspondance array old to new in a newly allocated array.
1664 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1666 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1667 getReverseNodalConnectivity(revNodal,revNodalI);
1668 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1671 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1672 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1674 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1675 int nbOfCells=nodalI->getNumberOfTuples()-1;
1676 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1677 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1678 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1679 std::vector<bool> isFetched(nbOfCells,false);
1682 for(int i=0;i<nbOfCells;i++)
1686 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1687 std::vector<int> v,v2;
1688 if(connOfNode!=connPtr+connIPtr[i+1])
1690 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1691 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1694 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1698 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1699 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1700 v2.resize(std::distance(v2.begin(),it));
1704 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1706 int pos=commonCellsI->back();
1707 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1708 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1709 isFetched[*it]=true;
1717 for(int i=startCellId;i<nbOfCells;i++)
1721 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1722 std::vector<int> v,v2;
1723 if(connOfNode!=connPtr+connIPtr[i+1])
1725 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1728 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1732 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1733 v2.resize(std::distance(v2.begin(),it));
1737 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1739 int pos=commonCellsI->back();
1740 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1741 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1742 isFetched[*it]=true;
1748 commonCellsArr=commonCells.retn();
1749 commonCellsIArr=commonCellsI.retn();
1753 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1754 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1755 * than \a other->getNumberOfCells() in the returned array means that there is no
1756 * corresponding cell in \a this mesh.
1757 * It is expected that \a this and \a other meshes share the same node coordinates
1758 * array, if it is not so an exception is thrown.
1759 * \param [in] other - the mesh to compare with.
1760 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1761 * valid values [0,1,2], see zipConnectivityTraducer().
1762 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1763 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1764 * values. The caller is to delete this array using
1765 * decrRef() as it is no more needed.
1766 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1769 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1770 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1771 * \sa checkDeepEquivalOnSameNodesWith()
1772 * \sa checkGeoEquivalWith()
1774 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1776 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1777 int nbOfCells=getNumberOfCells();
1778 static const int possibleCompType[]={0,1,2};
1779 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1781 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1782 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1784 throw INTERP_KERNEL::Exception(oss.str().c_str());
1786 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1787 arr=o2n->substr(nbOfCells);
1788 arr->setName(other->getName());
1790 if(other->getNumberOfCells()==0)
1792 return arr->getMaxValue(tmp)<nbOfCells;
1796 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1797 * This method tries to determine if \b other is fully included in \b this.
1798 * The main difference is that this method is not expected to throw exception.
1799 * This method has two outputs :
1801 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1802 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1804 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1806 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1807 DataArrayInt *commonCells=0,*commonCellsI=0;
1808 int thisNbCells=getNumberOfCells();
1809 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1810 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1811 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1812 int otherNbCells=other->getNumberOfCells();
1813 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1814 arr2->alloc(otherNbCells,1);
1815 arr2->fillWithZero();
1816 int *arr2Ptr=arr2->getPointer();
1817 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1818 for(int i=0;i<nbOfCommon;i++)
1820 int start=commonCellsPtr[commonCellsIPtr[i]];
1821 if(start<thisNbCells)
1823 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1825 int sig=commonCellsPtr[j]>0?1:-1;
1826 int val=std::abs(commonCellsPtr[j])-1;
1827 if(val>=thisNbCells)
1828 arr2Ptr[val-thisNbCells]=sig*(start+1);
1832 arr2->setName(other->getName());
1833 if(arr2->presenceOfValue(0))
1839 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1842 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1843 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1845 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1846 std::vector<const MEDCouplingUMesh *> ms(2);
1849 return MergeUMeshesOnSameCoords(ms);
1853 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1854 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1855 * cellIds is not given explicitely but by a range python like.
1857 * \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.
1858 * \return a newly allocated
1860 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1861 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1863 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1865 if(getMeshDimension()!=-1)
1866 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1869 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1871 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1873 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1875 return const_cast<MEDCouplingUMesh *>(this);
1880 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1881 * The result mesh shares or not the node coordinates array with \a this mesh depending
1882 * on \a keepCoords parameter.
1883 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1884 * to write this mesh to the MED file, its cells must be sorted using
1885 * sortCellsInMEDFileFrmt().
1886 * \param [in] begin - an array of cell ids to include to the new mesh.
1887 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
1888 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1889 * array of \a this mesh, else "free" nodes are removed from the result mesh
1890 * by calling zipCoords().
1891 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1892 * to delete this mesh using decrRef() as it is no more needed.
1893 * \throw If the coordinates array is not set.
1894 * \throw If the nodal connectivity of cells is not defined.
1895 * \throw If any cell id in the array \a begin is not valid.
1897 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1898 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
1900 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1902 if(getMeshDimension()!=-1)
1903 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1907 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1909 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1911 return const_cast<MEDCouplingUMesh *>(this);
1916 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1918 * 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.
1919 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1920 * The number of cells of \b this will remain the same with this method.
1922 * \param [in] begin begin of cell ids (included) of cells in this to assign
1923 * \param [in] end end of cell ids (excluded) of cells in this to assign
1924 * \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 ).
1925 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1927 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1929 checkConnectivityFullyDefined();
1930 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1931 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1932 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1933 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1935 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1936 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1937 throw INTERP_KERNEL::Exception(oss.str().c_str());
1939 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1940 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1942 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1943 throw INTERP_KERNEL::Exception(oss.str().c_str());
1945 int nbOfCells=getNumberOfCells();
1946 bool easyAssign=true;
1947 const int *connI=_nodal_connec_index->getConstPointer();
1948 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1949 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1951 if(*it>=0 && *it<nbOfCells)
1953 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1957 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1958 throw INTERP_KERNEL::Exception(oss.str().c_str());
1963 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1968 DataArrayInt *arrOut=0,*arrIOut=0;
1969 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
1971 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
1972 setConnectivity(arrOut,arrIOut,true);
1976 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1978 checkConnectivityFullyDefined();
1979 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1980 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1981 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1982 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1984 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1985 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1986 throw INTERP_KERNEL::Exception(oss.str().c_str());
1988 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
1989 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1991 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1992 throw INTERP_KERNEL::Exception(oss.str().c_str());
1994 int nbOfCells=getNumberOfCells();
1995 bool easyAssign=true;
1996 const int *connI=_nodal_connec_index->getConstPointer();
1997 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1999 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2001 if(it>=0 && it<nbOfCells)
2003 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2007 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2008 throw INTERP_KERNEL::Exception(oss.str().c_str());
2013 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2018 DataArrayInt *arrOut=0,*arrIOut=0;
2019 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2021 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2022 setConnectivity(arrOut,arrIOut,true);
2027 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2028 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2029 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2030 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2032 * \param [in] begin input start of array of node ids.
2033 * \param [in] end input end of array of node ids.
2034 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2035 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2037 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2039 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2040 checkConnectivityFullyDefined();
2042 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2043 std::vector<bool> fastFinder(sz,false);
2044 for(const int *work=begin;work!=end;work++)
2045 if(*work>=0 && *work<sz)
2046 fastFinder[*work]=true;
2047 int nbOfCells=getNumberOfCells();
2048 const int *conn=getNodalConnectivity()->getConstPointer();
2049 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2050 for(int i=0;i<nbOfCells;i++)
2052 int ref=0,nbOfHit=0;
2053 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2057 if(fastFinder[*work2])
2060 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2061 cellIdsKept->pushBackSilent(i);
2063 cellIdsKeptArr=cellIdsKept.retn();
2067 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2068 * this->getMeshDimension(), that bound some cells of \a this mesh.
2069 * The cells of lower dimension to include to the result mesh are selected basing on
2070 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2071 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2072 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2073 * created mesh shares the node coordinates array with \a this mesh.
2074 * \param [in] begin - the array of node ids.
2075 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2076 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2077 * array \a begin are added, else cells whose any node is in the
2078 * array \a begin are added.
2079 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2080 * to delete this mesh using decrRef() as it is no more needed.
2081 * \throw If the coordinates array is not set.
2082 * \throw If the nodal connectivity of cells is not defined.
2083 * \throw If any node id in \a begin is not valid.
2085 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2086 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2088 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2090 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2091 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2092 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2093 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2094 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2098 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2099 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2100 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2101 * array of \a this mesh, else "free" nodes are removed from the result mesh
2102 * by calling zipCoords().
2103 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2104 * to delete this mesh using decrRef() as it is no more needed.
2105 * \throw If the coordinates array is not set.
2106 * \throw If the nodal connectivity of cells is not defined.
2108 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2109 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2111 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2113 DataArrayInt *desc=DataArrayInt::New();
2114 DataArrayInt *descIndx=DataArrayInt::New();
2115 DataArrayInt *revDesc=DataArrayInt::New();
2116 DataArrayInt *revDescIndx=DataArrayInt::New();
2118 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2121 descIndx->decrRef();
2122 int nbOfCells=meshDM1->getNumberOfCells();
2123 const int *revDescIndxC=revDescIndx->getConstPointer();
2124 std::vector<int> boundaryCells;
2125 for(int i=0;i<nbOfCells;i++)
2126 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2127 boundaryCells.push_back(i);
2128 revDescIndx->decrRef();
2129 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2134 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2135 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2136 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2138 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2140 checkFullyDefined();
2141 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2142 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2143 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2144 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2146 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2147 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2149 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2150 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2151 const int *revDescPtr=revDesc->getConstPointer();
2152 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2153 int nbOfCells=getNumberOfCells();
2154 std::vector<bool> ret1(nbOfCells,false);
2156 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2157 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2158 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2160 DataArrayInt *ret2=DataArrayInt::New();
2162 int *ret2Ptr=ret2->getPointer();
2164 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2167 ret2->setName("BoundaryCells");
2172 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2173 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2174 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2175 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2177 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2178 * This method method returns cells ids set s = s1 + s2 where :
2180 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2181 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2183 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2184 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2186 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2187 * \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
2188 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2190 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2192 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2193 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2194 checkConnectivityFullyDefined();
2195 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2196 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2197 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2198 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2199 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2200 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2201 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2202 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2203 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2204 DataArrayInt *idsOtherInConsti=0;
2205 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2206 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2208 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2210 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2211 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2212 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2213 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2214 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2215 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2216 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2217 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2218 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2219 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2220 neighThisPartAuto=0;
2221 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2222 const int li[2]={0,1};
2223 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2224 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2225 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2228 cellIdsRk0=s0arr.retn();
2229 cellIdsRk1=s_renum1.retn();
2233 * 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
2234 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2236 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2238 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2240 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2241 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2242 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2243 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2245 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2246 revDesc=0; desc=0; descIndx=0;
2247 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2248 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2249 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2253 * Finds nodes lying on the boundary of \a this mesh.
2254 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2255 * nodes. The caller is to delete this array using decrRef() as it is no
2257 * \throw If the coordinates array is not set.
2258 * \throw If the nodal connectivity of cells is node defined.
2260 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2261 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2263 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2265 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2266 return skin->computeFetchedNodeIds();
2269 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2272 return const_cast<MEDCouplingUMesh *>(this);
2276 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2277 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2278 * 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.
2279 * 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.
2280 * 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.
2282 * \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
2283 * parameter is altered during the call.
2284 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2285 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2286 * \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.
2288 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2290 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2291 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2293 checkFullyDefined();
2294 otherDimM1OnSameCoords.checkFullyDefined();
2295 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2296 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2297 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2298 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2299 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2300 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2301 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2302 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2303 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2304 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2305 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2306 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2307 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2308 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2310 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2311 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2312 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2313 DataArrayInt *idsTmp=0;
2314 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2315 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2317 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2318 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2319 DataArrayInt *tmp0=0,*tmp1=0;
2320 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2321 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2322 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2323 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2324 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2325 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2326 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2328 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2329 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2330 nodeIdsToDuplicate=s3.retn();
2334 * This method operates a modification of the connectivity and coords in \b this.
2335 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2336 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2337 * 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
2338 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2339 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2341 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2343 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2344 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2346 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2348 int nbOfNodes=getNumberOfNodes();
2349 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2350 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2354 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2355 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2356 * This method is a generalization of shiftNodeNumbersInConn().
2357 * \warning This method performs no check of validity of new ids. **Use it with care !**
2358 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2359 * this->getNumberOfNodes(), in "Old to New" mode.
2360 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2361 * \throw If the nodal connectivity of cells is not defined.
2363 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2364 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2366 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2368 checkConnectivityFullyDefined();
2369 int *conn=getNodalConnectivity()->getPointer();
2370 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2371 int nbOfCells=getNumberOfCells();
2372 for(int i=0;i<nbOfCells;i++)
2373 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2375 int& node=conn[iconn];
2376 if(node>=0)//avoid polyhedron separator
2378 node=newNodeNumbersO2N[node];
2381 _nodal_connec->declareAsNew();
2386 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2387 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2388 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2390 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2392 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2394 checkConnectivityFullyDefined();
2395 int *conn=getNodalConnectivity()->getPointer();
2396 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2397 int nbOfCells=getNumberOfCells();
2398 for(int i=0;i<nbOfCells;i++)
2399 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2401 int& node=conn[iconn];
2402 if(node>=0)//avoid polyhedron separator
2407 _nodal_connec->declareAsNew();
2412 * This method operates a modification of the connectivity in \b this.
2413 * 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.
2414 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2415 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2416 * 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
2417 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2418 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2420 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2421 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2423 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2424 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2425 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2427 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2429 checkConnectivityFullyDefined();
2430 std::map<int,int> m;
2432 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2434 int *conn=getNodalConnectivity()->getPointer();
2435 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2436 int nbOfCells=getNumberOfCells();
2437 for(int i=0;i<nbOfCells;i++)
2438 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2440 int& node=conn[iconn];
2441 if(node>=0)//avoid polyhedron separator
2443 std::map<int,int>::iterator it=m.find(node);
2452 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2454 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2455 * After the call of this method the number of cells remains the same as before.
2457 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2458 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2459 * be strictly in [0;this->getNumberOfCells()).
2461 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2462 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2463 * should be contained in[0;this->getNumberOfCells()).
2465 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2467 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2469 checkConnectivityFullyDefined();
2470 int nbCells=getNumberOfCells();
2471 const int *array=old2NewBg;
2473 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2475 const int *conn=_nodal_connec->getConstPointer();
2476 const int *connI=_nodal_connec_index->getConstPointer();
2477 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2478 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2479 const int *n2oPtr=n2o->begin();
2480 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2481 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2482 newConn->copyStringInfoFrom(*_nodal_connec);
2483 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2484 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2485 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2487 int *newC=newConn->getPointer();
2488 int *newCI=newConnI->getPointer();
2491 for(int i=0;i<nbCells;i++)
2494 int nbOfElts=connI[pos+1]-connI[pos];
2495 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2500 setConnectivity(newConn,newConnI);
2502 free(const_cast<int *>(array));
2506 * Finds cells whose bounding boxes intersect a given bounding box.
2507 * \param [in] bbox - an array defining the bounding box via coordinates of its
2508 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2510 * \param [in] eps - a factor used to increase size of the bounding box of cell
2511 * before comparing it with \a bbox. This factor is multiplied by the maximal
2512 * extent of the bounding box of cell to produce an addition to this bounding box.
2513 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2514 * cells. The caller is to delete this array using decrRef() as it is no more
2516 * \throw If the coordinates array is not set.
2517 * \throw If the nodal connectivity of cells is not defined.
2519 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2520 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2522 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2524 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2525 if(getMeshDimension()==-1)
2527 elems->pushBackSilent(0);
2528 return elems.retn();
2530 int dim=getSpaceDimension();
2531 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2532 const int* conn = getNodalConnectivity()->getConstPointer();
2533 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2534 const double* coords = getCoords()->getConstPointer();
2535 int nbOfCells=getNumberOfCells();
2536 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2538 for (int i=0; i<dim; i++)
2540 elem_bb[i*2]=std::numeric_limits<double>::max();
2541 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2544 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2546 int node= conn[inode];
2547 if(node>=0)//avoid polyhedron separator
2549 for (int idim=0; idim<dim; idim++)
2551 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2553 elem_bb[idim*2] = coords[node*dim+idim] ;
2555 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2557 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2562 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2563 elems->pushBackSilent(ielem);
2565 return elems.retn();
2569 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2570 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2571 * added in 'elems' parameter.
2573 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2575 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2576 if(getMeshDimension()==-1)
2578 elems->pushBackSilent(0);
2579 return elems.retn();
2581 int dim=getSpaceDimension();
2582 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2583 const int* conn = getNodalConnectivity()->getConstPointer();
2584 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2585 const double* coords = getCoords()->getConstPointer();
2586 int nbOfCells=getNumberOfCells();
2587 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2589 for (int i=0; i<dim; i++)
2591 elem_bb[i*2]=std::numeric_limits<double>::max();
2592 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2595 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2597 int node= conn[inode];
2598 if(node>=0)//avoid polyhedron separator
2600 for (int idim=0; idim<dim; idim++)
2602 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2604 elem_bb[idim*2] = coords[node*dim+idim] ;
2606 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2608 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2613 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2614 elems->pushBackSilent(ielem);
2616 return elems.retn();
2620 * Returns a type of a cell by its id.
2621 * \param [in] cellId - the id of the cell of interest.
2622 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2623 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2625 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2627 const int *ptI=_nodal_connec_index->getConstPointer();
2628 const int *pt=_nodal_connec->getConstPointer();
2629 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2630 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2633 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2634 throw INTERP_KERNEL::Exception(oss.str().c_str());
2639 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2640 * This method does not throw exception if geometric type \a type is not in \a this.
2641 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2642 * The coordinates array is not considered here.
2644 * \param [in] type the geometric type
2645 * \return cell ids in this having geometric type \a type.
2647 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2650 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2652 checkConnectivityFullyDefined();
2653 int nbCells=getNumberOfCells();
2654 int mdim=getMeshDimension();
2655 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2656 if(mdim!=(int)cm.getDimension())
2657 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2658 const int *ptI=_nodal_connec_index->getConstPointer();
2659 const int *pt=_nodal_connec->getConstPointer();
2660 for(int i=0;i<nbCells;i++)
2662 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2663 ret->pushBackSilent(i);
2669 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2671 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2673 const int *ptI=_nodal_connec_index->getConstPointer();
2674 const int *pt=_nodal_connec->getConstPointer();
2675 int nbOfCells=getNumberOfCells();
2677 for(int i=0;i<nbOfCells;i++)
2678 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2684 * Returns the nodal connectivity of a given cell.
2685 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2686 * all returned node ids can be used in getCoordinatesOfNode().
2687 * \param [in] cellId - an id of the cell of interest.
2688 * \param [in,out] conn - a vector where the node ids are appended. It is not
2689 * cleared before the appending.
2690 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2692 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2694 const int *ptI=_nodal_connec_index->getConstPointer();
2695 const int *pt=_nodal_connec->getConstPointer();
2696 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2701 std::string MEDCouplingUMesh::simpleRepr() const
2703 static const char msg0[]="No coordinates specified !";
2704 std::ostringstream ret;
2705 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2706 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2708 double tt=getTime(tmpp1,tmpp2);
2709 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2710 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2712 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2714 { ret << " Mesh dimension has not been set or is invalid !"; }
2717 const int spaceDim=getSpaceDimension();
2718 ret << spaceDim << "\nInfo attached on space dimension : ";
2719 for(int i=0;i<spaceDim;i++)
2720 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2724 ret << msg0 << "\n";
2725 ret << "Number of nodes : ";
2727 ret << getNumberOfNodes() << "\n";
2729 ret << msg0 << "\n";
2730 ret << "Number of cells : ";
2731 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2732 ret << getNumberOfCells() << "\n";
2734 ret << "No connectivity specified !" << "\n";
2735 ret << "Cell types present : ";
2736 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2738 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2739 ret << cm.getRepr() << " ";
2745 std::string MEDCouplingUMesh::advancedRepr() const
2747 std::ostringstream ret;
2748 ret << simpleRepr();
2749 ret << "\nCoordinates array : \n___________________\n\n";
2751 _coords->reprWithoutNameStream(ret);
2753 ret << "No array set !\n";
2754 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2755 reprConnectivityOfThisLL(ret);
2760 * This method returns a C++ code that is a dump of \a this.
2761 * This method will throw if this is not fully defined.
2763 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2765 static const char coordsName[]="coords";
2766 static const char connName[]="conn";
2767 static const char connIName[]="connI";
2768 checkFullyDefined();
2769 std::ostringstream ret; ret << "// coordinates" << std::endl;
2770 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2771 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2772 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2773 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2774 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2775 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2776 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2780 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2782 std::ostringstream ret;
2783 reprConnectivityOfThisLL(ret);
2788 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2789 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2790 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2793 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2794 * 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
2795 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2797 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2799 int mdim=getMeshDimension();
2801 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2802 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
2803 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2804 bool needToCpyCT=true;
2807 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2815 if(!_nodal_connec_index)
2817 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2822 tmp2=_nodal_connec_index;
2825 ret->setConnectivity(tmp1,tmp2,false);
2830 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2831 ret->setCoords(coords);
2834 ret->setCoords(_coords);
2838 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2840 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2842 int nbOfCells=getNumberOfCells();
2843 const int *c=_nodal_connec->getConstPointer();
2844 const int *ci=_nodal_connec_index->getConstPointer();
2845 for(int i=0;i<nbOfCells;i++)
2847 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2848 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2849 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2854 stream << "Connectivity not defined !\n";
2857 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2859 const int *ptI=_nodal_connec_index->getConstPointer();
2860 const int *pt=_nodal_connec->getConstPointer();
2861 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2862 return ptI[cellId+1]-ptI[cellId]-1;
2864 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2868 * Returns types of cells of the specified part of \a this mesh.
2869 * This method avoids computing sub-mesh explicitely to get its types.
2870 * \param [in] begin - an array of cell ids of interest.
2871 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2872 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2873 * describing the cell types.
2874 * \throw If the coordinates array is not set.
2875 * \throw If the nodal connectivity of cells is not defined.
2878 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2880 checkFullyDefined();
2881 std::set<INTERP_KERNEL::NormalizedCellType> ret;
2882 const int *conn=_nodal_connec->getConstPointer();
2883 const int *connIndex=_nodal_connec_index->getConstPointer();
2884 for(const int *w=begin;w!=end;w++)
2885 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2890 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2891 * a set of types of cells constituting \a this mesh.
2892 * This method is for advanced users having prepared their connectivity before. For
2893 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2894 * \param [in] conn - the nodal connectivity array.
2895 * \param [in] connIndex - the nodal connectivity index array.
2896 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2899 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2901 DataArrayInt::SetArrayIn(conn,_nodal_connec);
2902 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2903 if(isComputingTypes)
2909 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2910 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2912 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2913 _nodal_connec(0),_nodal_connec_index(0),
2914 _types(other._types)
2916 if(other._nodal_connec)
2917 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2918 if(other._nodal_connec_index)
2919 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2922 MEDCouplingUMesh::~MEDCouplingUMesh()
2925 _nodal_connec->decrRef();
2926 if(_nodal_connec_index)
2927 _nodal_connec_index->decrRef();
2931 * Recomputes a set of cell types of \a this mesh. For more info see
2932 * \ref MEDCouplingUMeshNodalConnectivity.
2934 void MEDCouplingUMesh::computeTypes()
2936 if(_nodal_connec && _nodal_connec_index)
2939 const int *conn=_nodal_connec->getConstPointer();
2940 const int *connIndex=_nodal_connec_index->getConstPointer();
2941 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2943 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
2944 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2949 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2951 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2953 if(!_nodal_connec_index || !_nodal_connec || !_coords)
2954 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2958 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2960 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2962 if(!_nodal_connec_index || !_nodal_connec)
2963 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
2967 * Returns a number of cells constituting \a this mesh.
2968 * \return int - the number of cells in \a this mesh.
2969 * \throw If the nodal connectivity of cells is not defined.
2971 int MEDCouplingUMesh::getNumberOfCells() const
2973 if(_nodal_connec_index)
2974 return _nodal_connec_index->getNumberOfTuples()-1;
2979 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
2983 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
2984 * mesh. For more info see \ref MEDCouplingMeshesPage.
2985 * \return int - the dimension of \a this mesh.
2986 * \throw If the mesh dimension is not defined using setMeshDimension().
2988 int MEDCouplingUMesh::getMeshDimension() const
2991 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
2996 * Returns a length of the nodal connectivity array.
2997 * This method is for test reason. Normally the integer returned is not useable by
2998 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
2999 * \return int - the length of the nodal connectivity array.
3001 int MEDCouplingUMesh::getMeshLength() const
3003 return _nodal_connec->getNbOfElems();
3007 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3009 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3011 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3012 tinyInfo.push_back(getMeshDimension());
3013 tinyInfo.push_back(getNumberOfCells());
3015 tinyInfo.push_back(getMeshLength());
3017 tinyInfo.push_back(-1);
3021 * First step of unserialization process.
3023 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3025 return tinyInfo[6]<=0;
3029 * Second step of serialization process.
3030 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3032 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3034 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3036 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3040 * Third and final step of serialization process.
3042 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3044 MEDCouplingPointSet::serialize(a1,a2);
3045 if(getMeshDimension()>-1)
3047 a1=DataArrayInt::New();
3048 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3049 int *ptA1=a1->getPointer();
3050 const int *conn=getNodalConnectivity()->getConstPointer();
3051 const int *index=getNodalConnectivityIndex()->getConstPointer();
3052 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3053 std::copy(conn,conn+getMeshLength(),ptA1);
3060 * Second and final unserialization process.
3061 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3063 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3065 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3066 setMeshDimension(tinyInfo[5]);
3070 const int *recvBuffer=a1->getConstPointer();
3071 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3072 myConnecIndex->alloc(tinyInfo[6]+1,1);
3073 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3074 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3075 myConnec->alloc(tinyInfo[7],1);
3076 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3077 setConnectivity(myConnec, myConnecIndex);
3082 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3083 * CellIds are given using range specified by a start an end and step.
3085 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3087 checkFullyDefined();
3088 int ncell=getNumberOfCells();
3089 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3090 ret->_mesh_dim=_mesh_dim;
3091 ret->setCoords(_coords);
3092 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3093 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3094 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3096 const int *conn=_nodal_connec->getConstPointer();
3097 const int *connIndex=_nodal_connec_index->getConstPointer();
3098 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3100 if(work>=0 && work<ncell)
3102 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3106 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3107 throw INTERP_KERNEL::Exception(oss.str().c_str());
3110 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3111 int *newConnPtr=newConn->getPointer();
3112 std::set<INTERP_KERNEL::NormalizedCellType> types;
3114 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3116 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3117 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3119 ret->setConnectivity(newConn,newConnI,false);
3121 ret->copyTinyInfoFrom(this);
3126 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3127 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3128 * The return newly allocated mesh will share the same coordinates as \a this.
3130 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3132 checkFullyDefined();
3133 int ncell=getNumberOfCells();
3134 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3135 ret->_mesh_dim=_mesh_dim;
3136 ret->setCoords(_coords);
3137 std::size_t nbOfElemsRet=std::distance(begin,end);
3138 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3140 const int *conn=_nodal_connec->getConstPointer();
3141 const int *connIndex=_nodal_connec_index->getConstPointer();
3143 for(const int *work=begin;work!=end;work++,newNbring++)
3145 if(*work>=0 && *work<ncell)
3146 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3150 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3151 throw INTERP_KERNEL::Exception(oss.str().c_str());
3154 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3155 int *connRetWork=connRet;
3156 std::set<INTERP_KERNEL::NormalizedCellType> types;
3157 for(const int *work=begin;work!=end;work++)
3159 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3160 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3162 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3163 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3164 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3165 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3166 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3168 ret->copyTinyInfoFrom(this);
3173 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3175 * For 1D cells, the returned field contains lengths.<br>
3176 * For 2D cells, the returned field contains areas.<br>
3177 * For 3D cells, the returned field contains volumes.
3178 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3179 * orientation, i.e. the volume is always positive.
3180 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3181 * and one time . The caller is to delete this field using decrRef() as it is no
3184 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3186 std::string name="MeasureOfMesh_";
3188 int nbelem=getNumberOfCells();
3189 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3190 field->setName(name.c_str());
3191 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3192 array->alloc(nbelem,1);
3193 double *area_vol=array->getPointer();
3194 field->setArray(array) ; array=0;
3195 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3196 field->synchronizeTimeWithMesh();
3197 if(getMeshDimension()!=-1)
3200 INTERP_KERNEL::NormalizedCellType type;
3201 int dim_space=getSpaceDimension();
3202 const double *coords=getCoords()->getConstPointer();
3203 const int *connec=getNodalConnectivity()->getConstPointer();
3204 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3205 for(int iel=0;iel<nbelem;iel++)
3207 ipt=connec_index[iel];
3208 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3209 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);
3212 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3216 area_vol[0]=std::numeric_limits<double>::max();
3218 return field.retn();
3222 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3224 * For 1D cells, the returned array contains lengths.<br>
3225 * For 2D cells, the returned array contains areas.<br>
3226 * For 3D cells, the returned array contains volumes.
3227 * This method avoids building explicitly a part of \a this mesh to perform the work.
3228 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3229 * orientation, i.e. the volume is always positive.
3230 * \param [in] begin - an array of cell ids of interest.
3231 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3232 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3233 * delete this array using decrRef() as it is no more needed.
3235 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3236 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3237 * \sa getMeasureField()
3239 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3241 std::string name="PartMeasureOfMesh_";
3243 int nbelem=(int)std::distance(begin,end);
3244 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3245 array->setName(name.c_str());
3246 array->alloc(nbelem,1);
3247 double *area_vol=array->getPointer();
3248 if(getMeshDimension()!=-1)
3251 INTERP_KERNEL::NormalizedCellType type;
3252 int dim_space=getSpaceDimension();
3253 const double *coords=getCoords()->getConstPointer();
3254 const int *connec=getNodalConnectivity()->getConstPointer();
3255 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3256 for(const int *iel=begin;iel!=end;iel++)
3258 ipt=connec_index[*iel];
3259 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3260 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3263 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3267 area_vol[0]=std::numeric_limits<double>::max();
3269 return array.retn();
3273 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3274 * \a this one. The returned field contains the dual cell volume for each corresponding
3275 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3276 * the dual mesh in P1 sens of \a this.<br>
3277 * For 1D cells, the returned field contains lengths.<br>
3278 * For 2D cells, the returned field contains areas.<br>
3279 * For 3D cells, the returned field contains volumes.
3280 * This method is useful to check "P1*" conservative interpolators.
3281 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3282 * orientation, i.e. the volume is always positive.
3283 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3284 * nodes and one time. The caller is to delete this array using decrRef() as
3285 * it is no more needed.
3287 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3289 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3290 std::string name="MeasureOnNodeOfMesh_";
3292 int nbNodes=getNumberOfNodes();
3293 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3294 double cst=1./((double)getMeshDimension()+1.);
3295 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3296 array->alloc(nbNodes,1);
3297 double *valsToFill=array->getPointer();
3298 std::fill(valsToFill,valsToFill+nbNodes,0.);
3299 const double *values=tmp->getArray()->getConstPointer();
3300 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3301 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3302 getReverseNodalConnectivity(da,daInd);
3303 const int *daPtr=da->getConstPointer();
3304 const int *daIPtr=daInd->getConstPointer();
3305 for(int i=0;i<nbNodes;i++)
3306 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3307 valsToFill[i]+=cst*values[*cell];
3309 ret->setArray(array);
3314 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3315 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3316 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3317 * and are normalized.
3318 * <br> \a this can be either
3319 * - a 2D mesh in 2D or 3D space or
3320 * - an 1D mesh in 2D space.
3322 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3323 * cells and one time. The caller is to delete this field using decrRef() as
3324 * it is no more needed.
3325 * \throw If the nodal connectivity of cells is not defined.
3326 * \throw If the coordinates array is not set.
3327 * \throw If the mesh dimension is not set.
3328 * \throw If the mesh and space dimension is not as specified above.
3330 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3332 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3333 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3334 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3335 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3336 int nbOfCells=getNumberOfCells();
3337 int nbComp=getMeshDimension()+1;
3338 array->alloc(nbOfCells,nbComp);
3339 double *vals=array->getPointer();
3340 const int *connI=_nodal_connec_index->getConstPointer();
3341 const int *conn=_nodal_connec->getConstPointer();
3342 const double *coords=_coords->getConstPointer();
3343 if(getMeshDimension()==2)
3345 if(getSpaceDimension()==3)
3347 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3348 const double *locPtr=loc->getConstPointer();
3349 for(int i=0;i<nbOfCells;i++,vals+=3)
3351 int offset=connI[i];
3352 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3353 double n=INTERP_KERNEL::norm<3>(vals);
3354 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3359 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3360 const double *isAbsPtr=isAbs->getArray()->begin();
3361 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3362 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3365 else//meshdimension==1
3368 for(int i=0;i<nbOfCells;i++)
3370 int offset=connI[i];
3371 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3372 double n=INTERP_KERNEL::norm<2>(tmp);
3373 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3378 ret->setArray(array);
3380 ret->synchronizeTimeWithSupport();
3385 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3386 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3387 * and are normalized.
3388 * <br> \a this can be either
3389 * - a 2D mesh in 2D or 3D space or
3390 * - an 1D mesh in 2D space.
3392 * This method avoids building explicitly a part of \a this mesh to perform the work.
3393 * \param [in] begin - an array of cell ids of interest.
3394 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3395 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3396 * cells and one time. The caller is to delete this field using decrRef() as
3397 * it is no more needed.
3398 * \throw If the nodal connectivity of cells is not defined.
3399 * \throw If the coordinates array is not set.
3400 * \throw If the mesh dimension is not set.
3401 * \throw If the mesh and space dimension is not as specified above.
3402 * \sa buildOrthogonalField()
3404 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3405 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3407 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3409 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3410 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3411 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3412 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3413 std::size_t nbelems=std::distance(begin,end);
3414 int nbComp=getMeshDimension()+1;
3415 array->alloc((int)nbelems,nbComp);
3416 double *vals=array->getPointer();
3417 const int *connI=_nodal_connec_index->getConstPointer();
3418 const int *conn=_nodal_connec->getConstPointer();
3419 const double *coords=_coords->getConstPointer();
3420 if(getMeshDimension()==2)
3422 if(getSpaceDimension()==3)
3424 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3425 const double *locPtr=loc->getConstPointer();
3426 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3428 int offset=connI[*i];
3429 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3430 double n=INTERP_KERNEL::norm<3>(vals);
3431 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3436 for(std::size_t i=0;i<nbelems;i++)
3437 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3440 else//meshdimension==1
3443 for(const int *i=begin;i!=end;i++)
3445 int offset=connI[*i];
3446 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3447 double n=INTERP_KERNEL::norm<2>(tmp);
3448 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3453 ret->setArray(array);
3455 ret->synchronizeTimeWithSupport();
3460 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3461 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3462 * and are \b not normalized.
3463 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3464 * cells and one time. The caller is to delete this field using decrRef() as
3465 * it is no more needed.
3466 * \throw If the nodal connectivity of cells is not defined.
3467 * \throw If the coordinates array is not set.
3468 * \throw If \a this->getMeshDimension() != 1.
3469 * \throw If \a this mesh includes cells of type other than SEG2.
3471 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3473 if(getMeshDimension()!=1)
3474 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3475 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3476 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3477 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3478 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3479 int nbOfCells=getNumberOfCells();
3480 int spaceDim=getSpaceDimension();
3481 array->alloc(nbOfCells,spaceDim);
3482 double *pt=array->getPointer();
3483 const double *coo=getCoords()->getConstPointer();
3484 std::vector<int> conn;
3486 for(int i=0;i<nbOfCells;i++)
3489 getNodeIdsOfCell(i,conn);
3490 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3492 ret->setArray(array);
3494 ret->synchronizeTimeWithSupport();
3499 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3500 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3501 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3502 * from. If a result face is shared by two 3D cells, then the face in included twice in
3504 * \param [in] origin - 3 components of a point defining location of the plane.
3505 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3506 * must be greater than 1e-6.
3507 * \param [in] eps - half-thickness of the plane.
3508 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3509 * producing correspondent 2D cells. The caller is to delete this array
3510 * using decrRef() as it is no more needed.
3511 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3512 * not share the node coordinates array with \a this mesh. The caller is to
3513 * delete this mesh using decrRef() as it is no more needed.
3514 * \throw If the coordinates array is not set.
3515 * \throw If the nodal connectivity of cells is not defined.
3516 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3517 * \throw If magnitude of \a vec is less than 1e-6.
3518 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3519 * \throw If \a this includes quadratic cells.
3521 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3523 checkFullyDefined();
3524 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3525 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3526 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3527 if(candidates->empty())
3528 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3529 std::vector<int> nodes;
3530 DataArrayInt *cellIds1D=0;
3531 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3532 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3533 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3534 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3535 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3536 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3537 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3538 revDesc2=0; revDescIndx2=0;
3539 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3540 revDesc1=0; revDescIndx1=0;
3541 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3542 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3544 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3545 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3547 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3548 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3549 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3550 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3551 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3552 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3553 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3554 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3555 if(cellIds2->empty())
3556 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3557 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3558 ret->setCoords(mDesc1->getCoords());
3559 ret->setConnectivity(conn,connI,true);
3560 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3565 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3566 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
3567 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3569 * \param [in] origin - 3 components of a point defining location of the plane.
3570 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3571 * must be greater than 1e-6.
3572 * \param [in] eps - half-thickness of the plane.
3573 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3574 * producing correspondent segments. The caller is to delete this array
3575 * using decrRef() as it is no more needed.
3576 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3577 * mesh in 3D space. This mesh does not share the node coordinates array with
3578 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3580 * \throw If the coordinates array is not set.
3581 * \throw If the nodal connectivity of cells is not defined.
3582 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3583 * \throw If magnitude of \a vec is less than 1e-6.
3584 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3585 * \throw If \a this includes quadratic cells.
3587 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3589 checkFullyDefined();
3590 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3591 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3592 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3593 if(candidates->empty())
3594 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3595 std::vector<int> nodes;
3596 DataArrayInt *cellIds1D=0;
3597 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3598 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3599 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3600 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3601 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3602 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3603 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3604 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3605 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3607 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3608 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3610 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3611 int ncellsSub=subMesh->getNumberOfCells();
3612 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3613 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3614 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3615 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3616 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3618 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3619 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3620 for(int i=0;i<ncellsSub;i++)
3622 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3624 if(cut3DSurf[i].first!=-2)
3626 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3627 connI->pushBackSilent(conn->getNumberOfTuples());
3628 cellIds2->pushBackSilent(i);
3632 int cellId3DSurf=cut3DSurf[i].second;
3633 int offset=nodalI[cellId3DSurf]+1;
3634 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3635 for(int j=0;j<nbOfEdges;j++)
3637 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3638 connI->pushBackSilent(conn->getNumberOfTuples());
3639 cellIds2->pushBackSilent(cellId3DSurf);
3644 if(cellIds2->empty())
3645 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3646 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3647 ret->setCoords(mDesc1->getCoords());
3648 ret->setConnectivity(conn,connI,true);
3649 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3654 * Finds cells whose bounding boxes intersect a given plane.
3655 * \param [in] origin - 3 components of a point defining location of the plane.
3656 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3657 * must be greater than 1e-6.
3658 * \param [in] eps - half-thickness of the plane.
3659 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3660 * cells. The caller is to delete this array using decrRef() as it is no more
3662 * \throw If the coordinates array is not set.
3663 * \throw If the nodal connectivity of cells is not defined.
3664 * \throw If \a this->getSpaceDimension() != 3.
3665 * \throw If magnitude of \a vec is less than 1e-6.
3666 * \sa buildSlice3D()
3668 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3670 checkFullyDefined();
3671 if(getSpaceDimension()!=3)
3672 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3673 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3675 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3677 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3678 double angle=acos(vec[2]/normm);
3679 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3683 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3684 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3685 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3687 mw->getBoundingBox(bbox);
3688 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3689 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3693 getBoundingBox(bbox);
3694 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3695 cellIds=getCellsInBoundingBox(bbox,eps);
3697 return cellIds.retn();
3701 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3702 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3703 * No consideration of coordinate is done by this method.
3704 * 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)
3705 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3707 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3709 if(getMeshDimension()!=1)
3710 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3711 int nbCells=getNumberOfCells();
3713 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3714 const int *connI=_nodal_connec_index->getConstPointer();
3715 const int *conn=_nodal_connec->getConstPointer();
3716 int ref=conn[connI[0]+2];
3717 for(int i=1;i<nbCells;i++)
3719 if(conn[connI[i]+1]!=ref)
3721 ref=conn[connI[i]+2];
3727 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3728 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3729 * \param pt reference point of the line
3730 * \param v normalized director vector of the line
3731 * \param eps max precision before throwing an exception
3732 * \param res output of size this->getNumberOfCells
3734 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3736 if(getMeshDimension()!=1)
3737 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3738 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3739 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3740 if(getSpaceDimension()!=3)
3741 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3742 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3743 const double *fPtr=f->getArray()->getConstPointer();
3745 for(int i=0;i<getNumberOfCells();i++)
3747 const double *tmp1=fPtr+3*i;
3748 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3749 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3750 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3751 double n1=INTERP_KERNEL::norm<3>(tmp);
3752 n1/=INTERP_KERNEL::norm<3>(tmp1);
3754 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3756 const double *coo=getCoords()->getConstPointer();
3757 for(int i=0;i<getNumberOfNodes();i++)
3759 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3760 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3761 res[i]=std::accumulate(tmp,tmp+3,0.);
3766 * 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.
3767 * \a this is expected to be a mesh so that its space dimension is equal to its
3768 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3769 * 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).
3771 * 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
3772 * 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).
3773 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3775 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3776 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3778 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3779 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3780 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3781 * \return the positive value of the distance.
3782 * \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
3784 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3786 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
3788 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3789 if(meshDim!=spaceDim-1)
3790 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3791 if(meshDim!=2 && meshDim!=1)
3792 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3793 checkFullyDefined();
3794 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3795 { 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()); }
3796 DataArrayInt *ret1=0;
3797 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3798 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3799 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3800 cellId=*ret1Safe->begin();
3801 return *ret0->begin();
3805 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3806 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
3807 * 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
3808 * 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).
3809 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3811 * \a this is expected to be a mesh so that its space dimension is equal to its
3812 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3813 * 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).
3815 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3816 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3818 * \param [in] pts the list of points in which each tuple represents a point
3819 * \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.
3820 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3821 * \throw if number of components of \a pts is not equal to the space dimension.
3822 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3823 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3825 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
3828 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3829 pts->checkAllocated();
3830 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3831 if(meshDim!=spaceDim-1)
3832 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3833 if(meshDim!=2 && meshDim!=1)
3834 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3835 if(pts->getNumberOfComponents()!=spaceDim)
3837 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3838 throw INTERP_KERNEL::Exception(oss.str().c_str());
3840 checkFullyDefined();
3841 int nbCells=getNumberOfCells();
3843 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3844 int nbOfPts=pts->getNumberOfTuples();
3845 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3846 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3847 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3848 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3849 std::vector<double> bbox;
3850 getBoundingBoxForBBTree(bbox);
3855 BBTreeDst<3> myTree(&bbox[0],0,0,nbCells);
3856 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3858 double x=std::numeric_limits<double>::max();
3859 std::vector<int> elems;
3860 myTree.getMinDistanceOfMax(ptsPtr,x);
3861 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3862 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3868 BBTreeDst<2> myTree(&bbox[0],0,0,nbCells);
3869 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3871 double x=std::numeric_limits<double>::max();
3872 std::vector<int> elems;
3873 myTree.getMinDistanceOfMax(ptsPtr,x);
3874 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3875 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3880 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3882 cellIds=ret1.retn();
3887 * \param [in] pt the start pointer (included) of the coordinates of the point
3888 * \param [in] cellIdsBg the start pointer (included) of cellIds
3889 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3890 * \param [in] nc nodal connectivity
3891 * \param [in] ncI nodal connectivity index
3892 * \param [in,out] ret0 the min distance between \a this and the external input point
3893 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3894 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3896 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)
3899 ret0=std::numeric_limits<double>::max();
3900 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3902 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3904 case INTERP_KERNEL::NORM_TRI3:
3906 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3908 { ret0=tmp; cellId=*zeCell; }
3911 case INTERP_KERNEL::NORM_QUAD4:
3912 case INTERP_KERNEL::NORM_POLYGON:
3914 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3916 { ret0=tmp; cellId=*zeCell; }
3920 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3926 * \param [in] pt the start pointer (included) of the coordinates of the point
3927 * \param [in] cellIdsBg the start pointer (included) of cellIds
3928 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3929 * \param [in] nc nodal connectivity
3930 * \param [in] ncI nodal connectivity index
3931 * \param [in,out] ret0 the min distance between \a this and the external input point
3932 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3933 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3935 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)
3938 ret0=std::numeric_limits<double>::max();
3939 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3941 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3943 case INTERP_KERNEL::NORM_SEG2:
3945 std::size_t uselessEntry=0;
3946 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
3949 { ret0=tmp; cellId=*zeCell; }
3953 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3959 * Finds cells in contact with a ball (i.e. a point with precision).
3960 * \warning This method is suitable if the caller intends to evaluate only one
3961 * point, for more points getCellsContainingPoints() is recommended as it is
3963 * \param [in] pos - array of coordinates of the ball central point.
3964 * \param [in] eps - ball radius.
3965 * \return int - a smallest id of cells being in contact with the ball, -1 in case
3966 * if there are no such cells.
3967 * \throw If the coordinates array is not set.
3968 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
3970 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
3972 std::vector<int> elts;
3973 getCellsContainingPoint(pos,eps,elts);
3976 return elts.front();
3980 * Finds cells in contact with a ball (i.e. a point with precision).
3981 * \warning This method is suitable if the caller intends to evaluate only one
3982 * point, for more points getCellsContainingPoints() is recommended as it is
3984 * \param [in] pos - array of coordinates of the ball central point.
3985 * \param [in] eps - ball radius.
3986 * \param [in,out] elts - vector returning ids of the found cells. It is cleared
3987 * before inserting ids.
3988 * \throw If the coordinates array is not set.
3989 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
3991 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
3992 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
3994 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
3996 std::vector<int> eltsIndex;
3997 getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
4002 namespace ParaMEDMEM
4004 template<const int SPACEDIMM>
4008 static const int MY_SPACEDIM=SPACEDIMM;
4009 static const int MY_MESHDIM=8;
4010 typedef int MyConnType;
4011 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4013 // useless, but for windows compilation ...
4014 const double* getCoordinatesPtr() const { return 0; }
4015 const int* getConnectivityPtr() const { return 0; }
4016 const int* getConnectivityIndexPtr() const { return 0; }
4017 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4021 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4023 INTERP_KERNEL::Edge *ret=0;
4026 case INTERP_KERNEL::NORM_SEG2:
4028 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4031 case INTERP_KERNEL::NORM_SEG3:
4033 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4034 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4035 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4036 bool colinearity=inters.areColinears();
4037 delete e1; delete e2;
4039 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4041 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4042 mapp2[bg[2]].second=false;
4046 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4052 * 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'.
4053 * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4054 * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4056 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4059 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.
4060 const double *coo=mDesc->getCoords()->getConstPointer();
4061 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4062 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4064 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4065 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4066 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4068 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4069 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4071 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4072 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4074 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4075 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4077 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4079 if((*it2).second.second)
4080 mapp[(*it2).second.first]=(*it2).first;
4081 ((*it2).second.first)->decrRef();
4086 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4090 int locId=nodeId-offset2;
4091 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4095 int locId=nodeId-offset1;
4096 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4098 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4101 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4102 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4103 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4105 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4107 int eltId1=abs(*desc1)-1;
4108 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4110 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4111 if(it==mappRev.end())
4113 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4124 template<int SPACEDIM>
4125 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4126 double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4128 std::vector<double> bbox;
4129 eltsIndex.resize(nbOfPoints+1);
4132 getBoundingBoxForBBTree(bbox);
4133 int nbOfCells=getNumberOfCells();
4134 const int *conn=_nodal_connec->getConstPointer();
4135 const int *connI=_nodal_connec_index->getConstPointer();
4136 double bb[2*SPACEDIM];
4137 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4138 for(int i=0;i<nbOfPoints;i++)
4140 eltsIndex[i+1]=eltsIndex[i];
4141 for(int j=0;j<SPACEDIM;j++)
4143 bb[2*j]=pos[SPACEDIM*i+j];
4144 bb[2*j+1]=pos[SPACEDIM*i+j];
4146 std::vector<int> candidates;
4147 myTree.getIntersectingElems(bb,candidates);
4148 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4150 int sz=connI[(*iter)+1]-connI[*iter]-1;
4151 if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4152 (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4153 coords,conn+connI[*iter]+1,sz,eps))
4156 elts.push_back(*iter);
4162 * Finds cells in contact with several balls (i.e. points with precision).
4163 * This method is an extension of getCellContainingPoint() and
4164 * getCellsContainingPoint() for the case of multiple points.
4165 * \param [in] pos - an array of coordinates of points in full interlace mode :
4166 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4167 * this->getSpaceDimension() * \a nbOfPoints
4168 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4169 * \param [in] eps - radius of balls (i.e. the precision).
4170 * \param [in,out] elts - vector returning ids of found cells.
4171 * \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4172 * dividing cell ids in \a elts into groups each referring to one
4173 * point. Its every element (except the last one) is an index pointing to the
4174 * first id of a group of cells. For example cells in contact with the *i*-th
4175 * point are described by following range of indices:
4176 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4177 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4178 * Number of cells in contact with the *i*-th point is
4179 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4180 * \throw If the coordinates array is not set.
4181 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4183 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4184 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4186 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4187 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4189 int spaceDim=getSpaceDimension();
4190 int mDim=getMeshDimension();
4195 const double *coords=_coords->getConstPointer();
4196 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4203 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4205 else if(spaceDim==2)
4209 const double *coords=_coords->getConstPointer();
4210 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4213 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4215 else if(spaceDim==1)
4219 const double *coords=_coords->getConstPointer();
4220 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4223 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4226 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4230 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4231 * least two its edges intersect each other anywhere except their extremities. An
4232 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4233 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4234 * cleared before filling in.
4235 * \param [in] eps - precision.
4236 * \throw If \a this->getMeshDimension() != 2.
4237 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4239 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4241 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4242 if(getMeshDimension()!=2)
4243 throw INTERP_KERNEL::Exception(msg);
4244 int spaceDim=getSpaceDimension();
4245 if(spaceDim!=2 && spaceDim!=3)
4246 throw INTERP_KERNEL::Exception(msg);
4247 const int *conn=_nodal_connec->getConstPointer();
4248 const int *connI=_nodal_connec_index->getConstPointer();
4249 int nbOfCells=getNumberOfCells();
4250 std::vector<double> cell2DinS2;
4251 for(int i=0;i<nbOfCells;i++)
4253 int offset=connI[i];
4254 int nbOfNodesForCell=connI[i+1]-offset-1;
4255 if(nbOfNodesForCell<=3)
4257 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4258 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4259 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4266 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4268 * 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.
4269 * 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.
4271 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4272 * This convex envelop is computed using Jarvis march algorithm.
4273 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4274 * 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)
4275 * 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.
4277 * \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.
4279 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4281 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4282 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4283 checkFullyDefined();
4284 const double *coords=getCoords()->getConstPointer();
4285 int nbOfCells=getNumberOfCells();
4286 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4287 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4288 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4289 int *workIndexOut=nodalConnecIndexOut->getPointer();
4291 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4292 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4293 std::set<INTERP_KERNEL::NormalizedCellType> types;
4294 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4295 isChanged->alloc(0,1);
4296 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4298 int pos=nodalConnecOut->getNumberOfTuples();
4299 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4300 isChanged->pushBackSilent(i);
4301 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4302 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4304 if(isChanged->empty())
4306 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4308 return isChanged.retn();
4312 * This method is \b NOT const because it can modify \a this.
4313 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4314 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4315 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4316 * \b 1 for translation and rotation around point of 'mesh1D'.
4317 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4319 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4321 checkFullyDefined();
4322 mesh1D->checkFullyDefined();
4323 if(!mesh1D->isContiguous1D())
4324 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4325 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4326 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4327 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4328 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4329 if(mesh1D->getMeshDimension()!=1)
4330 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4332 if(isPresenceOfQuadratic())
4334 if(mesh1D->isFullyQuadratic())
4337 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4340 int oldNbOfNodes=getNumberOfNodes();
4341 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4346 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4351 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4355 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4357 setCoords(newCoords);
4358 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4364 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4365 * If it is not the case an exception will be thrown.
4366 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4367 * intersection of plane defined by ('origin','vec').
4368 * This method has one in/out parameter : 'cut3DCurve'.
4369 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4370 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4371 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4372 * This method will throw an exception if \a this contains a non linear segment.
4374 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4376 checkFullyDefined();
4377 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4378 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4379 int ncells=getNumberOfCells();
4380 int nnodes=getNumberOfNodes();
4381 double vec2[3],vec3[3],vec4[3];
4382 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4384 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4385 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4386 const int *conn=_nodal_connec->getConstPointer();
4387 const int *connI=_nodal_connec_index->getConstPointer();
4388 const double *coo=_coords->getConstPointer();
4389 std::vector<double> addCoo;
4390 for(int i=0;i<ncells;i++)
4392 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4394 if(cut3DCurve[i]==-2)
4396 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4397 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];
4398 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4399 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4400 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4402 const double *st2=coo+3*st;
4403 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4404 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]));
4405 if(pos>eps && pos<1-eps)
4407 int nNode=((int)addCoo.size())/3;
4408 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4409 addCoo.insert(addCoo.end(),vec4,vec4+3);
4410 cut3DCurve[i]=nnodes+nNode;
4416 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4420 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4421 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4422 coo2->alloc(newNbOfNodes,3);
4423 double *tmp=coo2->getPointer();
4424 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4425 std::copy(addCoo.begin(),addCoo.end(),tmp);
4426 DataArrayDouble::SetArrayIn(coo2,_coords);
4431 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4432 * \param mesh1D is the input 1D mesh used for translation computation.
4433 * \return newCoords new coords filled by this method.
4435 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4437 int oldNbOfNodes=getNumberOfNodes();
4438 int nbOf1DCells=mesh1D->getNumberOfCells();
4439 int spaceDim=getSpaceDimension();
4440 DataArrayDouble *ret=DataArrayDouble::New();
4441 std::vector<bool> isQuads;
4442 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4443 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4444 double *retPtr=ret->getPointer();
4445 const double *coords=getCoords()->getConstPointer();
4446 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4448 std::vector<double> c;
4452 for(int i=0;i<nbOf1DCells;i++)
4455 mesh1D->getNodeIdsOfCell(i,v);
4457 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4458 mesh1D->getCoordinatesOfNode(v[0],c);
4459 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4460 for(int j=0;j<oldNbOfNodes;j++)
4461 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4465 mesh1D->getCoordinatesOfNode(v[1],c);
4466 mesh1D->getCoordinatesOfNode(v[0],c);
4467 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4468 for(int j=0;j<oldNbOfNodes;j++)
4469 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4472 ret->copyStringInfoFrom(*getCoords());
4477 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4478 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4479 * \return newCoords new coords filled by this method.
4481 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4483 if(mesh1D->getSpaceDimension()==2)
4484 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4485 if(mesh1D->getSpaceDimension()==3)
4486 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4487 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4491 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4492 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4493 * \return newCoords new coords filled by this method.
4495 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4498 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4499 int oldNbOfNodes=getNumberOfNodes();
4500 int nbOf1DCells=mesh1D->getNumberOfCells();
4502 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4503 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4504 int nbOfLevsInVec=nbOf1DCells+1;
4505 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4506 double *retPtr=ret->getPointer();
4507 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4508 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4509 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4510 tmp->setCoords(tmp2);
4511 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4512 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4513 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4514 for(int i=1;i<nbOfLevsInVec;i++)
4516 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4517 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4518 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4519 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4520 tmp->translate(vec);
4521 double tmp3[2],radius,alpha,alpha0;
4522 const double *p0=i+1<nbOfLevsInVec?begin:third;
4523 const double *p1=i+1<nbOfLevsInVec?end:begin;
4524 const double *p2=i+1<nbOfLevsInVec?third:end;
4525 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4526 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]);
4527 double angle=acos(cosangle/(radius*radius));
4528 tmp->rotate(end,0,angle);
4529 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4535 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4536 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4537 * \return newCoords new coords filled by this method.
4539 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4542 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4543 int oldNbOfNodes=getNumberOfNodes();
4544 int nbOf1DCells=mesh1D->getNumberOfCells();
4546 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4547 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4548 int nbOfLevsInVec=nbOf1DCells+1;
4549 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4550 double *retPtr=ret->getPointer();
4551 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4552 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4553 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4554 tmp->setCoords(tmp2);
4555 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4556 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4557 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4558 for(int i=1;i<nbOfLevsInVec;i++)
4560 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4561 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4562 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4563 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4564 tmp->translate(vec);
4565 double tmp3[2],radius,alpha,alpha0;
4566 const double *p0=i+1<nbOfLevsInVec?begin:third;
4567 const double *p1=i+1<nbOfLevsInVec?end:begin;
4568 const double *p2=i+1<nbOfLevsInVec?third:end;
4569 double vecPlane[3]={
4570 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4571 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4572 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4574 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4577 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4578 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4579 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4581 double c2=cos(asin(s2));
4583 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4584 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4585 {-vec2[1]*s2, vec2[0]*s2, c2}
4587 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]};
4588 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]};
4589 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]};
4590 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4591 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]);
4592 double angle=acos(cosangle/(radius*radius));
4593 tmp->rotate(end,vecPlane,angle);
4596 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4602 * This method is private because not easy to use for end user. This method is const contrary to
4603 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4604 * the coords sorted slice by slice.
4605 * \param isQuad specifies presence of quadratic cells.
4607 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4609 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4610 int nbOf2DCells=getNumberOfCells();
4611 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4612 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4613 const int *conn=_nodal_connec->getConstPointer();
4614 const int *connI=_nodal_connec_index->getConstPointer();
4615 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4616 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4617 newConnI->alloc(nbOf3DCells+1,1);
4618 int *newConnIPtr=newConnI->getPointer();
4620 std::vector<int> newc;
4621 for(int j=0;j<nbOf2DCells;j++)
4623 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4624 *newConnIPtr++=(int)newc.size();
4626 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4627 int *newConnPtr=newConn->getPointer();
4628 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4629 newConnIPtr=newConnI->getPointer();
4630 for(int iz=0;iz<nbOf1DCells;iz++)
4633 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4634 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4636 int icell=(int)(iter-newc.begin());
4637 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4640 *newConnPtr=(*iter)+iz*deltaPerLev;
4645 *newConnPtr=(*iter);
4648 ret->setConnectivity(newConn,newConnI,true);
4649 ret->setCoords(getCoords());
4654 * Checks if \a this mesh is constituted by only quadratic cells.
4655 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4656 * \throw If the coordinates array is not set.
4657 * \throw If the nodal connectivity of cells is not defined.
4659 bool MEDCouplingUMesh::isFullyQuadratic() const
4661 checkFullyDefined();
4663 int nbOfCells=getNumberOfCells();
4664 for(int i=0;i<nbOfCells && ret;i++)
4666 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4667 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4668 ret=cm.isQuadratic();
4674 * Checks if \a this mesh includes any quadratic cell.
4675 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4676 * \throw If the coordinates array is not set.
4677 * \throw If the nodal connectivity of cells is not defined.
4679 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4681 checkFullyDefined();
4683 int nbOfCells=getNumberOfCells();
4684 for(int i=0;i<nbOfCells && !ret;i++)
4686 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4687 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4688 ret=cm.isQuadratic();
4694 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4695 * this mesh, it remains unchanged.
4696 * \throw If the coordinates array is not set.
4697 * \throw If the nodal connectivity of cells is not defined.
4699 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4701 checkFullyDefined();
4702 int nbOfCells=getNumberOfCells();
4704 const int *iciptr=_nodal_connec_index->getConstPointer();
4705 for(int i=0;i<nbOfCells;i++)
4707 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4708 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4709 if(cm.isQuadratic())
4711 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4712 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4713 if(!cml.isDynamic())
4714 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4716 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4721 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4722 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4723 const int *icptr=_nodal_connec->getConstPointer();
4724 newConn->alloc(getMeshLength()-delta,1);
4725 newConnI->alloc(nbOfCells+1,1);
4726 int *ocptr=newConn->getPointer();
4727 int *ociptr=newConnI->getPointer();
4730 for(int i=0;i<nbOfCells;i++,ociptr++)
4732 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4733 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4734 if(!cm.isQuadratic())
4736 _types.insert(type);
4737 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4738 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4742 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4743 _types.insert(typel);
4744 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4745 int newNbOfNodes=cml.getNumberOfNodes();
4747 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4748 *ocptr++=(int)typel;
4749 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4750 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4753 setConnectivity(newConn,newConnI,false);
4757 * This method converts all linear cell in \a this to quadratic one.
4758 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4759 * 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)
4760 * 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.
4761 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4762 * end of the existing coordinates.
4764 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4765 * corresponding quadratic cells. 1 is those creating the 'most' complex.
4766 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4768 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4770 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4772 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4774 DataArrayInt *conn=0,*connI=0;
4775 DataArrayDouble *coords=0;
4776 std::set<INTERP_KERNEL::NormalizedCellType> types;
4777 checkFullyDefined();
4778 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4779 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4780 int meshDim=getMeshDimension();
4781 switch(conversionType)
4787 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4788 connSafe=conn; connISafe=connI; coordsSafe=coords;
4791 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4792 connSafe=conn; connISafe=connI; coordsSafe=coords;
4795 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4796 connSafe=conn; connISafe=connI; coordsSafe=coords;
4799 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4807 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4808 connSafe=conn; connISafe=connI; coordsSafe=coords;
4811 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4812 connSafe=conn; connISafe=connI; coordsSafe=coords;
4815 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4816 connSafe=conn; connISafe=connI; coordsSafe=coords;
4819 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4824 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4826 setConnectivity(connSafe,connISafe,false);
4828 setCoords(coordsSafe);
4833 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4834 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4835 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4837 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4839 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4840 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4841 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4842 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4843 int nbOfCells=getNumberOfCells();
4844 int nbOfNodes=getNumberOfNodes();
4845 const int *cPtr=_nodal_connec->getConstPointer();
4846 const int *icPtr=_nodal_connec_index->getConstPointer();
4847 int lastVal=0,offset=nbOfNodes;
4848 for(int i=0;i<nbOfCells;i++,icPtr++)
4850 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4851 if(type==INTERP_KERNEL::NORM_SEG2)
4853 types.insert(INTERP_KERNEL::NORM_SEG3);
4854 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4855 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4856 newConn->pushBackSilent(offset++);
4858 newConnI->pushBackSilent(lastVal);
4859 ret->pushBackSilent(i);
4864 lastVal+=(icPtr[1]-icPtr[0]);
4865 newConnI->pushBackSilent(lastVal);
4866 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4869 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4870 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4874 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)
4876 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4877 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4878 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4880 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4881 DataArrayInt *conn1D=0,*conn1DI=0;
4882 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4883 DataArrayDouble *coordsTmp=0;
4884 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4885 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4886 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4887 const int *c1DPtr=conn1D->begin();
4888 const int *c1DIPtr=conn1DI->begin();
4889 int nbOfCells=getNumberOfCells();
4890 const int *cPtr=_nodal_connec->getConstPointer();
4891 const int *icPtr=_nodal_connec_index->getConstPointer();
4893 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4895 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4896 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4897 if(!cm.isQuadratic())
4899 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4900 types.insert(typ2); newConn->pushBackSilent(typ2);
4901 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4902 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4903 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4904 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4905 newConnI->pushBackSilent(lastVal);
4906 ret->pushBackSilent(i);
4911 lastVal+=(icPtr[1]-icPtr[0]);
4912 newConnI->pushBackSilent(lastVal);
4913 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4916 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4921 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4922 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4923 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4925 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4928 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4929 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4930 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4933 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4935 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4936 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4938 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4939 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4940 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4942 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4943 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4944 DataArrayInt *conn1D=0,*conn1DI=0;
4945 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4946 DataArrayDouble *coordsTmp=0;
4947 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4948 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4949 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4950 const int *c1DPtr=conn1D->begin();
4951 const int *c1DIPtr=conn1DI->begin();
4952 int nbOfCells=getNumberOfCells();
4953 const int *cPtr=_nodal_connec->getConstPointer();
4954 const int *icPtr=_nodal_connec_index->getConstPointer();
4955 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4956 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4958 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4959 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4960 if(!cm.isQuadratic())
4962 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
4963 types.insert(typ2); newConn->pushBackSilent(typ2);
4964 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4965 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4966 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4967 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
4968 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
4969 newConnI->pushBackSilent(lastVal);
4970 ret->pushBackSilent(i);
4975 lastVal+=(icPtr[1]-icPtr[0]);
4976 newConnI->pushBackSilent(lastVal);
4977 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4980 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4981 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
4986 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4987 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4988 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4990 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4992 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4993 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4994 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4997 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4999 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5000 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5001 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5002 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5004 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5005 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5006 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5008 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5009 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5010 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5011 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5012 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5013 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5014 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5015 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5016 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5017 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5018 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5019 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5020 int nbOfCells=getNumberOfCells();
5021 const int *cPtr=_nodal_connec->getConstPointer();
5022 const int *icPtr=_nodal_connec_index->getConstPointer();
5023 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5024 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5026 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5027 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5028 if(!cm.isQuadratic())
5030 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5031 if(typ2==INTERP_KERNEL::NORM_ERROR)
5033 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5034 throw INTERP_KERNEL::Exception(oss.str().c_str());
5036 types.insert(typ2); newConn->pushBackSilent(typ2);
5037 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5038 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5039 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5040 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5042 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5043 int tmpPos=newConn->getNumberOfTuples();
5044 newConn->pushBackSilent(nodeId2);
5045 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5047 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5048 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5049 newConnI->pushBackSilent(lastVal);
5050 ret->pushBackSilent(i);
5055 lastVal+=(icPtr[1]-icPtr[0]);
5056 newConnI->pushBackSilent(lastVal);
5057 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5060 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5061 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5062 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5063 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5064 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5065 int *c=newConn->getPointer();
5066 const int *cI(newConnI->begin());
5067 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5068 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5069 offset=coordsTmp2Safe->getNumberOfTuples();
5070 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5071 c[cI[(*elt)+1]-1]+=offset;
5072 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5077 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5078 * so that the number of cells remains the same. Quadratic faces are converted to
5079 * polygons. This method works only for 2D meshes in
5080 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5081 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5082 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5083 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5084 * a polylinized edge constituting the input polygon.
5085 * \throw If the coordinates array is not set.
5086 * \throw If the nodal connectivity of cells is not defined.
5087 * \throw If \a this->getMeshDimension() != 2.
5088 * \throw If \a this->getSpaceDimension() != 2.
5090 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5092 checkFullyDefined();
5093 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5094 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5095 double epsa=fabs(eps);
5096 if(epsa<std::numeric_limits<double>::min())
5097 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 !");
5098 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5099 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5100 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5101 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5102 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5103 revDesc1=0; revDescIndx1=0;
5104 mDesc->tessellate2DCurve(eps);
5105 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5106 setCoords(mDesc->getCoords());
5110 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5111 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5112 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5113 * a sub-divided edge.
5114 * \throw If the coordinates array is not set.
5115 * \throw If the nodal connectivity of cells is not defined.
5116 * \throw If \a this->getMeshDimension() != 1.
5117 * \throw If \a this->getSpaceDimension() != 2.
5119 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5121 checkFullyDefined();
5122 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5123 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5124 double epsa=fabs(eps);
5125 if(epsa<std::numeric_limits<double>::min())
5126 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 !");
5127 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5128 int nbCells=getNumberOfCells();
5129 int nbNodes=getNumberOfNodes();
5130 const int *conn=_nodal_connec->getConstPointer();
5131 const int *connI=_nodal_connec_index->getConstPointer();
5132 const double *coords=_coords->getConstPointer();
5133 std::vector<double> addCoo;
5134 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5135 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5136 newConnI->alloc(nbCells+1,1);
5137 int *newConnIPtr=newConnI->getPointer();
5140 INTERP_KERNEL::Node *tmp2[3];
5141 std::set<INTERP_KERNEL::NormalizedCellType> types;
5142 for(int i=0;i<nbCells;i++,newConnIPtr++)
5144 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5145 if(cm.isQuadratic())
5146 {//assert(connI[i+1]-connI[i]-1==3)
5147 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5148 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5149 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5150 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5151 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5154 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5155 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5157 newConnIPtr[1]=(int)newConn.size();
5161 types.insert(INTERP_KERNEL::NORM_SEG2);
5162 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5163 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5164 newConnIPtr[1]=newConnIPtr[0]+3;
5169 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5170 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5171 newConnIPtr[1]=newConnIPtr[0]+3;
5174 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5177 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5178 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5179 newConnArr->alloc((int)newConn.size(),1);
5180 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5181 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5182 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5183 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5184 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5185 std::copy(addCoo.begin(),addCoo.end(),work);
5186 DataArrayDouble::SetArrayIn(newCoords,_coords);
5191 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5192 * In addition, returns an array mapping new cells to old ones. <br>
5193 * This method typically increases the number of cells in \a this mesh
5194 * but the number of nodes remains \b unchanged.
5195 * That's why the 3D splitting policies
5196 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5197 * \param [in] policy - specifies a pattern used for splitting.
5198 * The semantic of \a policy is:
5199 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5200 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5201 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5202 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5203 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5204 * an id of old cell producing it. The caller is to delete this array using
5205 * decrRef() as it is no more needed.
5206 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5207 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5208 * and \a this->getMeshDimension() != 3.
5209 * \throw If \a policy is not one of the four discussed above.
5210 * \throw If the nodal connectivity of cells is not defined.
5212 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5217 return simplexizePol0();
5219 return simplexizePol1();
5220 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5221 return simplexizePlanarFace5();
5222 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5223 return simplexizePlanarFace6();
5225 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)");
5230 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5231 * - 1D: INTERP_KERNEL::NORM_SEG2
5232 * - 2D: INTERP_KERNEL::NORM_TRI3
5233 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5235 * This method is useful for users that need to use P1 field services as
5236 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5237 * All these methods need mesh support containing only simplex cells.
5238 * \return bool - \c true if there are only simplex cells in \a this mesh.
5239 * \throw If the coordinates array is not set.
5240 * \throw If the nodal connectivity of cells is not defined.
5241 * \throw If \a this->getMeshDimension() < 1.
5243 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5245 checkFullyDefined();
5246 int mdim=getMeshDimension();
5247 if(mdim<1 || mdim>3)
5248 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5249 int nbCells=getNumberOfCells();
5250 const int *conn=_nodal_connec->getConstPointer();
5251 const int *connI=_nodal_connec_index->getConstPointer();
5252 for(int i=0;i<nbCells;i++)
5254 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5262 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5264 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5266 checkConnectivityFullyDefined();
5267 if(getMeshDimension()!=2)
5268 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5269 int nbOfCells=getNumberOfCells();
5270 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5271 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5272 ret->alloc(nbOfCells+nbOfCutCells,1);
5273 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5274 int *retPt=ret->getPointer();
5275 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5276 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5277 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5278 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5279 int *pt=newConn->getPointer();
5280 int *ptI=newConnI->getPointer();
5282 const int *oldc=_nodal_connec->getConstPointer();
5283 const int *ci=_nodal_connec_index->getConstPointer();
5284 for(int i=0;i<nbOfCells;i++,ci++)
5286 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5288 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5289 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5290 pt=std::copy(tmp,tmp+8,pt);
5299 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5300 ptI[1]=ptI[0]+ci[1]-ci[0];
5305 _nodal_connec->decrRef();
5306 _nodal_connec=newConn.retn();
5307 _nodal_connec_index->decrRef();
5308 _nodal_connec_index=newConnI.retn();
5315 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5317 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5319 checkConnectivityFullyDefined();
5320 if(getMeshDimension()!=2)
5321 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5322 int nbOfCells=getNumberOfCells();
5323 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5324 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5325 ret->alloc(nbOfCells+nbOfCutCells,1);
5326 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5327 int *retPt=ret->getPointer();
5328 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5329 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5330 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5331 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5332 int *pt=newConn->getPointer();
5333 int *ptI=newConnI->getPointer();
5335 const int *oldc=_nodal_connec->getConstPointer();
5336 const int *ci=_nodal_connec_index->getConstPointer();
5337 for(int i=0;i<nbOfCells;i++,ci++)
5339 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5341 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5342 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5343 pt=std::copy(tmp,tmp+8,pt);
5352 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5353 ptI[1]=ptI[0]+ci[1]-ci[0];
5358 _nodal_connec->decrRef();
5359 _nodal_connec=newConn.retn();
5360 _nodal_connec_index->decrRef();
5361 _nodal_connec_index=newConnI.retn();
5368 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5370 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5372 checkConnectivityFullyDefined();
5373 if(getMeshDimension()!=3)
5374 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5375 int nbOfCells=getNumberOfCells();
5376 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5377 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5378 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5379 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5380 int *retPt=ret->getPointer();
5381 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5382 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5383 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5384 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5385 int *pt=newConn->getPointer();
5386 int *ptI=newConnI->getPointer();
5388 const int *oldc=_nodal_connec->getConstPointer();
5389 const int *ci=_nodal_connec_index->getConstPointer();
5390 for(int i=0;i<nbOfCells;i++,ci++)
5392 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5394 for(int j=0;j<5;j++,pt+=5,ptI++)
5396 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5397 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];
5404 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5405 ptI[1]=ptI[0]+ci[1]-ci[0];
5410 _nodal_connec->decrRef();
5411 _nodal_connec=newConn.retn();
5412 _nodal_connec_index->decrRef();
5413 _nodal_connec_index=newConnI.retn();
5420 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5422 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5424 checkConnectivityFullyDefined();
5425 if(getMeshDimension()!=3)
5426 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5427 int nbOfCells=getNumberOfCells();
5428 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5429 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5430 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5431 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5432 int *retPt=ret->getPointer();
5433 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5434 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5435 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5436 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5437 int *pt=newConn->getPointer();
5438 int *ptI=newConnI->getPointer();
5440 const int *oldc=_nodal_connec->getConstPointer();
5441 const int *ci=_nodal_connec_index->getConstPointer();
5442 for(int i=0;i<nbOfCells;i++,ci++)
5444 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5446 for(int j=0;j<6;j++,pt+=5,ptI++)
5448 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5449 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];
5456 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5457 ptI[1]=ptI[0]+ci[1]-ci[0];
5462 _nodal_connec->decrRef();
5463 _nodal_connec=newConn.retn();
5464 _nodal_connec_index->decrRef();
5465 _nodal_connec_index=newConnI.retn();
5472 * 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.
5473 * This method completly ignore coordinates.
5474 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5475 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5476 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5477 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5479 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5481 checkFullyDefined();
5482 if(getMeshDimension()!=2)
5483 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5484 int nbOfCells=getNumberOfCells();
5485 int *connI=_nodal_connec_index->getPointer();
5487 for(int i=0;i<nbOfCells;i++,connI++)
5489 int offset=descIndex[i];
5490 int nbOfEdges=descIndex[i+1]-offset;
5492 bool ddirect=desc[offset+nbOfEdges-1]>0;
5493 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5494 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5495 for(int j=0;j<nbOfEdges;j++)
5497 bool direct=desc[offset+j]>0;
5498 int edgeId=std::abs(desc[offset+j])-1;
5499 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5501 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5502 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5503 int ref2=direct?id1:id2;
5506 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5507 newConnLgth+=nbOfSubNodes-1;
5512 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5513 throw INTERP_KERNEL::Exception(oss.str().c_str());
5518 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5521 newConnLgth++;//+1 is for cell type
5522 connI[1]=newConnLgth;
5525 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5526 newConn->alloc(newConnLgth,1);
5527 int *work=newConn->getPointer();
5528 for(int i=0;i<nbOfCells;i++)
5530 *work++=INTERP_KERNEL::NORM_POLYGON;
5531 int offset=descIndex[i];
5532 int nbOfEdges=descIndex[i+1]-offset;
5533 for(int j=0;j<nbOfEdges;j++)
5535 bool direct=desc[offset+j]>0;
5536 int edgeId=std::abs(desc[offset+j])-1;
5538 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5541 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5542 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5543 work=std::copy(it,it+nbOfSubNodes-1,work);
5547 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5550 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5554 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5555 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5556 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5557 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5558 * so it can be useful to call mergeNodes() before calling this method.
5559 * \throw If \a this->getMeshDimension() <= 1.
5560 * \throw If the coordinates array is not set.
5561 * \throw If the nodal connectivity of cells is not defined.
5563 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5565 checkFullyDefined();
5566 if(getMeshDimension()<=1)
5567 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5568 int nbOfCells=getNumberOfCells();
5571 int initMeshLgth=getMeshLength();
5572 int *conn=_nodal_connec->getPointer();
5573 int *index=_nodal_connec_index->getPointer();
5577 for(int i=0;i<nbOfCells;i++)
5579 lgthOfCurCell=index[i+1]-posOfCurCell;
5580 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5582 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5583 conn+newPos+1,newLgth);
5584 conn[newPos]=newType;
5586 posOfCurCell=index[i+1];
5589 if(newPos!=initMeshLgth)
5590 _nodal_connec->reAlloc(newPos);
5595 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5596 * A cell is considered to be oriented correctly if an angle between its
5597 * normal vector and a given vector is less than \c PI / \c 2.
5598 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5600 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5602 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5603 * is not cleared before filling in.
5604 * \throw If \a this->getMeshDimension() != 2.
5605 * \throw If \a this->getSpaceDimension() != 3.
5607 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5608 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5610 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5612 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5613 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5614 int nbOfCells=getNumberOfCells();
5615 const int *conn=_nodal_connec->getConstPointer();
5616 const int *connI=_nodal_connec_index->getConstPointer();
5617 const double *coordsPtr=_coords->getConstPointer();
5618 for(int i=0;i<nbOfCells;i++)
5620 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5621 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5623 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5624 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5631 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5632 * considered to be oriented correctly if an angle between its normal vector and a
5633 * given vector is less than \c PI / \c 2.
5634 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5636 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
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::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5646 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5647 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5648 int nbOfCells=getNumberOfCells();
5649 int *conn=_nodal_connec->getPointer();
5650 const int *connI=_nodal_connec_index->getConstPointer();
5651 const double *coordsPtr=_coords->getConstPointer();
5652 bool isModified=false;
5653 for(int i=0;i<nbOfCells;i++)
5655 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5656 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5658 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5659 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5662 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5663 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5664 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5669 _nodal_connec->declareAsNew();
5674 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5675 * oriented facets. The normal vector of the facet should point out of the cell.
5676 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5677 * is not cleared before filling in.
5678 * \throw If \a this->getMeshDimension() != 3.
5679 * \throw If \a this->getSpaceDimension() != 3.
5680 * \throw If the coordinates array is not set.
5681 * \throw If the nodal connectivity of cells is not defined.
5683 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5684 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5686 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5688 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5689 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5690 int nbOfCells=getNumberOfCells();
5691 const int *conn=_nodal_connec->getConstPointer();
5692 const int *connI=_nodal_connec_index->getConstPointer();
5693 const double *coordsPtr=_coords->getConstPointer();
5694 for(int i=0;i<nbOfCells;i++)
5696 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5697 if(type==INTERP_KERNEL::NORM_POLYHED)
5699 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5706 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5708 * \throw If \a this->getMeshDimension() != 3.
5709 * \throw If \a this->getSpaceDimension() != 3.
5710 * \throw If the coordinates array is not set.
5711 * \throw If the nodal connectivity of cells is not defined.
5712 * \throw If the reparation fails.
5714 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5715 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5716 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5718 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5720 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5721 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5722 int nbOfCells=getNumberOfCells();
5723 int *conn=_nodal_connec->getPointer();
5724 const int *connI=_nodal_connec_index->getConstPointer();
5725 const double *coordsPtr=_coords->getConstPointer();
5726 for(int i=0;i<nbOfCells;i++)
5728 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5729 if(type==INTERP_KERNEL::NORM_POLYHED)
5733 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5734 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5736 catch(INTERP_KERNEL::Exception& e)
5738 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5739 throw INTERP_KERNEL::Exception(oss.str().c_str());
5747 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5748 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5749 * according to which the first facet of the cell should be oriented to have the normal vector
5750 * pointing out of cell.
5751 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5752 * cells. The caller is to delete this array using decrRef() as it is no more
5754 * \throw If \a this->getMeshDimension() != 3.
5755 * \throw If \a this->getSpaceDimension() != 3.
5756 * \throw If the coordinates array is not set.
5757 * \throw If the nodal connectivity of cells is not defined.
5759 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5760 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5761 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5763 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5765 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5766 if(getMeshDimension()!=3)
5767 throw INTERP_KERNEL::Exception(msg);
5768 int spaceDim=getSpaceDimension();
5770 throw INTERP_KERNEL::Exception(msg);
5772 int nbOfCells=getNumberOfCells();
5773 int *conn=_nodal_connec->getPointer();
5774 const int *connI=_nodal_connec_index->getConstPointer();
5775 const double *coo=getCoords()->getConstPointer();
5776 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5777 for(int i=0;i<nbOfCells;i++)
5779 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5780 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5782 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5784 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5785 cells->pushBackSilent(i);
5789 return cells.retn();
5793 * This method is a faster method to correct orientation of all 3D cells in \a this.
5794 * 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.
5795 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5797 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5798 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
5800 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5802 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5803 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5804 int nbOfCells=getNumberOfCells();
5805 int *conn=_nodal_connec->getPointer();
5806 const int *connI=_nodal_connec_index->getConstPointer();
5807 const double *coordsPtr=_coords->getConstPointer();
5808 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5809 for(int i=0;i<nbOfCells;i++)
5811 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5814 case INTERP_KERNEL::NORM_TETRA4:
5816 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5818 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5819 ret->pushBackSilent(i);
5823 case INTERP_KERNEL::NORM_PYRA5:
5825 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5827 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5828 ret->pushBackSilent(i);
5832 case INTERP_KERNEL::NORM_PENTA6:
5833 case INTERP_KERNEL::NORM_HEXA8:
5834 case INTERP_KERNEL::NORM_HEXGP12:
5836 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5838 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5839 ret->pushBackSilent(i);
5843 case INTERP_KERNEL::NORM_POLYHED:
5845 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5847 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5848 ret->pushBackSilent(i);
5853 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 !");
5861 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5862 * If it is not the case an exception will be thrown.
5863 * This method is fast because the first cell of \a this is used to compute the plane.
5864 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5865 * \param pos output of size at least 3 used to store a point owned of searched plane.
5867 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5869 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5870 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5871 const int *conn=_nodal_connec->getConstPointer();
5872 const int *connI=_nodal_connec_index->getConstPointer();
5873 const double *coordsPtr=_coords->getConstPointer();
5874 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5875 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5879 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5880 * cells. Currently cells of the following types are treated:
5881 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5882 * For a cell of other type an exception is thrown.
5883 * Space dimension of a 2D mesh can be either 2 or 3.
5884 * The Edge Ratio of a cell \f$t\f$ is:
5885 * \f$\frac{|t|_\infty}{|t|_0}\f$,
5886 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5887 * the smallest edge lengths of \f$t\f$.
5888 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5889 * cells and one time, lying on \a this mesh. The caller is to delete this
5890 * field using decrRef() as it is no more needed.
5891 * \throw If the coordinates array is not set.
5892 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5893 * \throw If the connectivity data array has more than one component.
5894 * \throw If the connectivity data array has a named component.
5895 * \throw If the connectivity index data array has more than one component.
5896 * \throw If the connectivity index data array has a named component.
5897 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
5898 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5899 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
5901 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5904 int spaceDim=getSpaceDimension();
5905 int meshDim=getMeshDimension();
5906 if(spaceDim!=2 && spaceDim!=3)
5907 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5908 if(meshDim!=2 && meshDim!=3)
5909 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5910 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5912 int nbOfCells=getNumberOfCells();
5913 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5914 arr->alloc(nbOfCells,1);
5915 double *pt=arr->getPointer();
5916 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5917 const int *conn=_nodal_connec->getConstPointer();
5918 const int *connI=_nodal_connec_index->getConstPointer();
5919 const double *coo=_coords->getConstPointer();
5921 for(int i=0;i<nbOfCells;i++,pt++)
5923 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5926 case INTERP_KERNEL::NORM_TRI3:
5928 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5929 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5932 case INTERP_KERNEL::NORM_QUAD4:
5934 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5935 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5938 case INTERP_KERNEL::NORM_TETRA4:
5940 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5941 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5945 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5947 conn+=connI[i+1]-connI[i];
5949 ret->setName("EdgeRatio");
5950 ret->synchronizeTimeWithSupport();
5955 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5956 * cells. Currently cells of the following types are treated:
5957 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5958 * For a cell of other type an exception is thrown.
5959 * Space dimension of a 2D mesh can be either 2 or 3.
5960 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5961 * cells and one time, lying on \a this mesh. The caller is to delete this
5962 * field using decrRef() as it is no more needed.
5963 * \throw If the coordinates array is not set.
5964 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5965 * \throw If the connectivity data array has more than one component.
5966 * \throw If the connectivity data array has a named component.
5967 * \throw If the connectivity index data array has more than one component.
5968 * \throw If the connectivity index data array has a named component.
5969 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
5970 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5971 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
5973 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
5976 int spaceDim=getSpaceDimension();
5977 int meshDim=getMeshDimension();
5978 if(spaceDim!=2 && spaceDim!=3)
5979 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
5980 if(meshDim!=2 && meshDim!=3)
5981 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
5982 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5984 int nbOfCells=getNumberOfCells();
5985 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5986 arr->alloc(nbOfCells,1);
5987 double *pt=arr->getPointer();
5988 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5989 const int *conn=_nodal_connec->getConstPointer();
5990 const int *connI=_nodal_connec_index->getConstPointer();
5991 const double *coo=_coords->getConstPointer();
5993 for(int i=0;i<nbOfCells;i++,pt++)
5995 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5998 case INTERP_KERNEL::NORM_TRI3:
6000 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6001 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6004 case INTERP_KERNEL::NORM_QUAD4:
6006 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6007 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6010 case INTERP_KERNEL::NORM_TETRA4:
6012 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6013 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6017 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6019 conn+=connI[i+1]-connI[i];
6021 ret->setName("AspectRatio");
6022 ret->synchronizeTimeWithSupport();
6027 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6028 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6029 * treated: INTERP_KERNEL::NORM_QUAD4.
6030 * For a cell of other type an exception is thrown.
6031 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6032 * cells and one time, lying on \a this mesh. The caller is to delete this
6033 * field using decrRef() as it is no more needed.
6034 * \throw If the coordinates array is not set.
6035 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6036 * \throw If the connectivity data array has more than one component.
6037 * \throw If the connectivity data array has a named component.
6038 * \throw If the connectivity index data array has more than one component.
6039 * \throw If the connectivity index data array has a named component.
6040 * \throw If \a this->getMeshDimension() != 2.
6041 * \throw If \a this->getSpaceDimension() != 3.
6042 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6044 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6047 int spaceDim=getSpaceDimension();
6048 int meshDim=getMeshDimension();
6050 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6052 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6053 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6055 int nbOfCells=getNumberOfCells();
6056 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6057 arr->alloc(nbOfCells,1);
6058 double *pt=arr->getPointer();
6059 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6060 const int *conn=_nodal_connec->getConstPointer();
6061 const int *connI=_nodal_connec_index->getConstPointer();
6062 const double *coo=_coords->getConstPointer();
6064 for(int i=0;i<nbOfCells;i++,pt++)
6066 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6069 case INTERP_KERNEL::NORM_QUAD4:
6071 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6072 *pt=INTERP_KERNEL::quadWarp(tmp);
6076 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6078 conn+=connI[i+1]-connI[i];
6080 ret->setName("Warp");
6081 ret->synchronizeTimeWithSupport();
6087 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6088 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6089 * treated: INTERP_KERNEL::NORM_QUAD4.
6090 * For a cell of other type an exception is thrown.
6091 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6092 * cells and one time, lying on \a this mesh. The caller is to delete this
6093 * field using decrRef() as it is no more needed.
6094 * \throw If the coordinates array is not set.
6095 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6096 * \throw If the connectivity data array has more than one component.
6097 * \throw If the connectivity data array has a named component.
6098 * \throw If the connectivity index data array has more than one component.
6099 * \throw If the connectivity index data array has a named component.
6100 * \throw If \a this->getMeshDimension() != 2.
6101 * \throw If \a this->getSpaceDimension() != 3.
6102 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6104 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6107 int spaceDim=getSpaceDimension();
6108 int meshDim=getMeshDimension();
6110 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6112 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6113 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6115 int nbOfCells=getNumberOfCells();
6116 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6117 arr->alloc(nbOfCells,1);
6118 double *pt=arr->getPointer();
6119 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6120 const int *conn=_nodal_connec->getConstPointer();
6121 const int *connI=_nodal_connec_index->getConstPointer();
6122 const double *coo=_coords->getConstPointer();
6124 for(int i=0;i<nbOfCells;i++,pt++)
6126 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6129 case INTERP_KERNEL::NORM_QUAD4:
6131 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6132 *pt=INTERP_KERNEL::quadSkew(tmp);
6136 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6138 conn+=connI[i+1]-connI[i];
6140 ret->setName("Skew");
6141 ret->synchronizeTimeWithSupport();
6146 * This method aggregate the bbox of each cell and put it into bbox parameter.
6147 * \param bbox out parameter of size 2*spacedim*nbOfcells.
6149 void MEDCouplingUMesh::getBoundingBoxForBBTree(std::vector<double>& bbox) const
6151 int spaceDim=getSpaceDimension();
6152 int nbOfCells=getNumberOfCells();
6153 bbox.resize(2*nbOfCells*spaceDim);
6154 for(int i=0;i<nbOfCells*spaceDim;i++)
6156 bbox[2*i]=std::numeric_limits<double>::max();
6157 bbox[2*i+1]=-std::numeric_limits<double>::max();
6159 const double *coordsPtr=_coords->getConstPointer();
6160 const int *conn=_nodal_connec->getConstPointer();
6161 const int *connI=_nodal_connec_index->getConstPointer();
6162 for(int i=0;i<nbOfCells;i++)
6164 int offset=connI[i]+1;
6165 int nbOfNodesForCell=connI[i+1]-offset;
6166 for(int j=0;j<nbOfNodesForCell;j++)
6168 int nodeId=conn[offset+j];
6170 for(int k=0;k<spaceDim;k++)
6172 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6173 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6181 namespace ParaMEDMEMImpl
6186 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6187 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6196 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6197 bool operator() (const int& pos) { return _conn[pos]==_val; }
6207 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6208 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6209 * \a this is composed in cell types.
6210 * The returned array is of size 3*n where n is the number of different types present in \a this.
6211 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6212 * This parameter is kept only for compatibility with other methode listed above.
6214 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6216 checkConnectivityFullyDefined();
6217 const int *conn=_nodal_connec->getConstPointer();
6218 const int *connI=_nodal_connec_index->getConstPointer();
6219 const int *work=connI;
6220 int nbOfCells=getNumberOfCells();
6221 std::size_t n=getAllTypes().size();
6222 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6223 std::set<INTERP_KERNEL::NormalizedCellType> types;
6224 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6226 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6227 if(types.find(typ)!=types.end())
6229 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6230 oss << " is not contiguous !";
6231 throw INTERP_KERNEL::Exception(oss.str().c_str());
6235 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6236 ret[3*i+1]=(int)std::distance(work,work2);
6243 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6244 * only for types cell, type node is not managed.
6245 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6246 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6247 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6248 * If 2 or more same geometric type is in \a code and exception is thrown too.
6250 * This method firstly checks
6251 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6252 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6253 * an exception is thrown too.
6255 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6256 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6257 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6259 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6262 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6263 std::size_t sz=code.size();
6266 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6267 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6269 bool isNoPflUsed=true;
6270 for(std::size_t i=0;i<n;i++)
6271 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6273 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6275 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6276 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6277 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6280 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6283 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6284 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6285 if(types.size()==_types.size())
6288 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6290 int *retPtr=ret->getPointer();
6291 const int *connI=_nodal_connec_index->getConstPointer();
6292 const int *conn=_nodal_connec->getConstPointer();
6293 int nbOfCells=getNumberOfCells();
6296 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6298 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6299 int offset=(int)std::distance(connI,i);
6300 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6301 int nbOfCellsOfCurType=(int)std::distance(i,j);
6302 if(code[3*kk+2]==-1)
6303 for(int k=0;k<nbOfCellsOfCurType;k++)
6307 int idInIdsPerType=code[3*kk+2];
6308 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6310 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6313 zePfl->checkAllocated();
6314 if(zePfl->getNumberOfComponents()==1)
6316 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6318 if(*k>=0 && *k<nbOfCellsOfCurType)
6319 *retPtr=(*k)+offset;
6322 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6323 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6324 throw INTERP_KERNEL::Exception(oss.str().c_str());
6329 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6332 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6336 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6337 oss << " should be in [0," << idsPerType.size() << ") !";
6338 throw INTERP_KERNEL::Exception(oss.str().c_str());
6347 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6348 * 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.
6349 * 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.
6350 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6352 * \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.
6353 * \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,
6354 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6355 * \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.
6356 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6357 * \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
6359 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6362 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6363 if(profile->getNumberOfComponents()!=1)
6364 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6365 checkConnectivityFullyDefined();
6366 const int *conn=_nodal_connec->getConstPointer();
6367 const int *connI=_nodal_connec_index->getConstPointer();
6368 int nbOfCells=getNumberOfCells();
6369 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6370 std::vector<int> typeRangeVals(1);
6371 for(const int *i=connI;i!=connI+nbOfCells;)
6373 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6374 if(std::find(types.begin(),types.end(),curType)!=types.end())
6376 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6378 types.push_back(curType);
6379 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6380 typeRangeVals.push_back((int)std::distance(connI,i));
6383 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6384 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6385 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6386 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6387 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6389 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6390 code.resize(3*nbOfCastsFinal);
6391 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6392 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6393 for(int i=0;i<nbOfCastsFinal;i++)
6395 int castId=castsPresent->getIJ(i,0);
6396 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6397 idsInPflPerType2.push_back(tmp3);
6398 code[3*i]=(int)types[castId];
6399 code[3*i+1]=tmp3->getNumberOfTuples();
6400 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6401 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6403 tmp4->copyStringInfoFrom(*profile);
6404 idsPerType2.push_back(tmp4);
6405 code[3*i+2]=(int)idsPerType2.size()-1;
6412 std::size_t sz2=idsInPflPerType2.size();
6413 idsInPflPerType.resize(sz2);
6414 for(std::size_t i=0;i<sz2;i++)
6416 DataArrayInt *locDa=idsInPflPerType2[i];
6418 idsInPflPerType[i]=locDa;
6420 std::size_t sz=idsPerType2.size();
6421 idsPerType.resize(sz);
6422 for(std::size_t i=0;i<sz;i++)
6424 DataArrayInt *locDa=idsPerType2[i];
6426 idsPerType[i]=locDa;
6431 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6432 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6433 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6434 * 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.
6436 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6438 checkFullyDefined();
6439 nM1LevMesh->checkFullyDefined();
6440 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6441 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6442 if(_coords!=nM1LevMesh->getCoords())
6443 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6444 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6445 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6446 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6447 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6448 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6449 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6450 tmp->setConnectivity(tmp0,tmp1);
6451 tmp->renumberCells(ret0->getConstPointer(),false);
6452 revDesc=tmp->getNodalConnectivity();
6453 revDescIndx=tmp->getNodalConnectivityIndex();
6454 DataArrayInt *ret=0;
6455 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6458 ret->getMaxValue(tmp2);
6460 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6461 throw INTERP_KERNEL::Exception(oss.str().c_str());
6466 revDescIndx->incrRef();
6469 meshnM1Old2New=ret0;
6474 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6475 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6476 * in "Old to New" mode.
6477 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6478 * this array using decrRef() as it is no more needed.
6479 * \throw If the nodal connectivity of cells is not defined.
6481 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6483 checkConnectivityFullyDefined();
6484 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6485 renumberCells(ret->getConstPointer(),false);
6490 * This methods checks that cells are sorted by their types.
6491 * This method makes asumption (no check) that connectivity is correctly set before calling.
6493 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6495 checkFullyDefined();
6496 const int *conn=_nodal_connec->getConstPointer();
6497 const int *connI=_nodal_connec_index->getConstPointer();
6498 int nbOfCells=getNumberOfCells();
6499 std::set<INTERP_KERNEL::NormalizedCellType> types;
6500 for(const int *i=connI;i!=connI+nbOfCells;)
6502 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6503 if(types.find(curType)!=types.end())
6505 types.insert(curType);
6506 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6512 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6513 * The geometric type order is specified by MED file.
6515 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6517 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6519 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6523 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6524 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6525 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6526 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6528 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6530 checkFullyDefined();
6531 const int *conn=_nodal_connec->getConstPointer();
6532 const int *connI=_nodal_connec_index->getConstPointer();
6533 int nbOfCells=getNumberOfCells();
6537 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6538 for(const int *i=connI;i!=connI+nbOfCells;)
6540 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6541 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6542 if(isTypeExists!=orderEnd)
6544 int pos=(int)std::distance(orderBg,isTypeExists);
6548 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6552 if(sg.find(curType)==sg.end())
6554 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6565 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6566 * 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
6567 * 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'.
6569 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6571 checkConnectivityFullyDefined();
6572 int nbOfCells=getNumberOfCells();
6573 const int *conn=_nodal_connec->getConstPointer();
6574 const int *connI=_nodal_connec_index->getConstPointer();
6575 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6576 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6577 tmpa->alloc(nbOfCells,1);
6578 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6579 tmpb->fillWithZero();
6580 int *tmp=tmpa->getPointer();
6581 int *tmp2=tmpb->getPointer();
6582 for(const int *i=connI;i!=connI+nbOfCells;i++)
6584 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6587 int pos=(int)std::distance(orderBg,where);
6589 tmp[std::distance(connI,i)]=pos;
6593 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6594 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6595 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6596 throw INTERP_KERNEL::Exception(oss.str().c_str());
6599 nbPerType=tmpb.retn();
6604 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6606 * \return a new object containing the old to new correspondance.
6608 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6610 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6612 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6616 * 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.
6617 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6618 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6619 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6621 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6623 DataArrayInt *nbPerType=0;
6624 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6625 nbPerType->decrRef();
6626 return tmpa->buildPermArrPerLevel();
6630 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6631 * The number of cells remains unchanged after the call of this method.
6632 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6633 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6635 * \return the array giving the correspondance old to new.
6637 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6639 checkFullyDefined();
6641 const int *conn=_nodal_connec->getConstPointer();
6642 const int *connI=_nodal_connec_index->getConstPointer();
6643 int nbOfCells=getNumberOfCells();
6644 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6645 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6646 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6648 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6649 types.push_back(curType);
6650 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6652 DataArrayInt *ret=DataArrayInt::New();
6653 ret->alloc(nbOfCells,1);
6654 int *retPtr=ret->getPointer();
6655 std::fill(retPtr,retPtr+nbOfCells,-1);
6657 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6659 for(const int *i=connI;i!=connI+nbOfCells;i++)
6660 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6661 retPtr[std::distance(connI,i)]=newCellId++;
6663 renumberCells(retPtr,false);
6668 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6669 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6670 * This method makes asumption that connectivity is correctly set before calling.
6672 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6674 checkFullyDefined();
6675 const int *conn=_nodal_connec->getConstPointer();
6676 const int *connI=_nodal_connec_index->getConstPointer();
6677 int nbOfCells=getNumberOfCells();
6678 std::vector<MEDCouplingUMesh *> ret;
6679 for(const int *i=connI;i!=connI+nbOfCells;)
6681 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6682 int beginCellId=(int)std::distance(connI,i);
6683 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6684 int endCellId=(int)std::distance(connI,i);
6685 int sz=endCellId-beginCellId;
6686 int *cells=new int[sz];
6687 for(int j=0;j<sz;j++)
6688 cells[j]=beginCellId+j;
6689 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6697 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6698 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6699 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6701 * \return a newly allocated instance, that the caller must manage.
6702 * \throw If \a this contains more than one geometric type.
6703 * \throw If the nodal connectivity of \a this is not fully defined.
6704 * \throw If the internal data is not coherent.
6706 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6708 checkConnectivityFullyDefined();
6709 if(_types.size()!=1)
6710 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6711 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6712 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName(),typ);
6713 ret->setCoords(getCoords());
6714 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6717 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6718 retC->setNodalConnectivity(c);
6722 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6724 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6725 DataArrayInt *c=0,*ci=0;
6726 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6727 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6728 retD->setNodalConnectivity(cs,cis);
6733 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6735 checkConnectivityFullyDefined();
6736 if(_types.size()!=1)
6737 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6738 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6739 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6742 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6743 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6744 throw INTERP_KERNEL::Exception(oss.str().c_str());
6746 int nbCells=getNumberOfCells();
6748 int nbNodesPerCell=(int)cm.getNumberOfNodes();
6749 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6750 int *outPtr=connOut->getPointer();
6751 const int *conn=_nodal_connec->begin();
6752 const int *connI=_nodal_connec_index->begin();
6754 for(int i=0;i<nbCells;i++,connI++)
6756 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6757 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6760 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : there something wrong in cell #" << i << " ! The type of cell is not those expected, or the length of nodal connectivity is not those expected (" << nbNodesPerCell-1 << ") !";
6761 throw INTERP_KERNEL::Exception(oss.str().c_str());
6764 return connOut.retn();
6767 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const throw(INTERP_KERNEL::Exception)
6769 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
6770 checkConnectivityFullyDefined();
6771 if(_types.size()!=1)
6772 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6773 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6775 throw INTERP_KERNEL::Exception(msg0);
6776 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6777 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6778 int *cp(c->getPointer()),*cip(ci->getPointer());
6779 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6781 for(int i=0;i<nbCells;i++,cip++,incip++)
6783 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6784 int delta(stop-strt);
6787 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6788 cp=std::copy(incp+strt,incp+stop,cp);
6790 throw INTERP_KERNEL::Exception(msg0);
6793 throw INTERP_KERNEL::Exception(msg0);
6794 cip[1]=cip[0]+delta;
6796 nodalConn=c.retn(); nodalConnIndex=ci.retn();
6800 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6801 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6802 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6803 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6804 * are not used here to avoid the build of big permutation array.
6806 * \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
6807 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6808 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6809 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6810 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6811 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
6812 * \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
6813 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6815 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6816 DataArrayInt *&szOfCellGrpOfSameType,
6817 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6819 std::vector<const MEDCouplingUMesh *> ms2;
6820 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6823 (*it)->checkConnectivityFullyDefined();
6827 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6828 const DataArrayDouble *refCoo=ms2[0]->getCoords();
6829 int meshDim=ms2[0]->getMeshDimension();
6830 std::vector<const MEDCouplingUMesh *> m1ssm;
6831 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6833 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6834 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6836 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6837 ret1->alloc(0,1); ret2->alloc(0,1);
6838 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6840 if(meshDim!=(*it)->getMeshDimension())
6841 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6842 if(refCoo!=(*it)->getCoords())
6843 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6844 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6845 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6846 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6847 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6849 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6850 m1ssmSingleAuto.push_back(singleCell);
6851 m1ssmSingle.push_back(singleCell);
6852 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6855 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6856 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6857 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6858 for(std::size_t i=0;i<m1ssm.size();i++)
6859 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6860 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6861 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6862 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6867 * This method returns a newly created DataArrayInt instance.
6868 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6870 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6872 checkFullyDefined();
6873 const int *conn=_nodal_connec->getConstPointer();
6874 const int *connIndex=_nodal_connec_index->getConstPointer();
6875 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6876 for(const int *w=begin;w!=end;w++)
6877 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6878 ret->pushBackSilent(*w);
6883 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6884 * are in [0:getNumberOfCells())
6886 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6888 checkFullyDefined();
6889 const int *conn=_nodal_connec->getConstPointer();
6890 const int *connI=_nodal_connec_index->getConstPointer();
6891 int nbOfCells=getNumberOfCells();
6892 std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6893 int *tmp=new int[nbOfCells];
6894 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6897 for(const int *i=connI;i!=connI+nbOfCells;i++)
6898 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6899 tmp[std::distance(connI,i)]=j++;
6901 DataArrayInt *ret=DataArrayInt::New();
6902 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6903 ret->copyStringInfoFrom(*da);
6904 int *retPtr=ret->getPointer();
6905 const int *daPtr=da->getConstPointer();
6906 int nbOfElems=da->getNbOfElems();
6907 for(int k=0;k<nbOfElems;k++)
6908 retPtr[k]=tmp[daPtr[k]];
6914 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6915 * This method \b works \b for mesh sorted by type.
6916 * cells whose ids is in 'idsPerGeoType' array.
6917 * This method conserves coords and name of mesh.
6919 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6921 std::vector<int> code=getDistributionOfTypes();
6922 std::size_t nOfTypesInThis=code.size()/3;
6923 int sz=0,szOfType=0;
6924 for(std::size_t i=0;i<nOfTypesInThis;i++)
6929 szOfType=code[3*i+1];
6931 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6932 if(*work<0 || *work>=szOfType)
6934 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6935 oss << ". It should be in [0," << szOfType << ") !";
6936 throw INTERP_KERNEL::Exception(oss.str().c_str());
6938 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6939 int *idsPtr=idsTokeep->getPointer();
6941 for(std::size_t i=0;i<nOfTypesInThis;i++)
6944 for(int j=0;j<code[3*i+1];j++)
6947 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6948 offset+=code[3*i+1];
6950 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6951 ret->copyTinyInfoFrom(this);
6956 * This method returns a vector of size 'this->getNumberOfCells()'.
6957 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
6959 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
6961 int ncell=getNumberOfCells();
6962 std::vector<bool> ret(ncell);
6963 const int *cI=getNodalConnectivityIndex()->getConstPointer();
6964 const int *c=getNodalConnectivity()->getConstPointer();
6965 for(int i=0;i<ncell;i++)
6967 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
6968 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6969 ret[i]=cm.isQuadratic();
6975 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
6977 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
6979 if(other->getType()!=UNSTRUCTURED)
6980 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
6981 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
6982 return MergeUMeshes(this,otherC);
6986 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
6987 * computed by averaging coordinates of cell nodes, so this method is not a right
6988 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
6989 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
6990 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
6991 * components. The caller is to delete this array using decrRef() as it is
6993 * \throw If the coordinates array is not set.
6994 * \throw If the nodal connectivity of cells is not defined.
6995 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
6997 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
6999 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7000 int spaceDim=getSpaceDimension();
7001 int nbOfCells=getNumberOfCells();
7002 ret->alloc(nbOfCells,spaceDim);
7003 ret->copyStringInfoFrom(*getCoords());
7004 double *ptToFill=ret->getPointer();
7005 const int *nodal=_nodal_connec->getConstPointer();
7006 const int *nodalI=_nodal_connec_index->getConstPointer();
7007 const double *coor=_coords->getConstPointer();
7008 for(int i=0;i<nbOfCells;i++)
7010 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7011 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7018 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7019 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7021 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7022 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7024 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7025 * \throw If \a this is not fully defined (coordinates and connectivity)
7026 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7028 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7030 checkFullyDefined();
7031 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7032 int spaceDim=getSpaceDimension();
7033 int nbOfCells=getNumberOfCells();
7034 int nbOfNodes=getNumberOfNodes();
7035 ret->alloc(nbOfCells,spaceDim);
7036 double *ptToFill=ret->getPointer();
7037 const int *nodal=_nodal_connec->getConstPointer();
7038 const int *nodalI=_nodal_connec_index->getConstPointer();
7039 const double *coor=_coords->getConstPointer();
7040 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7042 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7043 std::fill(ptToFill,ptToFill+spaceDim,0.);
7044 if(type!=INTERP_KERNEL::NORM_POLYHED)
7046 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7048 if(*conn>=0 && *conn<nbOfNodes)
7049 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7052 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7053 throw INTERP_KERNEL::Exception(oss.str().c_str());
7056 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7057 if(nbOfNodesInCell>0)
7058 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7061 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7062 throw INTERP_KERNEL::Exception(oss.str().c_str());
7067 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7069 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7071 if(*it>=0 && *it<nbOfNodes)
7072 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7075 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7076 throw INTERP_KERNEL::Exception(oss.str().c_str());
7080 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7083 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7084 throw INTERP_KERNEL::Exception(oss.str().c_str());
7092 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7093 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7094 * are specified via an array of cell ids.
7095 * \warning Validity of the specified cell ids is not checked!
7096 * Valid range is [ 0, \a this->getNumberOfCells() ).
7097 * \param [in] begin - an array of cell ids of interest.
7098 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7099 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7100 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7101 * caller is to delete this array using decrRef() as it is no more needed.
7102 * \throw If the coordinates array is not set.
7103 * \throw If the nodal connectivity of cells is not defined.
7105 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7106 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7108 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7110 DataArrayDouble *ret=DataArrayDouble::New();
7111 int spaceDim=getSpaceDimension();
7112 int nbOfTuple=(int)std::distance(begin,end);
7113 ret->alloc(nbOfTuple,spaceDim);
7114 double *ptToFill=ret->getPointer();
7115 double *tmp=new double[spaceDim];
7116 const int *nodal=_nodal_connec->getConstPointer();
7117 const int *nodalI=_nodal_connec_index->getConstPointer();
7118 const double *coor=_coords->getConstPointer();
7119 for(const int *w=begin;w!=end;w++)
7121 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7122 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7130 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7133 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7136 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7137 da->checkAllocated();
7138 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7140 int nbOfTuples=da->getNumberOfTuples();
7141 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7142 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7143 c->alloc(2*nbOfTuples,1);
7144 cI->alloc(nbOfTuples+1,1);
7145 int *cp=c->getPointer();
7146 int *cip=cI->getPointer();
7148 for(int i=0;i<nbOfTuples;i++)
7150 *cp++=INTERP_KERNEL::NORM_POINT1;
7154 ret->setConnectivity(c,cI,true);
7158 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7159 * Cells and nodes of
7160 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7161 * \param [in] mesh1 - the first mesh.
7162 * \param [in] mesh2 - the second mesh.
7163 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7164 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7165 * is no more needed.
7166 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7167 * \throw If the coordinates array is not set in none of the meshes.
7168 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7169 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7171 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7173 std::vector<const MEDCouplingUMesh *> tmp(2);
7174 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7175 return MergeUMeshes(tmp);
7179 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7180 * Cells and nodes of
7181 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7182 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7183 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7184 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7185 * is no more needed.
7186 * \throw If \a a.size() == 0.
7187 * \throw If \a a[ *i* ] == NULL.
7188 * \throw If the coordinates array is not set in none of the meshes.
7189 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7190 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7192 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7194 std::size_t sz=a.size();
7196 return MergeUMeshesLL(a);
7197 for(std::size_t ii=0;ii<sz;ii++)
7200 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7201 throw INTERP_KERNEL::Exception(oss.str().c_str());
7203 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7204 std::vector< const MEDCouplingUMesh * > aa(sz);
7206 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7208 const MEDCouplingUMesh *cur=a[i];
7209 const DataArrayDouble *coo=cur->getCoords();
7211 spaceDim=coo->getNumberOfComponents();
7214 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7215 for(std::size_t i=0;i<sz;i++)
7217 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7220 return MergeUMeshesLL(aa);
7225 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7228 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7229 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7230 int meshDim=(*it)->getMeshDimension();
7231 int nbOfCells=(*it)->getNumberOfCells();
7232 int meshLgth=(*it++)->getMeshLength();
7233 for(;it!=a.end();it++)
7235 if(meshDim!=(*it)->getMeshDimension())
7236 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7237 nbOfCells+=(*it)->getNumberOfCells();
7238 meshLgth+=(*it)->getMeshLength();
7240 std::vector<const MEDCouplingPointSet *> aps(a.size());
7241 std::copy(a.begin(),a.end(),aps.begin());
7242 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7243 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7244 ret->setCoords(pts);
7245 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7246 c->alloc(meshLgth,1);
7247 int *cPtr=c->getPointer();
7248 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7249 cI->alloc(nbOfCells+1,1);
7250 int *cIPtr=cI->getPointer();
7254 for(it=a.begin();it!=a.end();it++)
7256 int curNbOfCell=(*it)->getNumberOfCells();
7257 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7258 const int *curC=(*it)->_nodal_connec->getConstPointer();
7259 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7260 for(int j=0;j<curNbOfCell;j++)
7262 const int *src=curC+curCI[j];
7264 for(;src!=curC+curCI[j+1];src++,cPtr++)
7272 offset+=curCI[curNbOfCell];
7273 offset2+=(*it)->getNumberOfNodes();
7276 ret->setConnectivity(c,cI,true);
7283 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7284 * dimension and sharing the node coordinates array.
7285 * All cells of the first mesh precede all cells of the second mesh
7286 * within the result mesh.
7287 * \param [in] mesh1 - the first mesh.
7288 * \param [in] mesh2 - the second mesh.
7289 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7290 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7291 * is no more needed.
7292 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7293 * \throw If the meshes do not share the node coordinates array.
7294 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7295 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7297 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7299 std::vector<const MEDCouplingUMesh *> tmp(2);
7300 tmp[0]=mesh1; tmp[1]=mesh2;
7301 return MergeUMeshesOnSameCoords(tmp);
7305 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7306 * dimension and sharing the node coordinates array.
7307 * All cells of the *i*-th mesh precede all cells of the
7308 * (*i*+1)-th mesh within the result mesh.
7309 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7310 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7311 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7312 * is no more needed.
7313 * \throw If \a a.size() == 0.
7314 * \throw If \a a[ *i* ] == NULL.
7315 * \throw If the meshes do not share the node coordinates array.
7316 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7317 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7319 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7322 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7323 for(std::size_t ii=0;ii<meshes.size();ii++)
7326 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7327 throw INTERP_KERNEL::Exception(oss.str().c_str());
7329 const DataArrayDouble *coords=meshes.front()->getCoords();
7330 int meshDim=meshes.front()->getMeshDimension();
7331 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7333 int meshIndexLgth=0;
7334 for(;iter!=meshes.end();iter++)
7336 if(coords!=(*iter)->getCoords())
7337 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7338 if(meshDim!=(*iter)->getMeshDimension())
7339 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7340 meshLgth+=(*iter)->getMeshLength();
7341 meshIndexLgth+=(*iter)->getNumberOfCells();
7343 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7344 nodal->alloc(meshLgth,1);
7345 int *nodalPtr=nodal->getPointer();
7346 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7347 nodalIndex->alloc(meshIndexLgth+1,1);
7348 int *nodalIndexPtr=nodalIndex->getPointer();
7350 for(iter=meshes.begin();iter!=meshes.end();iter++)
7352 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7353 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7354 int nbOfCells=(*iter)->getNumberOfCells();
7355 int meshLgth2=(*iter)->getMeshLength();
7356 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7357 if(iter!=meshes.begin())
7358 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7360 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7363 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7364 ret->setName("merge");
7365 ret->setMeshDimension(meshDim);
7366 ret->setConnectivity(nodal,nodalIndex,true);
7367 ret->setCoords(coords);
7372 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7373 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7374 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7375 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7376 * New" mode are returned for each input mesh.
7377 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7378 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7379 * valid values [0,1,2], see zipConnectivityTraducer().
7380 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7381 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7382 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7384 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7385 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7386 * is no more needed.
7387 * \throw If \a meshes.size() == 0.
7388 * \throw If \a meshes[ *i* ] == NULL.
7389 * \throw If the meshes do not share the node coordinates array.
7390 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7391 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7392 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7393 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7395 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7397 //All checks are delegated to MergeUMeshesOnSameCoords
7398 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7399 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7400 corr.resize(meshes.size());
7401 std::size_t nbOfMeshes=meshes.size();
7403 const int *o2nPtr=o2n->getConstPointer();
7404 for(std::size_t i=0;i<nbOfMeshes;i++)
7406 DataArrayInt *tmp=DataArrayInt::New();
7407 int curNbOfCells=meshes[i]->getNumberOfCells();
7408 tmp->alloc(curNbOfCells,1);
7409 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7410 offset+=curNbOfCells;
7411 tmp->setName(meshes[i]->getName());
7418 * Makes all given meshes share the nodal connectivity array. The common connectivity
7419 * array is created by concatenating the connectivity arrays of all given meshes. All
7420 * the given meshes must be of the same space dimension but dimension of cells **can
7421 * differ**. 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 * \throw If any of \a meshes is NULL.
7426 * \throw If the coordinates array is not set in any of \a meshes.
7427 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7428 * \throw If \a meshes are of different space dimension.
7430 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7432 std::size_t sz=meshes.size();
7435 std::vector< const DataArrayDouble * > coords(meshes.size());
7436 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7437 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7441 (*it)->checkConnectivityFullyDefined();
7442 const DataArrayDouble *coo=(*it)->getCoords();
7447 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7448 oss << " has no coordinate array defined !";
7449 throw INTERP_KERNEL::Exception(oss.str().c_str());
7454 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7455 oss << " is null !";
7456 throw INTERP_KERNEL::Exception(oss.str().c_str());
7459 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7460 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7461 int offset=(*it)->getNumberOfNodes();
7462 (*it++)->setCoords(res);
7463 for(;it!=meshes.end();it++)
7465 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7466 (*it)->setCoords(res);
7467 (*it)->shiftNodeNumbersInConn(offset);
7468 offset+=oldNumberOfNodes;
7473 * Merges nodes coincident with a given precision within all given meshes that share
7474 * the nodal connectivity array. The given meshes **can be of different** mesh
7475 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7476 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7477 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7478 * \param [in,out] meshes - a vector of meshes to update.
7479 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7480 * \throw If any of \a meshes is NULL.
7481 * \throw If the \a meshes do not share the same node coordinates array.
7482 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7484 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7488 std::set<const DataArrayDouble *> s;
7489 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7492 s.insert((*it)->getCoords());
7495 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 !";
7496 throw INTERP_KERNEL::Exception(oss.str().c_str());
7501 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 !";
7502 throw INTERP_KERNEL::Exception(oss.str().c_str());
7504 const DataArrayDouble *coo=*(s.begin());
7508 DataArrayInt *comm,*commI;
7509 coo->findCommonTuples(eps,-1,comm,commI);
7510 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7511 int oldNbOfNodes=coo->getNumberOfTuples();
7513 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7514 if(oldNbOfNodes==newNbOfNodes)
7516 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7517 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7519 (*it)->renumberNodesInConn(o2n->getConstPointer());
7520 (*it)->setCoords(newCoords);
7525 * 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.
7526 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7527 * \param isQuad specifies the policy of connectivity.
7528 * @ret in/out parameter in which the result will be append
7530 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7532 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7533 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7534 ret.push_back(cm.getExtrudedType());
7535 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7538 case INTERP_KERNEL::NORM_POINT1:
7540 ret.push_back(connBg[1]);
7541 ret.push_back(connBg[1]+nbOfNodesPerLev);
7544 case INTERP_KERNEL::NORM_SEG2:
7546 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7547 ret.insert(ret.end(),conn,conn+4);
7550 case INTERP_KERNEL::NORM_SEG3:
7552 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7553 ret.insert(ret.end(),conn,conn+8);
7556 case INTERP_KERNEL::NORM_QUAD4:
7558 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7559 ret.insert(ret.end(),conn,conn+8);
7562 case INTERP_KERNEL::NORM_TRI3:
7564 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7565 ret.insert(ret.end(),conn,conn+6);
7568 case INTERP_KERNEL::NORM_TRI6:
7570 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,
7571 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7572 ret.insert(ret.end(),conn,conn+15);
7575 case INTERP_KERNEL::NORM_QUAD8:
7578 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7579 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7580 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7582 ret.insert(ret.end(),conn,conn+20);
7585 case INTERP_KERNEL::NORM_POLYGON:
7587 std::back_insert_iterator< std::vector<int> > ii(ret);
7588 std::copy(connBg+1,connEnd,ii);
7590 std::reverse_iterator<const int *> rConnBg(connEnd);
7591 std::reverse_iterator<const int *> rConnEnd(connBg+1);
7592 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7593 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7594 for(std::size_t i=0;i<nbOfRadFaces;i++)
7597 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7598 std::copy(conn,conn+4,ii);
7603 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7608 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7610 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7612 double v[3]={0.,0.,0.};
7613 std::size_t sz=std::distance(begin,end);
7616 for(std::size_t i=0;i<sz;i++)
7618 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];
7619 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7620 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7622 return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7626 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7628 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7630 std::vector<std::pair<int,int> > edges;
7631 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7632 const int *bgFace=begin;
7633 for(std::size_t i=0;i<nbOfFaces;i++)
7635 const int *endFace=std::find(bgFace+1,end,-1);
7636 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7637 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7639 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7640 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7642 edges.push_back(p1);
7646 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7650 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7652 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7654 double vec0[3],vec1[3];
7655 std::size_t sz=std::distance(begin,end);
7657 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7658 int nbOfNodes=(int)sz/2;
7659 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7660 const double *pt0=coords+3*begin[0];
7661 const double *pt1=coords+3*begin[nbOfNodes];
7662 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7663 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7666 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7668 std::size_t sz=std::distance(begin,end);
7669 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7670 std::size_t nbOfNodes(sz/2);
7671 std::copy(begin,end,(int *)tmp);
7672 for(std::size_t j=1;j<nbOfNodes;j++)
7674 begin[j]=tmp[nbOfNodes-j];
7675 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7679 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7681 std::size_t sz=std::distance(begin,end);
7683 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7684 double vec0[3],vec1[3];
7685 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7686 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];
7687 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;
7690 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7692 std::size_t sz=std::distance(begin,end);
7694 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7696 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7697 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7698 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7702 * 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 )
7703 * 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
7706 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7707 * \param [in] coords the coordinates with nb of components exactly equal to 3
7708 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7709 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7710 * \param [out] res the result is put at the end of the vector without any alteration of the data.
7712 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7714 int nbFaces=std::count(begin+1,end,-1)+1;
7715 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7716 double *vPtr=v->getPointer();
7717 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7718 double *pPtr=p->getPointer();
7719 const int *stFaceConn=begin+1;
7720 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7722 const int *endFaceConn=std::find(stFaceConn,end,-1);
7723 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7724 stFaceConn=endFaceConn+1;
7726 pPtr=p->getPointer(); vPtr=v->getPointer();
7727 DataArrayInt *comm1=0,*commI1=0;
7728 v->findCommonTuples(eps,-1,comm1,commI1);
7729 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7730 const int *comm1Ptr=comm1->getConstPointer();
7731 const int *commI1Ptr=commI1->getConstPointer();
7732 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7733 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7735 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7736 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7737 mm->finishInsertingCells();
7739 for(int i=0;i<nbOfGrps1;i++)
7741 int vecId=comm1Ptr[commI1Ptr[i]];
7742 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7743 DataArrayInt *comm2=0,*commI2=0;
7744 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7745 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7746 const int *comm2Ptr=comm2->getConstPointer();
7747 const int *commI2Ptr=commI2->getConstPointer();
7748 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7749 for(int j=0;j<nbOfGrps2;j++)
7751 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7753 res->insertAtTheEnd(begin,end);
7754 res->pushBackSilent(-1);
7758 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7759 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7760 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7761 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7762 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7763 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7764 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7765 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7766 const int *idsNodePtr=idsNode->getConstPointer();
7767 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];
7768 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7769 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7770 if(std::abs(norm)>eps)
7772 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7773 mm3->rotate(center,vec,angle);
7775 mm3->changeSpaceDimension(2);
7776 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7777 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7778 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7779 int nbOfCells=mm4->getNumberOfCells();
7780 for(int k=0;k<nbOfCells;k++)
7783 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7784 res->pushBackSilent(idsNodePtr[*work]);
7785 res->pushBackSilent(-1);
7790 res->popBackSilent();
7794 * 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
7795 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7797 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7798 * \param [in] coords coordinates expected to have 3 components.
7799 * \param [in] begin start of the nodal connectivity of the face.
7800 * \param [in] end end of the nodal connectivity (excluded) of the face.
7801 * \param [out] v the normalized vector of size 3
7802 * \param [out] p the pos of plane
7804 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7806 std::size_t nbPoints=std::distance(begin,end);
7808 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7809 double vec[3]={0.,0.,0.};
7811 bool refFound=false;
7812 for(;j<nbPoints-1 && !refFound;j++)
7814 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7815 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7816 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7817 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7821 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7824 for(std::size_t i=j;i<nbPoints-1;i++)
7827 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7828 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7829 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7830 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7833 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7834 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];
7835 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7838 v[0]/=norm; v[1]/=norm; v[2]/=norm;
7839 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7843 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7847 * This method tries to obtain a well oriented polyhedron.
7848 * If the algorithm fails, an exception will be thrown.
7850 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7852 std::list< std::pair<int,int> > edgesOK,edgesFinished;
7853 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7854 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7856 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7857 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7858 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7860 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7863 std::size_t smthChanged=0;
7864 for(std::size_t i=0;i<nbOfFaces;i++)
7866 endFace=std::find(bgFace+1,end,-1);
7867 nbOfEdgesInFace=std::distance(bgFace,endFace);
7871 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7873 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7874 std::pair<int,int> p2(p1.second,p1.first);
7875 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7876 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7877 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7882 std::reverse(bgFace+1,endFace);
7883 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7885 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7886 std::pair<int,int> p2(p1.second,p1.first);
7887 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7888 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7889 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7890 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7891 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7892 if(it!=edgesOK.end())
7895 edgesFinished.push_back(p1);
7898 edgesOK.push_back(p1);
7905 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7907 if(!edgesOK.empty())
7908 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7909 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7910 {//not lucky ! The first face was not correctly oriented : reorient all faces...
7912 for(std::size_t i=0;i<nbOfFaces;i++)
7914 endFace=std::find(bgFace+1,end,-1);
7915 std::reverse(bgFace+1,endFace);
7922 * This method makes the assumption spacedimension == meshdimension == 2.
7923 * This method works only for linear cells.
7925 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7927 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7929 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7930 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7931 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7932 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7933 int nbOfNodesExpected=m->getNumberOfNodes();
7934 if(m->getNumberOfCells()!=nbOfNodesExpected)
7935 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7936 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7937 const int *n2oPtr=n2o->getConstPointer();
7938 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7939 m->getReverseNodalConnectivity(revNodal,revNodalI);
7940 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7941 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7942 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7943 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7944 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
7945 if(nbOfNodesExpected<1)
7948 int prevNode=nodalPtr[nodalIPtr[0]+1];
7949 *work++=n2oPtr[prevNode];
7950 for(int i=1;i<nbOfNodesExpected;i++)
7952 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7954 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
7955 conn.erase(prevNode);
7958 int curNode=*(conn.begin());
7959 *work++=n2oPtr[curNode];
7960 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
7961 shar.erase(prevCell);
7964 prevCell=*(shar.begin());
7968 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
7971 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
7974 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
7980 * This method makes the assumption spacedimension == meshdimension == 3.
7981 * This method works only for linear cells.
7983 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
7985 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
7987 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
7988 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
7989 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7990 const int *conn=m->getNodalConnectivity()->getConstPointer();
7991 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
7992 int nbOfCells=m->getNumberOfCells();
7993 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
7994 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
7997 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
7998 for(int i=1;i<nbOfCells;i++)
8001 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8007 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8008 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8010 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
8014 for(int i=0;i<nbOfNodesInCell;i++)
8015 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8016 else if(spaceDim==2)
8018 for(int i=0;i<nbOfNodesInCell;i++)
8020 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8025 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8028 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8030 int nbOfCells=getNumberOfCells();
8032 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8033 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};
8034 ofs << " <" << getVTKDataSetType() << ">\n";
8035 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8036 ofs << " <PointData>\n" << pointData << std::endl;
8037 ofs << " </PointData>\n";
8038 ofs << " <CellData>\n" << cellData << std::endl;
8039 ofs << " </CellData>\n";
8040 ofs << " <Points>\n";
8041 if(getSpaceDimension()==3)
8042 _coords->writeVTK(ofs,8,"Points");
8045 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8046 coo->writeVTK(ofs,8,"Points");
8048 ofs << " </Points>\n";
8049 ofs << " <Cells>\n";
8050 const int *cPtr=_nodal_connec->getConstPointer();
8051 const int *cIPtr=_nodal_connec_index->getConstPointer();
8052 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8053 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8054 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8055 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8056 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8057 int szFaceOffsets=0,szConn=0;
8058 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8061 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8064 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8065 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8069 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8070 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8071 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8072 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8073 w4=std::copy(c.begin(),c.end(),w4);
8076 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8077 types->writeVTK(ofs,8,"UInt8","types");
8078 offsets->writeVTK(ofs,8,"Int32","offsets");
8079 if(szFaceOffsets!=0)
8080 {//presence of Polyhedra
8081 connectivity->reAlloc(szConn);
8082 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8083 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8084 w1=faces->getPointer();
8085 for(int i=0;i<nbOfCells;i++)
8086 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8088 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8090 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8091 for(int j=0;j<nbFaces;j++)
8093 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8094 *w1++=(int)std::distance(w6,w5);
8095 w1=std::copy(w6,w5,w1);
8099 faces->writeVTK(ofs,8,"Int32","faces");
8101 connectivity->writeVTK(ofs,8,"Int32","connectivity");
8102 ofs << " </Cells>\n";
8103 ofs << " </Piece>\n";
8104 ofs << " </" << getVTKDataSetType() << ">\n";
8107 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8109 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8111 { stream << " Not set !"; return ; }
8112 stream << " Mesh dimension : " << _mesh_dim << ".";
8116 { stream << " No coordinates set !"; return ; }
8117 if(!_coords->isAllocated())
8118 { stream << " Coordinates set but not allocated !"; return ; }
8119 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8120 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8121 if(!_nodal_connec_index)
8122 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8123 if(!_nodal_connec_index->isAllocated())
8124 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8125 int lgth=_nodal_connec_index->getNumberOfTuples();
8126 int cpt=_nodal_connec_index->getNumberOfComponents();
8127 if(cpt!=1 || lgth<1)
8129 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8132 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8134 return std::string("UnstructuredGrid");
8138 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8139 * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8140 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8142 * \param [in] m1 - the first input mesh which is a partitioned object.
8143 * \param [in] m2 - the second input mesh which is a partition tool.
8144 * \param [in] eps - precision used to detect coincident mesh entities.
8145 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8146 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8147 * this array using decrRef() as it is no more needed.
8148 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8149 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8150 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8151 * any cell of \a m2. The caller is to delete this array using decrRef() as
8152 * it is no more needed.
8153 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8154 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8155 * is no more needed.
8156 * \throw If the coordinates array is not set in any of the meshes.
8157 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8158 * \throw If any of the meshes is not a 2D mesh in 2D space.
8160 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8162 m1->checkFullyDefined();
8163 m2->checkFullyDefined();
8164 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8165 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8166 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8167 MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8168 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8169 std::vector<double> addCoo,addCoordsQuadratic;
8170 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8171 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8172 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8173 m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8174 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8175 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8176 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8177 std::vector< std::vector<int> > intersectEdge2;
8178 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8179 subDiv2.clear(); dd5=0; dd6=0;
8180 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8181 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8182 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8183 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8185 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8186 addCooDa->alloc((int)(addCoo.size())/2,2);
8187 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8188 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8189 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8190 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8191 std::vector<const DataArrayDouble *> coordss(4);
8192 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8193 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8194 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8195 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8196 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8197 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8198 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8199 ret->setConnectivity(conn,connI,true);
8200 ret->setCoords(coo);
8201 cellNb1=c1.retn(); cellNb2=c2.retn();
8205 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8206 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8207 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8208 const std::vector<double>& addCoords,
8209 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8211 static const int SPACEDIM=2;
8212 std::vector<double> bbox1,bbox2;
8213 const double *coo1=m1->getCoords()->getConstPointer();
8214 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8215 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8216 int offset1=m1->getNumberOfNodes();
8217 const double *coo2=m2->getCoords()->getConstPointer();
8218 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8219 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8220 int offset2=offset1+m2->getNumberOfNodes();
8221 int offset3=offset2+((int)addCoords.size())/2;
8222 m1->getBoundingBoxForBBTree(bbox1);
8223 m2->getBoundingBoxForBBTree(bbox2);
8224 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2->getNumberOfCells(),eps);
8225 int ncell1=m1->getNumberOfCells();
8227 for(int i=0;i<ncell1;i++)
8229 std::vector<int> candidates2;
8230 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8231 std::map<INTERP_KERNEL::Node *,int> mapp;
8232 std::map<int,INTERP_KERNEL::Node *> mappRev;
8233 INTERP_KERNEL::QuadraticPolygon pol1;
8234 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8235 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8236 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8237 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8238 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8240 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
8241 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8242 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8243 for(it1.first();!it1.finished();it1.next())
8244 edges1.insert(it1.current()->getPtr());
8246 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8247 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8249 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8251 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8252 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8253 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8254 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8255 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8258 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8260 pol1.initLocationsWithOther(pol2s[ii]);
8261 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8262 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8263 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8269 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8271 catch(INTERP_KERNEL::Exception& e)
8273 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();
8274 throw INTERP_KERNEL::Exception(oss.str().c_str());
8277 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8278 (*it).second->decrRef();
8283 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8286 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8287 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8288 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8289 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8290 std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8292 static const int SPACEDIM=2;
8293 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8294 desc2=DataArrayInt::New();
8295 descIndx2=DataArrayInt::New();
8296 revDesc2=DataArrayInt::New();
8297 revDescIndx2=DataArrayInt::New();
8298 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8299 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8300 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8301 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8302 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8303 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8304 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8305 std::vector<double> bbox1,bbox2;
8306 m1Desc->getBoundingBoxForBBTree(bbox1);
8307 m2Desc->getBoundingBoxForBBTree(bbox2);
8308 int ncell1=m1Desc->getNumberOfCells();
8309 int ncell2=m2Desc->getNumberOfCells();
8310 intersectEdge1.resize(ncell1);
8311 colinear2.resize(ncell2);
8312 subDiv2.resize(ncell2);
8313 BBTree<SPACEDIM,int> myTree(&bbox2[0],0,0,m2Desc->getNumberOfCells(),-eps);
8314 std::vector<int> candidates1(1);
8315 int offset1=m1->getNumberOfNodes();
8316 int offset2=offset1+m2->getNumberOfNodes();
8317 for(int i=0;i<ncell1;i++)
8319 std::vector<int> candidates2;
8320 myTree.getIntersectingElems(&bbox1[i*2*SPACEDIM],candidates2);
8321 if(!candidates2.empty())
8323 std::map<INTERP_KERNEL::Node *,int> map1,map2;
8324 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8326 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8327 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8332 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8334 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8335 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8339 * This method performs the 2nd step of Partition of 2D mesh.
8340 * This method has 4 inputs :
8341 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8342 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8343 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8344 * 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'
8345 * \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'
8346 * \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.
8347 * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8349 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)
8351 int offset1=m1->getNumberOfNodes();
8352 int ncell=m2->getNumberOfCells();
8353 const int *c=m2->getNodalConnectivity()->getConstPointer();
8354 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8355 const double *coo=m2->getCoords()->getConstPointer();
8356 const double *cooBis=m1->getCoords()->getConstPointer();
8357 int offset2=offset1+m2->getNumberOfNodes();
8358 intersectEdge.resize(ncell);
8359 for(int i=0;i<ncell;i++,cI++)
8361 const std::vector<int>& divs=subDiv[i];
8362 int nnode=cI[1]-cI[0]-1;
8363 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8364 std::map<INTERP_KERNEL::Node *, int> mapp22;
8365 for(int j=0;j<nnode;j++)
8367 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8368 int nnid=c[(*cI)+j+1];
8369 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8370 mapp22[nn]=nnid+offset1;
8372 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8373 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8374 ((*it).second.first)->decrRef();
8375 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8376 std::map<INTERP_KERNEL::Node *,int> mapp3;
8377 for(std::size_t j=0;j<divs.size();j++)
8380 INTERP_KERNEL::Node *tmp=0;
8382 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8384 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8386 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8390 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8391 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8398 * 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).
8399 * 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
8400 * with a plane. The result will be put in 'cut3DSuf' out parameter.
8401 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8402 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8403 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8404 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8405 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8406 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8407 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8408 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8409 * \param [out] cut3DSuf input/output param.
8411 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8412 const int *nodal3DCurve, const int *nodalIndx3DCurve,
8413 const int *desc, const int *descIndx,
8414 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8416 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8417 int nbOf3DSurfCell=(int)cut3DSurf.size();
8418 for(int i=0;i<nbOf3DSurfCell;i++)
8420 std::vector<int> res;
8421 int offset=descIndx[i];
8422 int nbOfSeg=descIndx[i+1]-offset;
8423 for(int j=0;j<nbOfSeg;j++)
8425 int edgeId=desc[offset+j];
8426 int status=cut3DCurve[edgeId];
8430 res.push_back(status);
8433 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8434 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8442 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8448 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8449 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8452 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8456 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8461 {// case when plane is on a multi colinear edge of a polyhedron
8462 if((int)res.size()==2*nbOfSeg)
8464 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8467 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8474 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8475 * 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).
8476 * 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
8477 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8478 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8479 * \param desc is the descending connectivity 3D->3DSurf
8480 * \param descIndx is the descending connectivity index 3D->3DSurf
8482 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8483 const int *desc, const int *descIndx,
8484 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8486 checkFullyDefined();
8487 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8488 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8489 const int *nodal3D=_nodal_connec->getConstPointer();
8490 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8491 int nbOfCells=getNumberOfCells();
8492 for(int i=0;i<nbOfCells;i++)
8494 std::map<int, std::set<int> > m;
8495 int offset=descIndx[i];
8496 int nbOfFaces=descIndx[i+1]-offset;
8499 for(int j=0;j<nbOfFaces;j++)
8501 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8502 if(p.first!=-1 && p.second!=-1)
8506 start=p.first; end=p.second;
8507 m[p.first].insert(p.second);
8508 m[p.second].insert(p.first);
8512 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8513 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8514 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8515 INTERP_KERNEL::NormalizedCellType cmsId;
8516 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8517 start=tmp[0]; end=tmp[nbOfNodesSon-1];
8518 for(unsigned k=0;k<nbOfNodesSon;k++)
8520 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8521 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8528 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8532 std::map<int, std::set<int> >::const_iterator it=m.find(start);
8533 const std::set<int>& s=(*it).second;
8534 std::set<int> s2; s2.insert(prev);
8536 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8539 int val=*s3.begin();
8540 conn.push_back(start);
8547 conn.push_back(end);
8550 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8551 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8552 cellIds->pushBackSilent(i);
8558 * 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
8559 * 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
8560 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8561 * 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
8562 * 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.
8564 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8566 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8568 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8571 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8572 if(cm.getDimension()==2)
8574 const int *node=nodalConnBg+1;
8575 int startNode=*node++;
8576 double refX=coords[2*startNode];
8577 for(;node!=nodalConnEnd;node++)
8579 if(coords[2*(*node)]<refX)
8582 refX=coords[2*startNode];
8585 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8589 double angle0=-M_PI/2;
8594 double angleNext=0.;
8595 while(nextNode!=startNode)
8599 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8601 if(*node!=tmpOut.back() && *node!=prevNode)
8603 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8604 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8609 res=angle0-angleM+2.*M_PI;
8618 if(nextNode!=startNode)
8620 angle0=angleNext-M_PI;
8623 prevNode=tmpOut.back();
8624 tmpOut.push_back(nextNode);
8627 std::vector<int> tmp3(2*(sz-1));
8628 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8629 std::copy(nodalConnBg+1,nodalConnEnd,it);
8630 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8632 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8635 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8637 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8642 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8643 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8648 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8651 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8655 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8656 * 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.
8658 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8659 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8660 * \param [in,out] arr array in which the remove operation will be done.
8661 * \param [in,out] arrIndx array in the remove operation will modify
8662 * \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])
8663 * \return true if \b arr and \b arrIndx have been modified, false if not.
8665 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8667 if(!arrIndx || !arr)
8668 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8669 if(offsetForRemoval<0)
8670 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8671 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8672 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8673 int *arrIPtr=arrIndx->getPointer();
8676 const int *arrPtr=arr->getConstPointer();
8677 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8678 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8680 if(*arrIPtr-previousArrI>offsetForRemoval)
8682 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8684 if(s.find(*work)==s.end())
8685 arrOut.push_back(*work);
8688 previousArrI=*arrIPtr;
8689 *arrIPtr=(int)arrOut.size();
8691 if(arr->getNumberOfTuples()==(int)arrOut.size())
8693 arr->alloc((int)arrOut.size(),1);
8694 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8699 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8700 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8701 * The selection of extraction is done standardly in new2old format.
8702 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8704 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8705 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8706 * \param [in] arrIn arr origin array from which the extraction will be done.
8707 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8708 * \param [out] arrOut the resulting array
8709 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8710 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
8712 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8713 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8715 if(!arrIn || !arrIndxIn)
8716 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8717 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8718 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8719 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
8720 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8721 const int *arrInPtr=arrIn->getConstPointer();
8722 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8723 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8725 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8726 int maxSizeOfArr=arrIn->getNumberOfTuples();
8727 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8728 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8729 arrIo->alloc((int)(sz+1),1);
8730 const int *idsIt=idsOfSelectBg;
8731 int *work=arrIo->getPointer();
8734 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8736 if(*idsIt>=0 && *idsIt<nbOfGrps)
8737 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8740 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8741 throw INTERP_KERNEL::Exception(oss.str().c_str());
8747 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8748 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8749 throw INTERP_KERNEL::Exception(oss.str().c_str());
8752 arro->alloc(lgth,1);
8753 work=arro->getPointer();
8754 idsIt=idsOfSelectBg;
8755 for(std::size_t i=0;i<sz;i++,idsIt++)
8757 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8758 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8761 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8762 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8763 throw INTERP_KERNEL::Exception(oss.str().c_str());
8767 arrIndexOut=arrIo.retn();
8771 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8772 * This method returns the result of the extraction ( specified by a set of ids with a slice given by \a idsOfSelectStart, \a idsOfSelectStop and \a idsOfSelectStep ).
8773 * The selection of extraction is done standardly in new2old format.
8774 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8776 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8777 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8778 * \param [in] arrIn arr origin array from which the extraction will be done.
8779 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8780 * \param [out] arrOut the resulting array
8781 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8782 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
8784 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8785 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8787 if(!arrIn || !arrIndxIn)
8788 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
8789 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8790 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8791 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
8792 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
8793 const int *arrInPtr=arrIn->getConstPointer();
8794 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8795 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8797 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8798 int maxSizeOfArr=arrIn->getNumberOfTuples();
8799 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8800 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8801 arrIo->alloc((int)(sz+1),1);
8802 int idsIt=idsOfSelectStart;
8803 int *work=arrIo->getPointer();
8806 for(std::size_t i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
8808 if(idsIt>=0 && idsIt<nbOfGrps)
8809 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
8812 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8813 throw INTERP_KERNEL::Exception(oss.str().c_str());
8819 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
8820 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
8821 throw INTERP_KERNEL::Exception(oss.str().c_str());
8824 arro->alloc(lgth,1);
8825 work=arro->getPointer();
8826 idsIt=idsOfSelectStart;
8827 for(std::size_t i=0;i<sz;i++,idsIt+=idsOfSelectStep)
8829 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
8830 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
8833 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
8834 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8835 throw INTERP_KERNEL::Exception(oss.str().c_str());
8839 arrIndexOut=arrIo.retn();
8843 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8844 * 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
8845 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8846 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8848 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8849 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8850 * \param [in] arrIn arr origin array from which the extraction will be done.
8851 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8852 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8853 * \param [in] srcArrIndex index array of \b srcArr
8854 * \param [out] arrOut the resulting array
8855 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8857 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8859 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8860 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8861 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8863 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8864 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8865 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8866 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8867 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8868 std::vector<bool> v(nbOfTuples,true);
8870 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8871 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8872 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8874 if(*it>=0 && *it<nbOfTuples)
8877 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8881 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8882 throw INTERP_KERNEL::Exception(oss.str().c_str());
8885 srcArrIndexPtr=srcArrIndex->getConstPointer();
8886 arrIo->alloc(nbOfTuples+1,1);
8887 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8888 const int *arrInPtr=arrIn->getConstPointer();
8889 const int *srcArrPtr=srcArr->getConstPointer();
8890 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8891 int *arroPtr=arro->getPointer();
8892 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8896 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8897 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8901 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8902 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8903 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8907 arrIndexOut=arrIo.retn();
8911 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8912 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8914 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8915 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8916 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8917 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8918 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8919 * \param [in] srcArrIndex index array of \b srcArr
8921 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8923 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8924 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8926 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8927 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8928 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8929 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8930 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8931 int *arrInOutPtr=arrInOut->getPointer();
8932 const int *srcArrPtr=srcArr->getConstPointer();
8933 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8935 if(*it>=0 && *it<nbOfTuples)
8937 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8938 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8941 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] !";
8942 throw INTERP_KERNEL::Exception(oss.str().c_str());
8947 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8948 throw INTERP_KERNEL::Exception(oss.str().c_str());
8954 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8955 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8956 * 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]].
8957 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8958 * A negative value in \b arrIn means that it is ignored.
8959 * 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.
8961 * \param [in] arrIn arr origin array from which the extraction will be done.
8962 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8963 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8964 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
8966 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
8968 int seed=0,nbOfDepthPeelingPerformed=0;
8969 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
8973 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8974 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8975 * 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]].
8976 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
8977 * A negative value in \b arrIn means that it is ignored.
8978 * 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.
8979 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
8980 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
8981 * \param [in] arrIn arr origin array from which the extraction will be done.
8982 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8983 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
8984 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
8985 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
8986 * \sa MEDCouplingUMesh::partitionBySpreadZone
8988 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
8990 nbOfDepthPeelingPerformed=0;
8992 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
8993 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8996 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9000 std::vector<bool> fetched(nbOfTuples,false);
9001 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9004 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)
9006 nbOfDepthPeelingPerformed=0;
9007 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9008 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9009 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9010 std::vector<bool> fetched2(nbOfTuples,false);
9012 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9014 if(*seedElt>=0 && *seedElt<nbOfTuples)
9015 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9017 { 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()); }
9019 const int *arrInPtr=arrIn->getConstPointer();
9020 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9021 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9022 std::vector<int> idsToFetch1(seedBg,seedEnd);
9023 std::vector<int> idsToFetch2;
9024 std::vector<int> *idsToFetch=&idsToFetch1;
9025 std::vector<int> *idsToFetchOther=&idsToFetch2;
9026 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9028 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9029 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9031 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9032 std::swap(idsToFetch,idsToFetchOther);
9033 idsToFetchOther->clear();
9034 nbOfDepthPeelingPerformed++;
9036 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9038 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9039 int *retPtr=ret->getPointer();
9040 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9047 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9048 * 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
9049 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9050 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9052 * \param [in] start begin of set of ids of the input extraction (included)
9053 * \param [in] end end of set of ids of the input extraction (excluded)
9054 * \param [in] step step of the set of ids in range mode.
9055 * \param [in] arrIn arr origin array from which the extraction will be done.
9056 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9057 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9058 * \param [in] srcArrIndex index array of \b srcArr
9059 * \param [out] arrOut the resulting array
9060 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9062 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9064 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9065 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9066 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9068 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9069 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9070 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9071 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9072 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9074 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9075 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9076 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9078 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9080 if(it>=0 && it<nbOfTuples)
9081 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9084 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9085 throw INTERP_KERNEL::Exception(oss.str().c_str());
9088 srcArrIndexPtr=srcArrIndex->getConstPointer();
9089 arrIo->alloc(nbOfTuples+1,1);
9090 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9091 const int *arrInPtr=arrIn->getConstPointer();
9092 const int *srcArrPtr=srcArr->getConstPointer();
9093 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9094 int *arroPtr=arro->getPointer();
9095 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9097 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9100 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9101 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9105 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9106 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9110 arrIndexOut=arrIo.retn();
9114 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9115 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9117 * \param [in] start begin of set of ids of the input extraction (included)
9118 * \param [in] end end of set of ids of the input extraction (excluded)
9119 * \param [in] step step of the set of ids in range mode.
9120 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9121 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9122 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9123 * \param [in] srcArrIndex index array of \b srcArr
9125 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9127 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9128 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9130 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9131 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9132 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9133 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9134 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9135 int *arrInOutPtr=arrInOut->getPointer();
9136 const int *srcArrPtr=srcArr->getConstPointer();
9137 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9139 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9141 if(it>=0 && it<nbOfTuples)
9143 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9144 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9147 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9148 throw INTERP_KERNEL::Exception(oss.str().c_str());
9153 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9154 throw INTERP_KERNEL::Exception(oss.str().c_str());
9160 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9161 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9162 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9163 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9164 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9166 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9168 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9170 checkFullyDefined();
9171 int mdim=getMeshDimension();
9172 int spaceDim=getSpaceDimension();
9174 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9175 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9176 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9177 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9178 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName(),mdim);
9179 ret->setCoords(getCoords());
9180 ret->allocateCells((int)partition.size());
9182 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9184 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9185 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9189 cell=tmp->buildUnionOf2DMesh();
9192 cell=tmp->buildUnionOf3DMesh();
9195 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9198 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9201 ret->finishInsertingCells();
9206 * This method partitions \b this into contiguous zone.
9207 * This method only needs a well defined connectivity. Coordinates are not considered here.
9208 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9210 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9213 int nbOfCellsCur=getNumberOfCells();
9214 std::vector<DataArrayInt *> ret;
9217 DataArrayInt *neigh=0,*neighI=0;
9218 computeNeighborsOfCells(neigh,neighI);
9219 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9220 std::vector<bool> fetchedCells(nbOfCellsCur,false);
9221 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9223 while(seed<nbOfCellsCur)
9225 int nbOfPeelPerformed=0;
9226 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9227 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9229 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9230 ret.push_back((*it).retn());
9234 int nbOfCellsCur=getNumberOfCells();
9235 DataArrayInt *neigh=0,*neighI=0;
9236 computeNeighborsOfCells(neigh,neighI);
9237 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9238 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids=DataArrayInt::New(); ids->alloc(nbOfCellsCur,1); ids->iota();
9239 std::vector<DataArrayInt *> ret;
9240 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9241 while(nbOfCellsCur>0)
9243 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=MEDCouplingUMesh::ComputeSpreadZoneGradually(neighAuto,neighIAuto);
9244 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=tmp->buildComplement(nbOfCellsCur);
9245 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=ids->selectByTupleId(tmp->begin(),tmp->end());
9246 ret2.push_back(tmp2); ret.push_back(tmp2);
9247 nbOfCellsCur=tmp3->getNumberOfTuples();
9250 ids=ids->selectByTupleId(tmp3->begin(),tmp3->end());
9251 MEDCouplingUMesh::ExtractFromIndexedArrays(tmp3->begin(),tmp3->end(),neighAuto,neighIAuto,neigh,neighI);
9254 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=tmp3->invertArrayN2O2O2N(nbOfCellsCur+tmp->getNumberOfTuples());
9255 neighAuto->transformWithIndArr(renum->begin(),renum->end());
9258 for(std::vector<DataArrayInt *>::const_iterator it=ret.begin();it!=ret.end();it++)
9265 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9266 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9268 * \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.
9269 * \return a newly allocated DataArrayInt to be managed by the caller.
9270 * \throw In case of \a code has not the right format (typically of size 3*n)
9272 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9274 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9275 std::size_t nb=code.size()/3;
9276 if(code.size()%3!=0)
9277 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9278 ret->alloc((int)nb,2);
9279 int *retPtr=ret->getPointer();
9280 for(std::size_t i=0;i<nb;i++,retPtr+=2)
9282 retPtr[0]=code[3*i+2];
9283 retPtr[1]=code[3*i+2]+code[3*i+1];
9288 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9289 _own_cell(true),_cell_id(-1),_nb_cell(0)
9294 _nb_cell=mesh->getNumberOfCells();
9298 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9306 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9307 _own_cell(false),_cell_id(bg-1),
9314 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9317 if(_cell_id<_nb_cell)
9326 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9332 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9334 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9337 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9343 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9351 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9357 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9362 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9367 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9369 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9372 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9377 _nb_cell=mesh->getNumberOfCells();
9381 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9388 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9390 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9391 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9392 if(_cell_id<_nb_cell)
9394 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9395 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9396 int startId=_cell_id;
9397 _cell_id+=nbOfElems;
9398 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9404 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9408 _conn=mesh->getNodalConnectivity()->getPointer();
9409 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9413 void MEDCouplingUMeshCell::next()
9415 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9420 _conn_lgth=_conn_indx[1]-_conn_indx[0];
9423 std::string MEDCouplingUMeshCell::repr() const
9425 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9427 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9429 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9433 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9436 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9438 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9439 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9441 return INTERP_KERNEL::NORM_ERROR;
9444 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9447 if(_conn_lgth!=NOTICABLE_FIRST_VAL)