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
1394 * \sa MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell
1396 DataArrayInt *MEDCouplingUMesh::computeNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1398 checkConnectivityFullyDefined();
1399 int nbOfCells=getNumberOfCells();
1400 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1401 ret->alloc(nbOfCells,1);
1402 int *retPtr=ret->getPointer();
1403 const int *conn=getNodalConnectivity()->getConstPointer();
1404 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1405 for(int i=0;i<nbOfCells;i++,retPtr++)
1407 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1408 *retPtr=connI[i+1]-connI[i]-1;
1410 *retPtr=connI[i+1]-connI[i]-1-std::count(conn+connI[i]+1,conn+connI[i+1],-1);
1416 * This method computes effective number of nodes per cell. That is to say nodes appearing several times in nodal connectivity of a cell,
1417 * will be counted only once here whereas it will be counted several times in MEDCouplingUMesh::computeNbOfNodesPerCell method.
1419 * \return DataArrayInt * - new object to be deallocated by the caller.
1420 * \sa MEDCouplingUMesh::computeNbOfNodesPerCell
1422 DataArrayInt *MEDCouplingUMesh::computeEffectiveNbOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
1424 checkConnectivityFullyDefined();
1425 int nbOfCells=getNumberOfCells();
1426 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1427 ret->alloc(nbOfCells,1);
1428 int *retPtr=ret->getPointer();
1429 const int *conn=getNodalConnectivity()->getConstPointer();
1430 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1431 for(int i=0;i<nbOfCells;i++,retPtr++)
1433 std::set<int> s(conn+connI[i]+1,conn+connI[i+1]);
1434 if(conn[connI[i]]!=(int)INTERP_KERNEL::NORM_POLYHED)
1435 *retPtr=(int)s.size();
1439 *retPtr=(int)s.size();
1446 * This method returns a newly allocated array containing this->getNumberOfCells() tuples and 1 component.
1447 * For each cell in \b this the number of faces constituting (entity of dimension this->getMeshDimension()-1) cell is computed.
1449 * \return a newly allocated array
1451 DataArrayInt *MEDCouplingUMesh::computeNbOfFacesPerCell() const throw(INTERP_KERNEL::Exception)
1453 checkConnectivityFullyDefined();
1454 int nbOfCells=getNumberOfCells();
1455 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
1456 ret->alloc(nbOfCells,1);
1457 int *retPtr=ret->getPointer();
1458 const int *conn=getNodalConnectivity()->getConstPointer();
1459 const int *connI=getNodalConnectivityIndex()->getConstPointer();
1460 for(int i=0;i<nbOfCells;i++,retPtr++,connI++)
1462 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*connI]);
1463 *retPtr=cm.getNumberOfSons2(conn+connI[0]+1,connI[1]-connI[0]-1);
1469 * Removes unused nodes (the node coordinates array is shorten) and returns an array
1470 * mapping between new and old node ids in "Old to New" mode. -1 values in the returned
1471 * array mean that the corresponding old node is no more used.
1472 * \return DataArrayInt * - a new instance of DataArrayInt of length \a
1473 * this->getNumberOfNodes() before call of this method. The caller is to
1474 * delete this array using decrRef() as it is no more needed.
1475 * \throw If the coordinates array is not set.
1476 * \throw If the nodal connectivity of cells is not defined.
1477 * \throw If the nodal connectivity includes an invalid id.
1479 * \ref cpp_mcumesh_zipCoordsTraducer "Here is a C++ example".<br>
1480 * \ref py_mcumesh_zipCoordsTraducer "Here is a Python example".
1482 DataArrayInt *MEDCouplingUMesh::zipCoordsTraducer() throw(INTERP_KERNEL::Exception)
1484 return MEDCouplingPointSet::zipCoordsTraducer();
1488 * This method stands if 'cell1' and 'cell2' are equals regarding 'compType' policy.
1489 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1491 int MEDCouplingUMesh::AreCellsEqual(const int *conn, const int *connI, int cell1, int cell2, int compType)
1496 return AreCellsEqual0(conn,connI,cell1,cell2);
1498 return AreCellsEqual1(conn,connI,cell1,cell2);
1500 return AreCellsEqual2(conn,connI,cell1,cell2);
1502 return AreCellsEqual3(conn,connI,cell1,cell2);
1504 return AreCellsEqual7(conn,connI,cell1,cell2);
1506 throw INTERP_KERNEL::Exception("Unknown comparison asked ! Must be in 0,1,2,3 or 7.");
1510 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 0.
1512 int MEDCouplingUMesh::AreCellsEqual0(const int *conn, const int *connI, int cell1, int cell2)
1514 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1515 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;
1520 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 1.
1522 int MEDCouplingUMesh::AreCellsEqual1(const int *conn, const int *connI, int cell1, int cell2)
1524 int sz=connI[cell1+1]-connI[cell1];
1525 if(sz==connI[cell2+1]-connI[cell2])
1527 if(conn[connI[cell1]]==conn[connI[cell2]])
1529 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1530 unsigned dim=cm.getDimension();
1536 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1537 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1538 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1539 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1540 return work!=tmp+sz1?1:0;
1543 return std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1)?1:0;//case of SEG2 and SEG3
1546 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual1 : not implemented yet for meshdim == 3 !");
1553 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 2.
1555 int MEDCouplingUMesh::AreCellsEqual2(const int *conn, const int *connI, int cell1, int cell2)
1557 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1559 if(conn[connI[cell1]]==conn[connI[cell2]])
1561 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1562 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1570 * This method is less restrictive than AreCellsEqual2. Here the geometric type is absolutely not taken into account !
1572 int MEDCouplingUMesh::AreCellsEqual3(const int *conn, const int *connI, int cell1, int cell2)
1574 if(connI[cell1+1]-connI[cell1]==connI[cell2+1]-connI[cell2])
1576 std::set<int> s1(conn+connI[cell1]+1,conn+connI[cell1+1]);
1577 std::set<int> s2(conn+connI[cell2]+1,conn+connI[cell2+1]);
1584 * This method is the last step of the MEDCouplingPointSet::zipConnectivityTraducer with policy 7.
1586 int MEDCouplingUMesh::AreCellsEqual7(const int *conn, const int *connI, int cell1, int cell2)
1588 int sz=connI[cell1+1]-connI[cell1];
1589 if(sz==connI[cell2+1]-connI[cell2])
1591 if(conn[connI[cell1]]==conn[connI[cell2]])
1593 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[cell1]]);
1594 unsigned dim=cm.getDimension();
1600 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz1];
1601 int *work=std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],(int *)tmp);
1602 std::copy(conn+connI[cell1]+1,conn+connI[cell1+1],work);
1603 work=std::search((int *)tmp,(int *)tmp+sz1,conn+connI[cell2]+1,conn+connI[cell2+1]);
1608 std::reverse_iterator<int *> it1((int *)tmp+sz1);
1609 std::reverse_iterator<int *> it2((int *)tmp);
1610 if(std::search(it1,it2,conn+connI[cell2]+1,conn+connI[cell2+1])!=it2)
1616 return work!=tmp+sz1?1:0;
1619 {//case of SEG2 and SEG3
1620 if(std::equal(conn+connI[cell1]+1,conn+connI[cell1+1],conn+connI[cell2]+1))
1622 if(!cm.isQuadratic())
1624 std::reverse_iterator<const int *> it1(conn+connI[cell1+1]);
1625 std::reverse_iterator<const int *> it2(conn+connI[cell1]+1);
1626 if(std::equal(it1,it2,conn+connI[cell2]+1))
1632 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])
1639 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AreCellsEqual7 : not implemented yet for meshdim == 3 !");
1646 * This method find in candidate pool defined by 'candidates' the cells equal following the polycy 'compType'.
1647 * If any true is returned and the results will be put at the end of 'result' output parameter. If not false is returned
1648 * and result remains unchanged.
1649 * The semantic of 'compType' is specified in MEDCouplingPointSet::zipConnectivityTraducer method.
1650 * If in 'candidates' pool -1 value is considered as an empty value.
1651 * WARNING this method returns only ONE set of result !
1653 bool MEDCouplingUMesh::AreCellsEqualInPool(const std::vector<int>& candidates, int compType, const int *conn, const int *connI, DataArrayInt *result)
1655 if(candidates.size()<1)
1658 std::vector<int>::const_iterator iter=candidates.begin();
1659 int start=(*iter++);
1660 for(;iter!=candidates.end();iter++)
1662 int status=AreCellsEqual(conn,connI,start,*iter,compType);
1667 result->pushBackSilent(start);
1671 result->pushBackSilent(*iter);
1673 result->pushBackSilent(status==2?(*iter+1):-(*iter+1));
1680 * This method find cells that are cells equal (regarding \a compType) in \a this. The comparison is specified by \a compType.
1681 * This method keeps the coordiantes of \a this. This method is time consuming and is called
1683 * \param [in] compType input specifying the technique used to compare cells each other.
1684 * - 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.
1685 * - 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)
1686 * and their type equal. For 1D mesh the policy 1 is equivalent to 0.
1687 * - 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
1688 * can be used for users not sensitive to orientation of cell
1689 * \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.
1690 * \param [out] commonCells
1691 * \param [out] commonCellsI
1692 * \return the correspondance array old to new in a newly allocated array.
1695 void MEDCouplingUMesh::findCommonCells(int compType, int startCellId, DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) const throw(INTERP_KERNEL::Exception)
1697 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal=DataArrayInt::New(),revNodalI=DataArrayInt::New();
1698 getReverseNodalConnectivity(revNodal,revNodalI);
1699 FindCommonCellsAlg(compType,startCellId,_nodal_connec,_nodal_connec_index,revNodal,revNodalI,commonCellsArr,commonCellsIArr);
1702 void MEDCouplingUMesh::FindCommonCellsAlg(int compType, int startCellId, const DataArrayInt *nodal, const DataArrayInt *nodalI, const DataArrayInt *revNodal, const DataArrayInt *revNodalI,
1703 DataArrayInt *& commonCellsArr, DataArrayInt *& commonCellsIArr) throw(INTERP_KERNEL::Exception)
1705 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCells=DataArrayInt::New(),commonCellsI=DataArrayInt::New(); commonCells->alloc(0,1);
1706 int nbOfCells=nodalI->getNumberOfTuples()-1;
1707 commonCellsI->reserve(1); commonCellsI->pushBackSilent(0);
1708 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
1709 const int *connPtr=nodal->getConstPointer(),*connIPtr=nodalI->getConstPointer();
1710 std::vector<bool> isFetched(nbOfCells,false);
1713 for(int i=0;i<nbOfCells;i++)
1717 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1718 std::vector<int> v,v2;
1719 if(connOfNode!=connPtr+connIPtr[i+1])
1721 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1722 v2.insert(v2.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1]);
1725 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1729 const int *locRevNodal=std::find(revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],i);
1730 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),locRevNodal,revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1731 v2.resize(std::distance(v2.begin(),it));
1735 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1737 int pos=commonCellsI->back();
1738 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1739 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1740 isFetched[*it]=true;
1748 for(int i=startCellId;i<nbOfCells;i++)
1752 const int *connOfNode=std::find_if(connPtr+connIPtr[i]+1,connPtr+connIPtr[i+1],std::bind2nd(std::not_equal_to<int>(),-1));
1753 std::vector<int> v,v2;
1754 if(connOfNode!=connPtr+connIPtr[i+1])
1756 v2.insert(v2.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1]);
1759 for(;connOfNode!=connPtr+connIPtr[i+1] && v2.size()>1;connOfNode++)
1763 std::vector<int>::iterator it=std::set_intersection(v.begin(),v.end(),revNodalPtr+revNodalIPtr[*connOfNode],revNodalPtr+revNodalIPtr[*connOfNode+1],v2.begin());
1764 v2.resize(std::distance(v2.begin(),it));
1768 if(AreCellsEqualInPool(v2,compType,connPtr,connIPtr,commonCells))
1770 int pos=commonCellsI->back();
1771 commonCellsI->pushBackSilent(commonCells->getNumberOfTuples());
1772 for(const int *it=commonCells->begin()+pos;it!=commonCells->end();it++)
1773 isFetched[*it]=true;
1779 commonCellsArr=commonCells.retn();
1780 commonCellsIArr=commonCellsI.retn();
1784 * Checks if \a this mesh includes all cells of an \a other mesh, and returns an array
1785 * giving for each cell of the \a other an id of a cell in \a this mesh. A value larger
1786 * than \a other->getNumberOfCells() in the returned array means that there is no
1787 * corresponding cell in \a this mesh.
1788 * It is expected that \a this and \a other meshes share the same node coordinates
1789 * array, if it is not so an exception is thrown.
1790 * \param [in] other - the mesh to compare with.
1791 * \param [in] compType - specifies a cell comparison technique. For meaning of its
1792 * valid values [0,1,2], see zipConnectivityTraducer().
1793 * \param [out] arr - a new instance of DataArrayInt returning correspondence
1794 * between cells of the two meshes. It contains \a other->getNumberOfCells()
1795 * values. The caller is to delete this array using
1796 * decrRef() as it is no more needed.
1797 * \return bool - \c true if all cells of \a other mesh are present in the \a this
1800 * \ref cpp_mcumesh_areCellsIncludedIn "Here is a C++ example".<br>
1801 * \ref py_mcumesh_areCellsIncludedIn "Here is a Python example".
1802 * \sa checkDeepEquivalOnSameNodesWith()
1803 * \sa checkGeoEquivalWith()
1805 bool MEDCouplingUMesh::areCellsIncludedIn(const MEDCouplingUMesh *other, int compType, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1807 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1808 int nbOfCells=getNumberOfCells();
1809 static const int possibleCompType[]={0,1,2};
1810 if(std::find(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),compType)==possibleCompType+sizeof(possibleCompType)/sizeof(int))
1812 std::ostringstream oss; oss << "MEDCouplingUMesh::areCellsIncludedIn : only following policies are possible : ";
1813 std::copy(possibleCompType,possibleCompType+sizeof(possibleCompType)/sizeof(int),std::ostream_iterator<int>(oss," "));
1815 throw INTERP_KERNEL::Exception(oss.str().c_str());
1817 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=mesh->zipConnectivityTraducer(compType,nbOfCells);
1818 arr=o2n->substr(nbOfCells);
1819 arr->setName(other->getName().c_str());
1821 if(other->getNumberOfCells()==0)
1823 return arr->getMaxValue(tmp)<nbOfCells;
1827 * This method makes the assumption that \a this and \a other share the same coords. If not an exception will be thrown !
1828 * This method tries to determine if \b other is fully included in \b this.
1829 * The main difference is that this method is not expected to throw exception.
1830 * This method has two outputs :
1832 * \param arr is an output parameter that returns a \b newly created instance. This array is of size 'other->getNumberOfCells()'.
1833 * \return If \a other is fully included in 'this 'true is returned. If not false is returned.
1835 bool MEDCouplingUMesh::areCellsIncludedIn2(const MEDCouplingUMesh *other, DataArrayInt *& arr) const throw(INTERP_KERNEL::Exception)
1837 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mesh=MergeUMeshesOnSameCoords(this,other);
1838 DataArrayInt *commonCells=0,*commonCellsI=0;
1839 int thisNbCells=getNumberOfCells();
1840 mesh->findCommonCells(7,thisNbCells,commonCells,commonCellsI);
1841 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> commonCellsTmp(commonCells),commonCellsITmp(commonCellsI);
1842 const int *commonCellsPtr=commonCells->getConstPointer(),*commonCellsIPtr=commonCellsI->getConstPointer();
1843 int otherNbCells=other->getNumberOfCells();
1844 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arr2=DataArrayInt::New();
1845 arr2->alloc(otherNbCells,1);
1846 arr2->fillWithZero();
1847 int *arr2Ptr=arr2->getPointer();
1848 int nbOfCommon=commonCellsI->getNumberOfTuples()-1;
1849 for(int i=0;i<nbOfCommon;i++)
1851 int start=commonCellsPtr[commonCellsIPtr[i]];
1852 if(start<thisNbCells)
1854 for(int j=commonCellsIPtr[i]+1;j!=commonCellsIPtr[i+1];j++)
1856 int sig=commonCellsPtr[j]>0?1:-1;
1857 int val=std::abs(commonCellsPtr[j])-1;
1858 if(val>=thisNbCells)
1859 arr2Ptr[val-thisNbCells]=sig*(start+1);
1863 arr2->setName(other->getName().c_str());
1864 if(arr2->presenceOfValue(0))
1870 MEDCouplingPointSet *MEDCouplingUMesh::mergeMyselfWithOnSameCoords(const MEDCouplingPointSet *other) const
1873 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : input other is null !");
1874 const MEDCouplingUMesh *otherC=dynamic_cast<const MEDCouplingUMesh *>(other);
1876 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::mergeMyselfWithOnSameCoords : the input other mesh is not of type unstructured !");
1877 std::vector<const MEDCouplingUMesh *> ms(2);
1880 return MergeUMeshesOnSameCoords(ms);
1884 * Build a sub part of \b this lying or not on the same coordinates than \b this (regarding value of \b keepCoords).
1885 * By default coordinates are kept. This method is close to MEDCouplingUMesh::buildPartOfMySelf except that here input
1886 * cellIds is not given explicitely but by a range python like.
1888 * \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.
1889 * \return a newly allocated
1891 * \warning This method modifies can generate an unstructured mesh whose cells are not sorted by geometric type order.
1892 * In view of the MED file writing, a renumbering of cells of returned unstructured mesh (using MEDCouplingUMesh::sortCellsInMEDFileFrmt) should be necessary.
1894 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf2(int start, int end, int step, bool keepCoords) const throw(INTERP_KERNEL::Exception)
1896 if(getMeshDimension()!=-1)
1897 return MEDCouplingPointSet::buildPartOfMySelf2(start,end,step,keepCoords);
1900 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelf2 for -1 dimension mesh ");
1902 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1904 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1906 return const_cast<MEDCouplingUMesh *>(this);
1911 * Creates a new MEDCouplingUMesh containing specified cells of \a this mesh.
1912 * The result mesh shares or not the node coordinates array with \a this mesh depending
1913 * on \a keepCoords parameter.
1914 * \warning Cells of the result mesh can be \b not sorted by geometric type, hence,
1915 * to write this mesh to the MED file, its cells must be sorted using
1916 * sortCellsInMEDFileFrmt().
1917 * \param [in] begin - an array of cell ids to include to the new mesh.
1918 * \param [in] end - a pointer to last-plus-one-th element of \a begin.
1919 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
1920 * array of \a this mesh, else "free" nodes are removed from the result mesh
1921 * by calling zipCoords().
1922 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
1923 * to delete this mesh using decrRef() as it is no more needed.
1924 * \throw If the coordinates array is not set.
1925 * \throw If the nodal connectivity of cells is not defined.
1926 * \throw If any cell id in the array \a begin is not valid.
1928 * \ref cpp_mcumesh_buildPartOfMySelf "Here is a C++ example".<br>
1929 * \ref py_mcumesh_buildPartOfMySelf "Here is a Python example".
1931 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelf(const int *begin, const int *end, bool keepCoords) const
1933 if(getMeshDimension()!=-1)
1934 return MEDCouplingPointSet::buildPartOfMySelf(begin,end,keepCoords);
1938 throw INTERP_KERNEL::Exception("-1D mesh has only one cell !");
1940 throw INTERP_KERNEL::Exception("-1D mesh has only one cell : 0 !");
1942 return const_cast<MEDCouplingUMesh *>(this);
1947 * This method operates only on nodal connectivity on \b this. Coordinates of \b this is completely ignored here.
1949 * 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.
1950 * Size of [ \b cellIdsBg, \b cellIdsEnd ) ) must be equal to the number of cells of otherOnSameCoordsThanThis.
1951 * The number of cells of \b this will remain the same with this method.
1953 * \param [in] begin begin of cell ids (included) of cells in this to assign
1954 * \param [in] end end of cell ids (excluded) of cells in this to assign
1955 * \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 ).
1956 * Coordinate pointer of \b this and those of \b otherOnSameCoordsThanThis must be the same
1958 void MEDCouplingUMesh::setPartOfMySelf(const int *cellIdsBg, const int *cellIdsEnd, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
1960 checkConnectivityFullyDefined();
1961 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
1962 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
1963 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
1964 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
1966 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
1967 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
1968 throw INTERP_KERNEL::Exception(oss.str().c_str());
1970 int nbOfCellsToModify=(int)std::distance(cellIdsBg,cellIdsEnd);
1971 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
1973 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
1974 throw INTERP_KERNEL::Exception(oss.str().c_str());
1976 int nbOfCells=getNumberOfCells();
1977 bool easyAssign=true;
1978 const int *connI=_nodal_connec_index->getConstPointer();
1979 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
1980 for(const int *it=cellIdsBg;it!=cellIdsEnd && easyAssign;it++,connIOther++)
1982 if(*it>=0 && *it<nbOfCells)
1984 easyAssign=(connIOther[1]-connIOther[0])==(connI[*it+1]-connI[*it]);
1988 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf : On pos #" << std::distance(cellIdsBg,it) << " id is equal to " << *it << " which is not in [0," << nbOfCells << ") !";
1989 throw INTERP_KERNEL::Exception(oss.str().c_str());
1994 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
1999 DataArrayInt *arrOut=0,*arrIOut=0;
2000 MEDCouplingUMesh::SetPartOfIndexedArrays(cellIdsBg,cellIdsEnd,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2002 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2003 setConnectivity(arrOut,arrIOut,true);
2007 void MEDCouplingUMesh::setPartOfMySelf2(int start, int end, int step, const MEDCouplingUMesh& otherOnSameCoordsThanThis) throw(INTERP_KERNEL::Exception)
2009 checkConnectivityFullyDefined();
2010 otherOnSameCoordsThanThis.checkConnectivityFullyDefined();
2011 if(getCoords()!=otherOnSameCoordsThanThis.getCoords())
2012 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::setPartOfMySelf2 : coordinates pointer are not the same ! Invoke setCoords or call tryToShareSameCoords method !");
2013 if(getMeshDimension()!=otherOnSameCoordsThanThis.getMeshDimension())
2015 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : Mismatch of meshdimensions ! this is equal to " << getMeshDimension();
2016 oss << ", whereas other mesh dimension is set equal to " << otherOnSameCoordsThanThis.getMeshDimension() << " !";
2017 throw INTERP_KERNEL::Exception(oss.str().c_str());
2019 int nbOfCellsToModify=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::setPartOfMySelf2 : ");
2020 if(nbOfCellsToModify!=otherOnSameCoordsThanThis.getNumberOfCells())
2022 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : cells ids length (" << nbOfCellsToModify << ") do not match the number of cells of other mesh (" << otherOnSameCoordsThanThis.getNumberOfCells() << ") !";
2023 throw INTERP_KERNEL::Exception(oss.str().c_str());
2025 int nbOfCells=getNumberOfCells();
2026 bool easyAssign=true;
2027 const int *connI=_nodal_connec_index->getConstPointer();
2028 const int *connIOther=otherOnSameCoordsThanThis._nodal_connec_index->getConstPointer();
2030 for(int i=0;i<nbOfCellsToModify && easyAssign;i++,it+=step,connIOther++)
2032 if(it>=0 && it<nbOfCells)
2034 easyAssign=(connIOther[1]-connIOther[0])==(connI[it+1]-connI[it]);
2038 std::ostringstream oss; oss << "MEDCouplingUMesh::setPartOfMySelf2 : On pos #" << i << " id is equal to " << it << " which is not in [0," << nbOfCells << ") !";
2039 throw INTERP_KERNEL::Exception(oss.str().c_str());
2044 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index);
2049 DataArrayInt *arrOut=0,*arrIOut=0;
2050 MEDCouplingUMesh::SetPartOfIndexedArrays2(start,end,step,_nodal_connec,_nodal_connec_index,otherOnSameCoordsThanThis._nodal_connec,otherOnSameCoordsThanThis._nodal_connec_index,
2052 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrOutAuto(arrOut),arrIOutAuto(arrIOut);
2053 setConnectivity(arrOut,arrIOut,true);
2058 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
2059 * The resulting cell ids are stored at the end of the 'cellIdsKept' parameter.
2060 * Parameter \a fullyIn specifies if a cell that has part of its nodes in ids array is kept or not.
2061 * If \a fullyIn is true only cells whose ids are \b fully contained in [ \a begin,\a end ) tab will be kept.
2063 * \param [in] begin input start of array of node ids.
2064 * \param [in] end input end of array of node ids.
2065 * \param [in] fullyIn input that specifies if all node ids must be in [ \a begin,\a end ) array to consider cell to be in.
2066 * \param [in,out] cellIdsKeptArr array where all candidate cell ids are put at the end.
2068 void MEDCouplingUMesh::fillCellIdsToKeepFromNodeIds(const int *begin, const int *end, bool fullyIn, DataArrayInt *&cellIdsKeptArr) const
2070 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsKept=DataArrayInt::New(); cellIdsKept->alloc(0,1);
2071 checkConnectivityFullyDefined();
2073 int sz=getNodalConnectivity()->getMaxValue(tmp); sz=std::max(sz,0)+1;
2074 std::vector<bool> fastFinder(sz,false);
2075 for(const int *work=begin;work!=end;work++)
2076 if(*work>=0 && *work<sz)
2077 fastFinder[*work]=true;
2078 int nbOfCells=getNumberOfCells();
2079 const int *conn=getNodalConnectivity()->getConstPointer();
2080 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2081 for(int i=0;i<nbOfCells;i++)
2083 int ref=0,nbOfHit=0;
2084 for(const int *work2=conn+connIndex[i]+1;work2!=conn+connIndex[i+1];work2++)
2088 if(fastFinder[*work2])
2091 if((ref==nbOfHit && fullyIn) || (nbOfHit!=0 && !fullyIn))
2092 cellIdsKept->pushBackSilent(i);
2094 cellIdsKeptArr=cellIdsKept.retn();
2098 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2099 * this->getMeshDimension(), that bound some cells of \a this mesh.
2100 * The cells of lower dimension to include to the result mesh are selected basing on
2101 * specified node ids and the value of \a fullyIn parameter. If \a fullyIn ==\c true, a
2102 * cell is copied if its all nodes are in the array \a begin of node ids. If \a fullyIn
2103 * ==\c false, a cell is copied if any its node is in the array of node ids. The
2104 * created mesh shares the node coordinates array with \a this mesh.
2105 * \param [in] begin - the array of node ids.
2106 * \param [in] end - a pointer to the (last+1)-th element of \a begin.
2107 * \param [in] fullyIn - if \c true, then cells whose all nodes are in the
2108 * array \a begin are added, else cells whose any node is in the
2109 * array \a begin are added.
2110 * \return MEDCouplingPointSet * - new instance of MEDCouplingUMesh. The caller is
2111 * to delete this mesh using decrRef() as it is no more needed.
2112 * \throw If the coordinates array is not set.
2113 * \throw If the nodal connectivity of cells is not defined.
2114 * \throw If any node id in \a begin is not valid.
2116 * \ref cpp_mcumesh_buildFacePartOfMySelfNode "Here is a C++ example".<br>
2117 * \ref py_mcumesh_buildFacePartOfMySelfNode "Here is a Python example".
2119 MEDCouplingPointSet *MEDCouplingUMesh::buildFacePartOfMySelfNode(const int *begin, const int *end, bool fullyIn) const
2121 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc,descIndx,revDesc,revDescIndx;
2122 desc=DataArrayInt::New(); descIndx=DataArrayInt::New(); revDesc=DataArrayInt::New(); revDescIndx=DataArrayInt::New();
2123 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2124 desc=0; descIndx=0; revDesc=0; revDescIndx=0;
2125 return subMesh->buildPartOfMySelfNode(begin,end,fullyIn);
2129 * Creates a new MEDCouplingUMesh containing cells, of dimension one less than \a
2130 * this->getMeshDimension(), which bound only one cell of \a this mesh.
2131 * \param [in] keepCoords - if \c true, the result mesh shares the node coordinates
2132 * array of \a this mesh, else "free" nodes are removed from the result mesh
2133 * by calling zipCoords().
2134 * \return MEDCouplingPointSet * - a new instance of MEDCouplingUMesh. The caller is
2135 * to delete this mesh using decrRef() as it is no more needed.
2136 * \throw If the coordinates array is not set.
2137 * \throw If the nodal connectivity of cells is not defined.
2139 * \ref cpp_mcumesh_buildBoundaryMesh "Here is a C++ example".<br>
2140 * \ref py_mcumesh_buildBoundaryMesh "Here is a Python example".
2142 MEDCouplingPointSet *MEDCouplingUMesh::buildBoundaryMesh(bool keepCoords) const
2144 DataArrayInt *desc=DataArrayInt::New();
2145 DataArrayInt *descIndx=DataArrayInt::New();
2146 DataArrayInt *revDesc=DataArrayInt::New();
2147 DataArrayInt *revDescIndx=DataArrayInt::New();
2149 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2152 descIndx->decrRef();
2153 int nbOfCells=meshDM1->getNumberOfCells();
2154 const int *revDescIndxC=revDescIndx->getConstPointer();
2155 std::vector<int> boundaryCells;
2156 for(int i=0;i<nbOfCells;i++)
2157 if(revDescIndxC[i+1]-revDescIndxC[i]==1)
2158 boundaryCells.push_back(i);
2159 revDescIndx->decrRef();
2160 MEDCouplingPointSet *ret=meshDM1->buildPartOfMySelf(&boundaryCells[0],&boundaryCells[0]+boundaryCells.size(),keepCoords);
2165 * This method returns a newly created DataArrayInt instance containing ids of cells located in boundary.
2166 * A cell is detected to be on boundary if it contains one or more than one face having only one father.
2167 * This method makes the assumption that \a this is fully defined (coords,connectivity). If not an exception will be thrown.
2169 DataArrayInt *MEDCouplingUMesh::findCellIdsOnBoundary() const throw(INTERP_KERNEL::Exception)
2171 checkFullyDefined();
2172 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2173 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2174 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2175 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2177 buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx)->decrRef();
2178 desc=(DataArrayInt*)0; descIndx=(DataArrayInt*)0;
2180 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp=revDescIndx->deltaShiftIndex();
2181 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceIds=tmp->getIdsEqual(1); tmp=(DataArrayInt*)0;
2182 const int *revDescPtr=revDesc->getConstPointer();
2183 const int *revDescIndxPtr=revDescIndx->getConstPointer();
2184 int nbOfCells=getNumberOfCells();
2185 std::vector<bool> ret1(nbOfCells,false);
2187 for(const int *pt=faceIds->begin();pt!=faceIds->end();pt++)
2188 if(!ret1[revDescPtr[revDescIndxPtr[*pt]]])
2189 { ret1[revDescPtr[revDescIndxPtr[*pt]]]=true; sz++; }
2191 DataArrayInt *ret2=DataArrayInt::New();
2193 int *ret2Ptr=ret2->getPointer();
2195 for(std::vector<bool>::const_iterator it=ret1.begin();it!=ret1.end();it++,sz++)
2198 ret2->setName("BoundaryCells");
2203 * This method find in \b this cells ids that lie on mesh \b otherDimM1OnSameCoords.
2204 * \b this and \b otherDimM1OnSameCoords have to lie on the same coordinate array pointer. The coherency of that coords array with connectivity
2205 * of \b this and \b otherDimM1OnSameCoords is not important here because this method works only on connectivity.
2206 * this->getMeshDimension() - 1 must be equal to otherDimM1OnSameCoords.getMeshDimension()
2208 * s0 is the cells ids set in \b this lying on at least one node in fetched nodes in \b otherDimM1OnSameCoords.
2209 * This method method returns cells ids set s = s1 + s2 where :
2211 * - s1 are cells ids in \b this whose dim-1 constituent equals a cell in \b otherDimM1OnSameCoords.
2212 * - s2 are cells ids in \b s0 - \b s1 whose at least two neighbors are in s1.
2214 * \throw if \b otherDimM1OnSameCoords is not part of constituent of \b this, or if coordinate pointer of \b this and \b otherDimM1OnSameCoords
2215 * are not same, or if this->getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension()
2217 * \param [out] cellIdsRk0 a newly allocated array containing cells ids in \b this containg s0 in above algorithm.
2218 * \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
2219 * cellIdsRk1->transformWithIndArr(cellIdsRk0->begin(),cellIdsRk0->end());
2221 void MEDCouplingUMesh::findCellIdsLyingOn(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *&cellIdsRk0, DataArrayInt *&cellIdsRk1) const throw(INTERP_KERNEL::Exception)
2223 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2224 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : coordinates pointer are not the same ! Use tryToShareSameCoords method !");
2225 checkConnectivityFullyDefined();
2226 otherDimM1OnSameCoords.checkConnectivityFullyDefined();
2227 if(getMeshDimension()-1!=otherDimM1OnSameCoords.getMeshDimension())
2228 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : invalid mesh dimension of input mesh regarding meshdimesion of this !");
2229 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> fetchedNodeIds1=otherDimM1OnSameCoords.computeFetchedNodeIds();
2230 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0arr=getCellIdsLyingOnNodes(fetchedNodeIds1->begin(),fetchedNodeIds1->end(),false);
2231 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPart=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0arr->begin(),s0arr->end(),true));
2232 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descThisPart=DataArrayInt::New(),descIThisPart=DataArrayInt::New(),revDescThisPart=DataArrayInt::New(),revDescIThisPart=DataArrayInt::New();
2233 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> thisPartConsti=thisPart->buildDescendingConnectivity(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart);
2234 const int *revDescThisPartPtr=revDescThisPart->getConstPointer(),*revDescIThisPartPtr=revDescIThisPart->getConstPointer();
2235 DataArrayInt *idsOtherInConsti=0;
2236 bool b=thisPartConsti->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsOtherInConsti);
2237 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsOtherInConstiAuto(idsOtherInConsti);
2239 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findCellIdsLyingOn : the given mdim-1 mesh in other is not a constituent of this !");
2241 for(const int *idOther=idsOtherInConsti->begin();idOther!=idsOtherInConsti->end();idOther++)
2242 s1.insert(revDescThisPartPtr+revDescIThisPartPtr[*idOther],revDescThisPartPtr+revDescIThisPartPtr[*idOther+1]);
2243 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1arr_renum1=DataArrayInt::New(); s1arr_renum1->alloc((int)s1.size(),1); std::copy(s1.begin(),s1.end(),s1arr_renum1->getPointer());
2244 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1Comparr_renum1=s1arr_renum1->buildComplement(s0arr->getNumberOfTuples());
2245 DataArrayInt *neighThisPart=0,*neighIThisPart=0;
2246 ComputeNeighborsOfCellsAdv(descThisPart,descIThisPart,revDescThisPart,revDescIThisPart,neighThisPart,neighIThisPart);
2247 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighThisPartAuto(neighThisPart),neighIThisPartAuto(neighIThisPart);
2248 ExtractFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart,neighThisPart,neighIThisPart);// reuse of neighThisPart and neighIThisPart
2249 neighThisPartAuto=neighThisPart; neighIThisPartAuto=neighIThisPart;
2250 RemoveIdsFromIndexedArrays(s1Comparr_renum1->begin(),s1Comparr_renum1->end(),neighThisPart,neighIThisPart);
2251 neighThisPartAuto=0;
2252 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_tmp=neighIThisPart->deltaShiftIndex();
2253 const int li[2]={0,1};
2254 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2_renum2=s2_tmp->getIdsNotEqualList(li,li+2);
2255 s2_renum2->transformWithIndArr(s1Comparr_renum1->begin(),s1Comparr_renum1->end());//s2_renum2==s2_renum1
2256 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s_renum1=DataArrayInt::Aggregate(s2_renum2,s1arr_renum1,0);
2259 cellIdsRk0=s0arr.retn();
2260 cellIdsRk1=s_renum1.retn();
2264 * 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
2265 * returned. This subpart of meshdim-1 mesh is built using meshdim-1 cells in it shared only one cell in \b this.
2267 * \return a newly allocated mesh lying on the same coordinates than \b this. The caller has to deal with returned mesh.
2269 MEDCouplingUMesh *MEDCouplingUMesh::computeSkin() const throw(INTERP_KERNEL::Exception)
2271 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc=DataArrayInt::New();
2272 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx=DataArrayInt::New();
2273 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc=DataArrayInt::New();
2274 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx=DataArrayInt::New();
2276 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> meshDM1=buildDescendingConnectivity(desc,descIndx,revDesc,revDescIndx);
2277 revDesc=0; desc=0; descIndx=0;
2278 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx2=revDescIndx->deltaShiftIndex();
2279 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> part=revDescIndx2->getIdsEqual(1);
2280 return static_cast<MEDCouplingUMesh *>(meshDM1->buildPartOfMySelf(part->begin(),part->end(),true));
2284 * Finds nodes lying on the boundary of \a this mesh.
2285 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of found
2286 * nodes. The caller is to delete this array using decrRef() as it is no
2288 * \throw If the coordinates array is not set.
2289 * \throw If the nodal connectivity of cells is node defined.
2291 * \ref cpp_mcumesh_findBoundaryNodes "Here is a C++ example".<br>
2292 * \ref py_mcumesh_findBoundaryNodes "Here is a Python example".
2294 DataArrayInt *MEDCouplingUMesh::findBoundaryNodes() const
2296 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> skin=computeSkin();
2297 return skin->computeFetchedNodeIds();
2300 MEDCouplingUMesh *MEDCouplingUMesh::buildUnstructured() const throw(INTERP_KERNEL::Exception)
2303 return const_cast<MEDCouplingUMesh *>(this);
2307 * This method expects that \b this and \b otherDimM1OnSameCoords share the same coordinates array.
2308 * otherDimM1OnSameCoords->getMeshDimension() is expected to be equal to this->getMeshDimension()-1.
2309 * 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.
2310 * 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.
2311 * 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.
2313 * \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
2314 * parameter is altered during the call.
2315 * \param [out] nodeIdsToDuplicate node ids needed to be duplicated following the algorithm explain above.
2316 * \param [out] cellIdsNeededToBeRenum cell ids in \b this in which the renumber of nodes should be performed.
2317 * \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.
2319 * \warning This method modifies param \b otherDimM1OnSameCoords (for speed reasons).
2321 void MEDCouplingUMesh::findNodesToDuplicate(const MEDCouplingUMesh& otherDimM1OnSameCoords, DataArrayInt *& nodeIdsToDuplicate,
2322 DataArrayInt *& cellIdsNeededToBeRenum, DataArrayInt *& cellIdsNotModified) const throw(INTERP_KERNEL::Exception)
2324 checkFullyDefined();
2325 otherDimM1OnSameCoords.checkFullyDefined();
2326 if(getCoords()!=otherDimM1OnSameCoords.getCoords())
2327 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : meshes do not share the same coords array !");
2328 if(otherDimM1OnSameCoords.getMeshDimension()!=getMeshDimension()-1)
2329 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the mesh given in other parameter must have this->getMeshDimension()-1 !");
2330 DataArrayInt *cellIdsRk0=0,*cellIdsRk1=0;
2331 findCellIdsLyingOn(otherDimM1OnSameCoords,cellIdsRk0,cellIdsRk1);
2332 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIdsRk0Auto(cellIdsRk0),cellIdsRk1Auto(cellIdsRk1);
2333 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s0=cellIdsRk1->buildComplement(cellIdsRk0->getNumberOfTuples());
2334 s0->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2335 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(s0->begin(),s0->end(),true));
2336 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s1=m0Part->computeFetchedNodeIds();
2337 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s2=otherDimM1OnSameCoords.computeFetchedNodeIds();
2338 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> s3=s2->buildSubstraction(s1);
2339 cellIdsRk1->transformWithIndArr(cellIdsRk0Auto->begin(),cellIdsRk0Auto->end());
2341 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m0Part2=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(cellIdsRk1->begin(),cellIdsRk1->end(),true));
2342 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc00=DataArrayInt::New(),descI00=DataArrayInt::New(),revDesc00=DataArrayInt::New(),revDescI00=DataArrayInt::New();
2343 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m01=m0Part2->buildDescendingConnectivity(desc00,descI00,revDesc00,revDescI00);
2344 DataArrayInt *idsTmp=0;
2345 bool b=m01->areCellsIncludedIn(&otherDimM1OnSameCoords,2,idsTmp);
2346 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids(idsTmp);
2348 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::findNodesToDuplicate : the given mdim-1 mesh in other is not a constituent of this !");
2349 MEDCouplingUMesh::RemoveIdsFromIndexedArrays(ids->begin(),ids->end(),desc00,descI00);
2350 DataArrayInt *tmp0=0,*tmp1=0;
2351 ComputeNeighborsOfCellsAdv(desc00,descI00,revDesc00,revDescI00,tmp0,tmp1);
2352 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neigh00(tmp0);
2353 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighI00(tmp1);
2354 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn0_torenum=MEDCouplingUMesh::ComputeSpreadZoneGradually(neigh00,neighI00);
2355 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellsToModifyConn1_torenum=cellsToModifyConn0_torenum->buildComplement(neighI00->getNumberOfTuples()-1);
2356 cellsToModifyConn0_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2357 cellsToModifyConn1_torenum->transformWithIndArr(cellIdsRk1->begin(),cellIdsRk1->end());
2359 cellIdsNeededToBeRenum=cellsToModifyConn0_torenum.retn();
2360 cellIdsNotModified=cellsToModifyConn1_torenum.retn();
2361 nodeIdsToDuplicate=s3.retn();
2365 * This method operates a modification of the connectivity and coords in \b this.
2366 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2367 * its ids will be modified to id this->getNumberOfNodes()+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2368 * 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
2369 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id this->getNumberOfNodes()+0, node id nodeIdsToDuplicateBg[1] will have id this->getNumberOfNodes()+1,
2370 * node id nodeIdsToDuplicateBg[2] will have id this->getNumberOfNodes()+2...
2372 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2374 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2375 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2377 void MEDCouplingUMesh::duplicateNodes(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd) throw(INTERP_KERNEL::Exception)
2379 int nbOfNodes=getNumberOfNodes();
2380 duplicateNodesInCoords(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd);
2381 duplicateNodesInConn(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,nbOfNodes);
2385 * Changes ids of nodes within the nodal connectivity arrays according to a permutation
2386 * array in "Old to New" mode. The node coordinates array is \b not changed by this method.
2387 * This method is a generalization of shiftNodeNumbersInConn().
2388 * \warning This method performs no check of validity of new ids. **Use it with care !**
2389 * \param [in] newNodeNumbersO2N - a permutation array, of length \a
2390 * this->getNumberOfNodes(), in "Old to New" mode.
2391 * See \ref MEDCouplingArrayRenumbering for more info on renumbering modes.
2392 * \throw If the nodal connectivity of cells is not defined.
2394 * \ref cpp_mcumesh_renumberNodesInConn "Here is a C++ example".<br>
2395 * \ref py_mcumesh_renumberNodesInConn "Here is a Python example".
2397 void MEDCouplingUMesh::renumberNodesInConn(const int *newNodeNumbersO2N)
2399 checkConnectivityFullyDefined();
2400 int *conn=getNodalConnectivity()->getPointer();
2401 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2402 int nbOfCells=getNumberOfCells();
2403 for(int i=0;i<nbOfCells;i++)
2404 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2406 int& node=conn[iconn];
2407 if(node>=0)//avoid polyhedron separator
2409 node=newNodeNumbersO2N[node];
2412 _nodal_connec->declareAsNew();
2417 * This method renumbers nodes \b in \b connectivity \b only \b without \b any \b reference \b to \b coords.
2418 * This method performs no check on the fact that new coordinate ids are valid. \b Use \b it \b with \b care !
2419 * This method is an specialization of \ref ParaMEDMEM::MEDCouplingUMesh::renumberNodesInConn "renumberNodesInConn method".
2421 * \param [in] delta specifies the shift size applied to nodeId in nodal connectivity in \b this.
2423 void MEDCouplingUMesh::shiftNodeNumbersInConn(int delta) throw(INTERP_KERNEL::Exception)
2425 checkConnectivityFullyDefined();
2426 int *conn=getNodalConnectivity()->getPointer();
2427 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2428 int nbOfCells=getNumberOfCells();
2429 for(int i=0;i<nbOfCells;i++)
2430 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2432 int& node=conn[iconn];
2433 if(node>=0)//avoid polyhedron separator
2438 _nodal_connec->declareAsNew();
2443 * This method operates a modification of the connectivity in \b this.
2444 * 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.
2445 * Every time that a node id in [ \b nodeIdsToDuplicateBg, \b nodeIdsToDuplicateEnd ) will append in nodal connectivity of \b this
2446 * its ids will be modified to id offset+std::distance(nodeIdsToDuplicateBg,std::find(nodeIdsToDuplicateBg,nodeIdsToDuplicateEnd,id)).
2447 * 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
2448 * renumbered. The node id nodeIdsToDuplicateBg[0] will have id offset+0, node id nodeIdsToDuplicateBg[1] will have id offset+1,
2449 * node id nodeIdsToDuplicateBg[2] will have id offset+2...
2451 * As a consequence nodal connectivity array length will remain unchanged by this method, and nodal connectivity index array will remain unchanged by this method.
2452 * As an another consequense after the call of this method \b this can be transiently non cohrent.
2454 * \param [in] nodeIdsToDuplicateBg begin of node ids (included) to be duplicated in connectivity only
2455 * \param [in] nodeIdsToDuplicateEnd end of node ids (excluded) to be duplicated in connectivity only
2456 * \param [in] offset the offset applied to all node ids in connectivity that are in [ \a nodeIdsToDuplicateBg, \a nodeIdsToDuplicateEnd ).
2458 void MEDCouplingUMesh::duplicateNodesInConn(const int *nodeIdsToDuplicateBg, const int *nodeIdsToDuplicateEnd, int offset) throw(INTERP_KERNEL::Exception)
2460 checkConnectivityFullyDefined();
2461 std::map<int,int> m;
2463 for(const int *work=nodeIdsToDuplicateBg;work!=nodeIdsToDuplicateEnd;work++,val++)
2465 int *conn=getNodalConnectivity()->getPointer();
2466 const int *connIndex=getNodalConnectivityIndex()->getConstPointer();
2467 int nbOfCells=getNumberOfCells();
2468 for(int i=0;i<nbOfCells;i++)
2469 for(int iconn=connIndex[i]+1;iconn!=connIndex[i+1];iconn++)
2471 int& node=conn[iconn];
2472 if(node>=0)//avoid polyhedron separator
2474 std::map<int,int>::iterator it=m.find(node);
2483 * This method renumbers cells of \a this using the array specified by [old2NewBg;old2NewBg+getNumberOfCells())
2485 * Contrary to MEDCouplingPointSet::renumberNodes, this method makes a permutation without any fuse of cell.
2486 * After the call of this method the number of cells remains the same as before.
2488 * If 'check' equals true the method will check that any elements in [ \a old2NewBg; \a old2NewEnd ) is unique ; if not
2489 * an INTERP_KERNEL::Exception will be thrown. When 'check' equals true [ \a old2NewBg ; \a old2NewEnd ) is not expected to
2490 * be strictly in [0;this->getNumberOfCells()).
2492 * If 'check' equals false the method will not check the content of [ \a old2NewBg ; \a old2NewEnd ).
2493 * To avoid any throw of SIGSEGV when 'check' equals false, the elements in [ \a old2NewBg ; \a old2NewEnd ) should be unique and
2494 * should be contained in[0;this->getNumberOfCells()).
2496 * \param [in] old2NewBg is expected to be a dynamically allocated pointer of size at least equal to this->getNumberOfCells()
2498 void MEDCouplingUMesh::renumberCells(const int *old2NewBg, bool check) throw(INTERP_KERNEL::Exception)
2500 checkConnectivityFullyDefined();
2501 int nbCells=getNumberOfCells();
2502 const int *array=old2NewBg;
2504 array=DataArrayInt::CheckAndPreparePermutation(old2NewBg,old2NewBg+nbCells);
2506 const int *conn=_nodal_connec->getConstPointer();
2507 const int *connI=_nodal_connec_index->getConstPointer();
2508 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::New(); o2n->useArray(array,false,C_DEALLOC,nbCells,1);
2509 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(nbCells);
2510 const int *n2oPtr=n2o->begin();
2511 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
2512 newConn->alloc(_nodal_connec->getNumberOfTuples(),_nodal_connec->getNumberOfComponents());
2513 newConn->copyStringInfoFrom(*_nodal_connec);
2514 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
2515 newConnI->alloc(_nodal_connec_index->getNumberOfTuples(),_nodal_connec_index->getNumberOfComponents());
2516 newConnI->copyStringInfoFrom(*_nodal_connec_index);
2518 int *newC=newConn->getPointer();
2519 int *newCI=newConnI->getPointer();
2522 for(int i=0;i<nbCells;i++)
2525 int nbOfElts=connI[pos+1]-connI[pos];
2526 newC=std::copy(conn+connI[pos],conn+connI[pos+1],newC);
2531 setConnectivity(newConn,newConnI);
2533 free(const_cast<int *>(array));
2537 * Finds cells whose bounding boxes intersect a given bounding box.
2538 * \param [in] bbox - an array defining the bounding box via coordinates of its
2539 * extremum points in "no interlace" mode, i.e. xMin, xMax, yMin, yMax, zMin,
2541 * \param [in] eps - a factor used to increase size of the bounding box of cell
2542 * before comparing it with \a bbox. This factor is multiplied by the maximal
2543 * extent of the bounding box of cell to produce an addition to this bounding box.
2544 * \return DataArrayInt * - a new instance of DataArrayInt holding ids for found
2545 * cells. The caller is to delete this array using decrRef() as it is no more
2547 * \throw If the coordinates array is not set.
2548 * \throw If the nodal connectivity of cells is not defined.
2550 * \ref cpp_mcumesh_getCellsInBoundingBox "Here is a C++ example".<br>
2551 * \ref py_mcumesh_getCellsInBoundingBox "Here is a Python example".
2553 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const double *bbox, double eps) const
2555 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2556 if(getMeshDimension()==-1)
2558 elems->pushBackSilent(0);
2559 return elems.retn();
2561 int dim=getSpaceDimension();
2562 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2563 const int* conn = getNodalConnectivity()->getConstPointer();
2564 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2565 const double* coords = getCoords()->getConstPointer();
2566 int nbOfCells=getNumberOfCells();
2567 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2569 for (int i=0; i<dim; i++)
2571 elem_bb[i*2]=std::numeric_limits<double>::max();
2572 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2575 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2577 int node= conn[inode];
2578 if(node>=0)//avoid polyhedron separator
2580 for (int idim=0; idim<dim; idim++)
2582 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2584 elem_bb[idim*2] = coords[node*dim+idim] ;
2586 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2588 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2593 if (intersectsBoundingBox(elem_bb, bbox, dim, eps))
2594 elems->pushBackSilent(ielem);
2596 return elems.retn();
2600 * Given a boundary box 'bbox' returns elements 'elems' contained in this 'bbox' or touching 'bbox' (within 'eps' distance).
2601 * Warning 'elems' is incremented during the call so if elems is not empty before call returned elements will be
2602 * added in 'elems' parameter.
2604 DataArrayInt *MEDCouplingUMesh::getCellsInBoundingBox(const INTERP_KERNEL::DirectedBoundingBox& bbox, double eps)
2606 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> elems=DataArrayInt::New(); elems->alloc(0,1);
2607 if(getMeshDimension()==-1)
2609 elems->pushBackSilent(0);
2610 return elems.retn();
2612 int dim=getSpaceDimension();
2613 INTERP_KERNEL::AutoPtr<double> elem_bb=new double[2*dim];
2614 const int* conn = getNodalConnectivity()->getConstPointer();
2615 const int* conn_index= getNodalConnectivityIndex()->getConstPointer();
2616 const double* coords = getCoords()->getConstPointer();
2617 int nbOfCells=getNumberOfCells();
2618 for ( int ielem=0; ielem<nbOfCells;ielem++ )
2620 for (int i=0; i<dim; i++)
2622 elem_bb[i*2]=std::numeric_limits<double>::max();
2623 elem_bb[i*2+1]=-std::numeric_limits<double>::max();
2626 for (int inode=conn_index[ielem]+1; inode<conn_index[ielem+1]; inode++)//+1 due to offset of cell type.
2628 int node= conn[inode];
2629 if(node>=0)//avoid polyhedron separator
2631 for (int idim=0; idim<dim; idim++)
2633 if ( coords[node*dim+idim] < elem_bb[idim*2] )
2635 elem_bb[idim*2] = coords[node*dim+idim] ;
2637 if ( coords[node*dim+idim] > elem_bb[idim*2+1] )
2639 elem_bb[idim*2+1] = coords[node*dim+idim] ;
2644 if(intersectsBoundingBox(bbox, elem_bb, dim, eps))
2645 elems->pushBackSilent(ielem);
2647 return elems.retn();
2651 * Returns a type of a cell by its id.
2652 * \param [in] cellId - the id of the cell of interest.
2653 * \return INTERP_KERNEL::NormalizedCellType - enumeration item describing the cell type.
2654 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2656 INTERP_KERNEL::NormalizedCellType MEDCouplingUMesh::getTypeOfCell(int cellId) const
2658 const int *ptI=_nodal_connec_index->getConstPointer();
2659 const int *pt=_nodal_connec->getConstPointer();
2660 if(cellId>=0 && cellId<(int)_nodal_connec_index->getNbOfElems()-1)
2661 return (INTERP_KERNEL::NormalizedCellType) pt[ptI[cellId]];
2664 std::ostringstream oss; oss << "MEDCouplingUMesh::getTypeOfCell : Requesting type of cell #" << cellId << " but it should be in [0," << _nodal_connec_index->getNbOfElems()-1 << ") !";
2665 throw INTERP_KERNEL::Exception(oss.str().c_str());
2670 * This method returns a newly allocated array containing cell ids (ascendingly sorted) whose geometric type are equal to type.
2671 * This method does not throw exception if geometric type \a type is not in \a this.
2672 * This method throws an INTERP_KERNEL::Exception if meshdimension of \b this is not equal to those of \b type.
2673 * The coordinates array is not considered here.
2675 * \param [in] type the geometric type
2676 * \return cell ids in this having geometric type \a type.
2678 DataArrayInt *MEDCouplingUMesh::giveCellsWithType(INTERP_KERNEL::NormalizedCellType type) const throw(INTERP_KERNEL::Exception)
2681 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
2683 checkConnectivityFullyDefined();
2684 int nbCells=getNumberOfCells();
2685 int mdim=getMeshDimension();
2686 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
2687 if(mdim!=(int)cm.getDimension())
2688 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::giveCellsWithType : Mismatch between mesh dimension and dimension of the cell !");
2689 const int *ptI=_nodal_connec_index->getConstPointer();
2690 const int *pt=_nodal_connec->getConstPointer();
2691 for(int i=0;i<nbCells;i++)
2693 if((INTERP_KERNEL::NormalizedCellType)pt[ptI[i]]==type)
2694 ret->pushBackSilent(i);
2700 * Returns nb of cells having the geometric type \a type. No throw if no cells in \a this has the geometric type \a type.
2702 int MEDCouplingUMesh::getNumberOfCellsWithType(INTERP_KERNEL::NormalizedCellType type) const
2704 const int *ptI=_nodal_connec_index->getConstPointer();
2705 const int *pt=_nodal_connec->getConstPointer();
2706 int nbOfCells=getNumberOfCells();
2708 for(int i=0;i<nbOfCells;i++)
2709 if((INTERP_KERNEL::NormalizedCellType) pt[ptI[i]]==type)
2715 * Returns the nodal connectivity of a given cell.
2716 * The separator of faces within polyhedron connectivity (-1) is not returned, thus
2717 * all returned node ids can be used in getCoordinatesOfNode().
2718 * \param [in] cellId - an id of the cell of interest.
2719 * \param [in,out] conn - a vector where the node ids are appended. It is not
2720 * cleared before the appending.
2721 * \throw If \a cellId is invalid. Valid range is [0, \a this->getNumberOfCells() ).
2723 void MEDCouplingUMesh::getNodeIdsOfCell(int cellId, std::vector<int>& conn) const
2725 const int *ptI=_nodal_connec_index->getConstPointer();
2726 const int *pt=_nodal_connec->getConstPointer();
2727 for(const int *w=pt+ptI[cellId]+1;w!=pt+ptI[cellId+1];w++)
2732 std::string MEDCouplingUMesh::simpleRepr() const
2734 static const char msg0[]="No coordinates specified !";
2735 std::ostringstream ret;
2736 ret << "Unstructured mesh with name : \"" << getName() << "\"\n";
2737 ret << "Description of mesh : \"" << getDescription() << "\"\n";
2739 double tt=getTime(tmpp1,tmpp2);
2740 ret << "Time attached to the mesh [unit] : " << tt << " [" << getTimeUnit() << "]\n";
2741 ret << "Iteration : " << tmpp1 << " Order : " << tmpp2 << "\n";
2743 { ret << "Mesh dimension : " << _mesh_dim << "\nSpace dimension : "; }
2745 { ret << " Mesh dimension has not been set or is invalid !"; }
2748 const int spaceDim=getSpaceDimension();
2749 ret << spaceDim << "\nInfo attached on space dimension : ";
2750 for(int i=0;i<spaceDim;i++)
2751 ret << "\"" << _coords->getInfoOnComponent(i) << "\" ";
2755 ret << msg0 << "\n";
2756 ret << "Number of nodes : ";
2758 ret << getNumberOfNodes() << "\n";
2760 ret << msg0 << "\n";
2761 ret << "Number of cells : ";
2762 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2763 ret << getNumberOfCells() << "\n";
2765 ret << "No connectivity specified !" << "\n";
2766 ret << "Cell types present : ";
2767 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=_types.begin();iter!=_types.end();iter++)
2769 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(*iter);
2770 ret << cm.getRepr() << " ";
2776 std::string MEDCouplingUMesh::advancedRepr() const
2778 std::ostringstream ret;
2779 ret << simpleRepr();
2780 ret << "\nCoordinates array : \n___________________\n\n";
2782 _coords->reprWithoutNameStream(ret);
2784 ret << "No array set !\n";
2785 ret << "\n\nConnectivity arrays : \n_____________________\n\n";
2786 reprConnectivityOfThisLL(ret);
2791 * This method returns a C++ code that is a dump of \a this.
2792 * This method will throw if this is not fully defined.
2794 std::string MEDCouplingUMesh::cppRepr() const throw(INTERP_KERNEL::Exception)
2796 static const char coordsName[]="coords";
2797 static const char connName[]="conn";
2798 static const char connIName[]="connI";
2799 checkFullyDefined();
2800 std::ostringstream ret; ret << "// coordinates" << std::endl;
2801 _coords->reprCppStream(coordsName,ret); ret << std::endl << "// connectivity" << std::endl;
2802 _nodal_connec->reprCppStream(connName,ret); ret << std::endl;
2803 _nodal_connec_index->reprCppStream(connIName,ret); ret << std::endl;
2804 ret << "MEDCouplingUMesh *mesh=MEDCouplingUMesh::New(\"" << getName() << "\"," << getMeshDimension() << ");" << std::endl;
2805 ret << "mesh->setCoords(" << coordsName << ");" << std::endl;
2806 ret << "mesh->setConnectivity(" << connName << "," << connIName << ",true);" << std::endl;
2807 ret << coordsName << "->decrRef(); " << connName << "->decrRef(); " << connIName << "->decrRef();" << std::endl;
2811 std::string MEDCouplingUMesh::reprConnectivityOfThis() const
2813 std::ostringstream ret;
2814 reprConnectivityOfThisLL(ret);
2819 * This method builds a newly allocated instance (with the same name than \a this) that the caller has the responsability to deal with.
2820 * This method returns an instance with all arrays allocated (connectivity, connectivity index, coordinates)
2821 * but with length of these arrays set to 0. It allows to define an "empty" mesh (with nor cells nor nodes but compliant with
2824 * This method expects that \a this has a mesh dimension set and higher or equal to 0. If not an exception will be thrown.
2825 * 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
2826 * with number of tuples set to 0, if not the array is taken as this in the returned instance.
2828 MEDCouplingUMesh *MEDCouplingUMesh::buildSetInstanceFromThis(int spaceDim) const throw(INTERP_KERNEL::Exception)
2830 int mdim=getMeshDimension();
2832 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSetInstanceFromThis : invalid mesh dimension ! Should be >= 0 !");
2833 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
2834 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1,tmp2;
2835 bool needToCpyCT=true;
2838 tmp1=DataArrayInt::New(); tmp1->alloc(0,1);
2846 if(!_nodal_connec_index)
2848 tmp2=DataArrayInt::New(); tmp2->alloc(1,1); tmp2->setIJ(0,0,0);
2853 tmp2=_nodal_connec_index;
2856 ret->setConnectivity(tmp1,tmp2,false);
2861 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coords=DataArrayDouble::New(); coords->alloc(0,spaceDim);
2862 ret->setCoords(coords);
2865 ret->setCoords(_coords);
2869 void MEDCouplingUMesh::reprConnectivityOfThisLL(std::ostringstream& stream) const
2871 if(_nodal_connec!=0 && _nodal_connec_index!=0)
2873 int nbOfCells=getNumberOfCells();
2874 const int *c=_nodal_connec->getConstPointer();
2875 const int *ci=_nodal_connec_index->getConstPointer();
2876 for(int i=0;i<nbOfCells;i++)
2878 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)c[ci[i]]);
2879 stream << "Cell #" << i << " " << cm.getRepr() << " : ";
2880 std::copy(c+ci[i]+1,c+ci[i+1],std::ostream_iterator<int>(stream," "));
2885 stream << "Connectivity not defined !\n";
2888 int MEDCouplingUMesh::getNumberOfNodesInCell(int cellId) const
2890 const int *ptI=_nodal_connec_index->getConstPointer();
2891 const int *pt=_nodal_connec->getConstPointer();
2892 if(pt[ptI[cellId]]!=INTERP_KERNEL::NORM_POLYHED)
2893 return ptI[cellId+1]-ptI[cellId]-1;
2895 return (int)std::count_if(pt+ptI[cellId]+1,pt+ptI[cellId+1],std::bind2nd(std::not_equal_to<int>(),-1));
2899 * Returns types of cells of the specified part of \a this mesh.
2900 * This method avoids computing sub-mesh explicitely to get its types.
2901 * \param [in] begin - an array of cell ids of interest.
2902 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
2903 * \return std::set<INTERP_KERNEL::NormalizedCellType> - a set of enumeration items
2904 * describing the cell types.
2905 * \throw If the coordinates array is not set.
2906 * \throw If the nodal connectivity of cells is not defined.
2909 std::set<INTERP_KERNEL::NormalizedCellType> MEDCouplingUMesh::getTypesOfPart(const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
2911 checkFullyDefined();
2912 std::set<INTERP_KERNEL::NormalizedCellType> ret;
2913 const int *conn=_nodal_connec->getConstPointer();
2914 const int *connIndex=_nodal_connec_index->getConstPointer();
2915 for(const int *w=begin;w!=end;w++)
2916 ret.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]);
2921 * Defines the nodal connectivity using given connectivity arrays. Optionally updates
2922 * a set of types of cells constituting \a this mesh.
2923 * This method is for advanced users having prepared their connectivity before. For
2924 * more info on using this method see \ref MEDCouplingUMeshAdvBuild.
2925 * \param [in] conn - the nodal connectivity array.
2926 * \param [in] connIndex - the nodal connectivity index array.
2927 * \param [in] isComputingTypes - if \c true, the set of types constituting \a this
2930 void MEDCouplingUMesh::setConnectivity(DataArrayInt *conn, DataArrayInt *connIndex, bool isComputingTypes)
2932 DataArrayInt::SetArrayIn(conn,_nodal_connec);
2933 DataArrayInt::SetArrayIn(connIndex,_nodal_connec_index);
2934 if(isComputingTypes)
2940 * Copy constructor. If 'deepCpy' is false \a this is a shallow copy of other.
2941 * If 'deeCpy' is true all arrays (coordinates and connectivities) are deeply copied.
2943 MEDCouplingUMesh::MEDCouplingUMesh(const MEDCouplingUMesh& other, bool deepCopy):MEDCouplingPointSet(other,deepCopy),_mesh_dim(other._mesh_dim),
2944 _nodal_connec(0),_nodal_connec_index(0),
2945 _types(other._types)
2947 if(other._nodal_connec)
2948 _nodal_connec=other._nodal_connec->performCpy(deepCopy);
2949 if(other._nodal_connec_index)
2950 _nodal_connec_index=other._nodal_connec_index->performCpy(deepCopy);
2953 MEDCouplingUMesh::~MEDCouplingUMesh()
2956 _nodal_connec->decrRef();
2957 if(_nodal_connec_index)
2958 _nodal_connec_index->decrRef();
2962 * Recomputes a set of cell types of \a this mesh. For more info see
2963 * \ref MEDCouplingUMeshNodalConnectivity.
2965 void MEDCouplingUMesh::computeTypes()
2967 if(_nodal_connec && _nodal_connec_index)
2970 const int *conn=_nodal_connec->getConstPointer();
2971 const int *connIndex=_nodal_connec_index->getConstPointer();
2972 int nbOfElem=_nodal_connec_index->getNbOfElems()-1;
2974 for(const int *pt=connIndex;pt !=connIndex+nbOfElem;pt++)
2975 _types.insert((INTERP_KERNEL::NormalizedCellType)conn[*pt]);
2980 * This method checks that all arrays are set. If yes nothing done if no an exception is thrown.
2982 void MEDCouplingUMesh::checkFullyDefined() const throw(INTERP_KERNEL::Exception)
2984 if(!_nodal_connec_index || !_nodal_connec || !_coords)
2985 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity and coordinates set in unstructured mesh.");
2989 * This method checks that all connectivity arrays are set. If yes nothing done if no an exception is thrown.
2991 void MEDCouplingUMesh::checkConnectivityFullyDefined() const throw(INTERP_KERNEL::Exception)
2993 if(!_nodal_connec_index || !_nodal_connec)
2994 throw INTERP_KERNEL::Exception("Reverse nodal connectivity computation requires full connectivity set in unstructured mesh.");
2998 * Returns a number of cells constituting \a this mesh.
2999 * \return int - the number of cells in \a this mesh.
3000 * \throw If the nodal connectivity of cells is not defined.
3002 int MEDCouplingUMesh::getNumberOfCells() const
3004 if(_nodal_connec_index)
3005 return _nodal_connec_index->getNumberOfTuples()-1;
3010 throw INTERP_KERNEL::Exception("Unable to get number of cells because no connectivity specified !");
3014 * Returns a dimension of \a this mesh, i.e. a dimension of cells constituting \a this
3015 * mesh. For more info see \ref MEDCouplingMeshesPage.
3016 * \return int - the dimension of \a this mesh.
3017 * \throw If the mesh dimension is not defined using setMeshDimension().
3019 int MEDCouplingUMesh::getMeshDimension() const
3022 throw INTERP_KERNEL::Exception("No mesh dimension specified !");
3027 * Returns a length of the nodal connectivity array.
3028 * This method is for test reason. Normally the integer returned is not useable by
3029 * user. For more info see \ref MEDCouplingUMeshNodalConnectivity.
3030 * \return int - the length of the nodal connectivity array.
3032 int MEDCouplingUMesh::getMeshLength() const
3034 return _nodal_connec->getNbOfElems();
3038 * First step of serialization process. Used by ParaMEDMEM and MEDCouplingCorba to transfert data between process.
3040 void MEDCouplingUMesh::getTinySerializationInformation(std::vector<double>& tinyInfoD, std::vector<int>& tinyInfo, std::vector<std::string>& littleStrings) const
3042 MEDCouplingPointSet::getTinySerializationInformation(tinyInfoD,tinyInfo,littleStrings);
3043 tinyInfo.push_back(getMeshDimension());
3044 tinyInfo.push_back(getNumberOfCells());
3046 tinyInfo.push_back(getMeshLength());
3048 tinyInfo.push_back(-1);
3052 * First step of unserialization process.
3054 bool MEDCouplingUMesh::isEmptyMesh(const std::vector<int>& tinyInfo) const
3056 return tinyInfo[6]<=0;
3060 * Second step of serialization process.
3061 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3063 void MEDCouplingUMesh::resizeForUnserialization(const std::vector<int>& tinyInfo, DataArrayInt *a1, DataArrayDouble *a2, std::vector<std::string>& littleStrings) const
3065 MEDCouplingPointSet::resizeForUnserialization(tinyInfo,a1,a2,littleStrings);
3067 a1->alloc(tinyInfo[7]+tinyInfo[6]+1,1);
3071 * Third and final step of serialization process.
3073 void MEDCouplingUMesh::serialize(DataArrayInt *&a1, DataArrayDouble *&a2) const
3075 MEDCouplingPointSet::serialize(a1,a2);
3076 if(getMeshDimension()>-1)
3078 a1=DataArrayInt::New();
3079 a1->alloc(getMeshLength()+getNumberOfCells()+1,1);
3080 int *ptA1=a1->getPointer();
3081 const int *conn=getNodalConnectivity()->getConstPointer();
3082 const int *index=getNodalConnectivityIndex()->getConstPointer();
3083 ptA1=std::copy(index,index+getNumberOfCells()+1,ptA1);
3084 std::copy(conn,conn+getMeshLength(),ptA1);
3091 * Second and final unserialization process.
3092 * \param tinyInfo must be equal to the result given by getTinySerializationInformation method.
3094 void MEDCouplingUMesh::unserialization(const std::vector<double>& tinyInfoD, const std::vector<int>& tinyInfo, const DataArrayInt *a1, DataArrayDouble *a2, const std::vector<std::string>& littleStrings)
3096 MEDCouplingPointSet::unserialization(tinyInfoD,tinyInfo,a1,a2,littleStrings);
3097 setMeshDimension(tinyInfo[5]);
3101 const int *recvBuffer=a1->getConstPointer();
3102 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnecIndex=DataArrayInt::New();
3103 myConnecIndex->alloc(tinyInfo[6]+1,1);
3104 std::copy(recvBuffer,recvBuffer+tinyInfo[6]+1,myConnecIndex->getPointer());
3105 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> myConnec=DataArrayInt::New();
3106 myConnec->alloc(tinyInfo[7],1);
3107 std::copy(recvBuffer+tinyInfo[6]+1,recvBuffer+tinyInfo[6]+1+tinyInfo[7],myConnec->getPointer());
3108 setConnectivity(myConnec, myConnecIndex);
3113 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf2.
3114 * CellIds are given using range specified by a start an end and step.
3116 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords2(int start, int end, int step) const
3118 checkFullyDefined();
3119 int ncell=getNumberOfCells();
3120 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3121 ret->_mesh_dim=_mesh_dim;
3122 ret->setCoords(_coords);
3123 int newNbOfCells=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : ");
3124 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(newNbOfCells+1,1);
3125 int *newConnIPtr=newConnI->getPointer(); *newConnIPtr=0;
3127 const int *conn=_nodal_connec->getConstPointer();
3128 const int *connIndex=_nodal_connec_index->getConstPointer();
3129 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3131 if(work>=0 && work<ncell)
3133 newConnIPtr[1]=newConnIPtr[0]+connIndex[work+1]-connIndex[work];
3137 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords2 : On pos #" << i << " input cell id =" << work << " should be in [0," << ncell << ") !";
3138 throw INTERP_KERNEL::Exception(oss.str().c_str());
3141 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(newConnIPtr[0],1);
3142 int *newConnPtr=newConn->getPointer();
3143 std::set<INTERP_KERNEL::NormalizedCellType> types;
3145 for(int i=0;i<newNbOfCells;i++,newConnIPtr++,work+=step)
3147 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[work]]);
3148 newConnPtr=std::copy(conn+connIndex[work],conn+connIndex[work+1],newConnPtr);
3150 ret->setConnectivity(newConn,newConnI,false);
3152 ret->copyTinyInfoFrom(this);
3157 * This is the low algorithm of MEDCouplingUMesh::buildPartOfMySelf.
3158 * Keeps from \a this only cells which constituing point id are in the ids specified by [ \a begin,\a end ).
3159 * The return newly allocated mesh will share the same coordinates as \a this.
3161 MEDCouplingPointSet *MEDCouplingUMesh::buildPartOfMySelfKeepCoords(const int *begin, const int *end) const
3163 checkConnectivityFullyDefined();
3164 int ncell=getNumberOfCells();
3165 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New();
3166 ret->_mesh_dim=_mesh_dim;
3167 ret->setCoords(_coords);
3168 std::size_t nbOfElemsRet=std::distance(begin,end);
3169 int *connIndexRet=(int *)malloc((nbOfElemsRet+1)*sizeof(int));
3171 const int *conn=_nodal_connec->getConstPointer();
3172 const int *connIndex=_nodal_connec_index->getConstPointer();
3174 for(const int *work=begin;work!=end;work++,newNbring++)
3176 if(*work>=0 && *work<ncell)
3177 connIndexRet[newNbring+1]=connIndexRet[newNbring]+connIndex[*work+1]-connIndex[*work];
3181 std::ostringstream oss; oss << "MEDCouplingUMesh::buildPartOfMySelfKeepCoords : On pos #" << std::distance(begin,work) << " input cell id =" << *work << " should be in [0," << ncell << ") !";
3182 throw INTERP_KERNEL::Exception(oss.str().c_str());
3185 int *connRet=(int *)malloc(connIndexRet[nbOfElemsRet]*sizeof(int));
3186 int *connRetWork=connRet;
3187 std::set<INTERP_KERNEL::NormalizedCellType> types;
3188 for(const int *work=begin;work!=end;work++)
3190 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*work]]);
3191 connRetWork=std::copy(conn+connIndex[*work],conn+connIndex[*work+1],connRetWork);
3193 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connRetArr=DataArrayInt::New();
3194 connRetArr->useArray(connRet,true,C_DEALLOC,connIndexRet[nbOfElemsRet],1);
3195 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connIndexRetArr=DataArrayInt::New();
3196 connIndexRetArr->useArray(connIndexRet,true,C_DEALLOC,(int)nbOfElemsRet+1,1);
3197 ret->setConnectivity(connRetArr,connIndexRetArr,false);
3199 ret->copyTinyInfoFrom(this);
3204 * Returns a new MEDCouplingFieldDouble containing volumes of cells constituting \a this
3206 * For 1D cells, the returned field contains lengths.<br>
3207 * For 2D cells, the returned field contains areas.<br>
3208 * For 3D cells, the returned field contains volumes.
3209 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3210 * orientation, i.e. the volume is always positive.
3211 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on cells
3212 * and one time . The caller is to delete this field using decrRef() as it is no
3215 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureField(bool isAbs) const
3217 std::string name="MeasureOfMesh_";
3219 int nbelem=getNumberOfCells();
3220 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> field=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3221 field->setName(name.c_str());
3222 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3223 array->alloc(nbelem,1);
3224 double *area_vol=array->getPointer();
3225 field->setArray(array) ; array=0;
3226 field->setMesh(const_cast<MEDCouplingUMesh *>(this));
3227 field->synchronizeTimeWithMesh();
3228 if(getMeshDimension()!=-1)
3231 INTERP_KERNEL::NormalizedCellType type;
3232 int dim_space=getSpaceDimension();
3233 const double *coords=getCoords()->getConstPointer();
3234 const int *connec=getNodalConnectivity()->getConstPointer();
3235 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3236 for(int iel=0;iel<nbelem;iel++)
3238 ipt=connec_index[iel];
3239 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3240 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);
3243 std::transform(area_vol,area_vol+nbelem,area_vol,std::ptr_fun<double,double>(fabs));
3247 area_vol[0]=std::numeric_limits<double>::max();
3249 return field.retn();
3253 * Returns a new DataArrayDouble containing volumes of specified cells of \a this
3255 * For 1D cells, the returned array contains lengths.<br>
3256 * For 2D cells, the returned array contains areas.<br>
3257 * For 3D cells, the returned array contains volumes.
3258 * This method avoids building explicitly a part of \a this mesh to perform the work.
3259 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3260 * orientation, i.e. the volume is always positive.
3261 * \param [in] begin - an array of cell ids of interest.
3262 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3263 * \return DataArrayDouble * - a new instance of DataArrayDouble. The caller is to
3264 * delete this array using decrRef() as it is no more needed.
3266 * \ref cpp_mcumesh_getPartMeasureField "Here is a C++ example".<br>
3267 * \ref py_mcumesh_getPartMeasureField "Here is a Python example".
3268 * \sa getMeasureField()
3270 DataArrayDouble *MEDCouplingUMesh::getPartMeasureField(bool isAbs, const int *begin, const int *end) const
3272 std::string name="PartMeasureOfMesh_";
3274 int nbelem=(int)std::distance(begin,end);
3275 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3276 array->setName(name.c_str());
3277 array->alloc(nbelem,1);
3278 double *area_vol=array->getPointer();
3279 if(getMeshDimension()!=-1)
3282 INTERP_KERNEL::NormalizedCellType type;
3283 int dim_space=getSpaceDimension();
3284 const double *coords=getCoords()->getConstPointer();
3285 const int *connec=getNodalConnectivity()->getConstPointer();
3286 const int *connec_index=getNodalConnectivityIndex()->getConstPointer();
3287 for(const int *iel=begin;iel!=end;iel++)
3289 ipt=connec_index[*iel];
3290 type=(INTERP_KERNEL::NormalizedCellType)connec[ipt];
3291 *area_vol++=INTERP_KERNEL::computeVolSurfOfCell2<int,INTERP_KERNEL::ALL_C_MODE>(type,connec+ipt+1,connec_index[*iel+1]-ipt-1,coords,dim_space);
3294 std::transform(array->getPointer(),area_vol,array->getPointer(),std::ptr_fun<double,double>(fabs));
3298 area_vol[0]=std::numeric_limits<double>::max();
3300 return array.retn();
3304 * Returns a new MEDCouplingFieldDouble containing volumes of cells of a dual mesh of
3305 * \a this one. The returned field contains the dual cell volume for each corresponding
3306 * node in \a this mesh. In other words, the field returns the getMeasureField() of
3307 * the dual mesh in P1 sens of \a this.<br>
3308 * For 1D cells, the returned field contains lengths.<br>
3309 * For 2D cells, the returned field contains areas.<br>
3310 * For 3D cells, the returned field contains volumes.
3311 * This method is useful to check "P1*" conservative interpolators.
3312 * \param [in] isAbs - if \c true, the computed cell volume does not reflect cell
3313 * orientation, i.e. the volume is always positive.
3314 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3315 * nodes and one time. The caller is to delete this array using decrRef() as
3316 * it is no more needed.
3318 MEDCouplingFieldDouble *MEDCouplingUMesh::getMeasureFieldOnNode(bool isAbs) const
3320 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> tmp=getMeasureField(isAbs);
3321 std::string name="MeasureOnNodeOfMesh_";
3323 int nbNodes=getNumberOfNodes();
3324 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_NODES);
3325 double cst=1./((double)getMeshDimension()+1.);
3326 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3327 array->alloc(nbNodes,1);
3328 double *valsToFill=array->getPointer();
3329 std::fill(valsToFill,valsToFill+nbNodes,0.);
3330 const double *values=tmp->getArray()->getConstPointer();
3331 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> da=DataArrayInt::New();
3332 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> daInd=DataArrayInt::New();
3333 getReverseNodalConnectivity(da,daInd);
3334 const int *daPtr=da->getConstPointer();
3335 const int *daIPtr=daInd->getConstPointer();
3336 for(int i=0;i<nbNodes;i++)
3337 for(const int *cell=daPtr+daIPtr[i];cell!=daPtr+daIPtr[i+1];cell++)
3338 valsToFill[i]+=cst*values[*cell];
3340 ret->setArray(array);
3345 * Returns a new MEDCouplingFieldDouble holding normal vectors to cells of \a this
3346 * mesh. The returned normal vectors to each cell have a norm2 equal to 1.
3347 * The computed vectors have <em> this->getMeshDimension()+1 </em> components
3348 * and are normalized.
3349 * <br> \a this can be either
3350 * - a 2D mesh in 2D or 3D space or
3351 * - an 1D mesh in 2D space.
3353 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3354 * cells and one time. The caller is to delete this field using decrRef() as
3355 * it is no more needed.
3356 * \throw If the nodal connectivity of cells is not defined.
3357 * \throw If the coordinates array is not set.
3358 * \throw If the mesh dimension is not set.
3359 * \throw If the mesh and space dimension is not as specified above.
3361 MEDCouplingFieldDouble *MEDCouplingUMesh::buildOrthogonalField() const
3363 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3364 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3365 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3366 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3367 int nbOfCells=getNumberOfCells();
3368 int nbComp=getMeshDimension()+1;
3369 array->alloc(nbOfCells,nbComp);
3370 double *vals=array->getPointer();
3371 const int *connI=_nodal_connec_index->getConstPointer();
3372 const int *conn=_nodal_connec->getConstPointer();
3373 const double *coords=_coords->getConstPointer();
3374 if(getMeshDimension()==2)
3376 if(getSpaceDimension()==3)
3378 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getBarycenterAndOwner();
3379 const double *locPtr=loc->getConstPointer();
3380 for(int i=0;i<nbOfCells;i++,vals+=3)
3382 int offset=connI[i];
3383 INTERP_KERNEL::crossprod<3>(locPtr+3*i,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3384 double n=INTERP_KERNEL::norm<3>(vals);
3385 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3390 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> isAbs=getMeasureField(false);
3391 const double *isAbsPtr=isAbs->getArray()->begin();
3392 for(int i=0;i<nbOfCells;i++,isAbsPtr++)
3393 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=*isAbsPtr>0.?1.:-1.; }
3396 else//meshdimension==1
3399 for(int i=0;i<nbOfCells;i++)
3401 int offset=connI[i];
3402 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3403 double n=INTERP_KERNEL::norm<2>(tmp);
3404 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3409 ret->setArray(array);
3411 ret->synchronizeTimeWithSupport();
3416 * Returns a new MEDCouplingFieldDouble holding normal vectors to specified cells of
3417 * \a this mesh. The computed vectors have <em> this->getMeshDimension()+1 </em> components
3418 * and are normalized.
3419 * <br> \a this can be either
3420 * - a 2D mesh in 2D or 3D space or
3421 * - an 1D mesh in 2D space.
3423 * This method avoids building explicitly a part of \a this mesh to perform the work.
3424 * \param [in] begin - an array of cell ids of interest.
3425 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
3426 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3427 * cells and one time. The caller is to delete this field using decrRef() as
3428 * it is no more needed.
3429 * \throw If the nodal connectivity of cells is not defined.
3430 * \throw If the coordinates array is not set.
3431 * \throw If the mesh dimension is not set.
3432 * \throw If the mesh and space dimension is not as specified above.
3433 * \sa buildOrthogonalField()
3435 * \ref cpp_mcumesh_buildPartOrthogonalField "Here is a C++ example".<br>
3436 * \ref py_mcumesh_buildPartOrthogonalField "Here is a Python example".
3438 MEDCouplingFieldDouble *MEDCouplingUMesh::buildPartOrthogonalField(const int *begin, const int *end) const
3440 if((getMeshDimension()!=2) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
3441 throw INTERP_KERNEL::Exception("Expected a umesh with ( meshDim == 2 spaceDim == 2 or 3 ) or ( meshDim == 1 spaceDim == 2 ) !");
3442 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3443 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3444 std::size_t nbelems=std::distance(begin,end);
3445 int nbComp=getMeshDimension()+1;
3446 array->alloc((int)nbelems,nbComp);
3447 double *vals=array->getPointer();
3448 const int *connI=_nodal_connec_index->getConstPointer();
3449 const int *conn=_nodal_connec->getConstPointer();
3450 const double *coords=_coords->getConstPointer();
3451 if(getMeshDimension()==2)
3453 if(getSpaceDimension()==3)
3455 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> loc=getPartBarycenterAndOwner(begin,end);
3456 const double *locPtr=loc->getConstPointer();
3457 for(const int *i=begin;i!=end;i++,vals+=3,locPtr+=3)
3459 int offset=connI[*i];
3460 INTERP_KERNEL::crossprod<3>(locPtr,coords+3*conn[offset+1],coords+3*conn[offset+2],vals);
3461 double n=INTERP_KERNEL::norm<3>(vals);
3462 std::transform(vals,vals+3,vals,std::bind2nd(std::multiplies<double>(),1./n));
3467 for(std::size_t i=0;i<nbelems;i++)
3468 { vals[3*i]=0.; vals[3*i+1]=0.; vals[3*i+2]=1.; }
3471 else//meshdimension==1
3474 for(const int *i=begin;i!=end;i++)
3476 int offset=connI[*i];
3477 std::transform(coords+2*conn[offset+2],coords+2*conn[offset+2]+2,coords+2*conn[offset+1],tmp,std::minus<double>());
3478 double n=INTERP_KERNEL::norm<2>(tmp);
3479 std::transform(tmp,tmp+2,tmp,std::bind2nd(std::multiplies<double>(),1./n));
3484 ret->setArray(array);
3486 ret->synchronizeTimeWithSupport();
3491 * Returns a new MEDCouplingFieldDouble holding a direction vector for each SEG2 in \a
3492 * this 1D mesh. The computed vectors have <em> this->getSpaceDimension() </em> components
3493 * and are \b not normalized.
3494 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
3495 * cells and one time. The caller is to delete this field using decrRef() as
3496 * it is no more needed.
3497 * \throw If the nodal connectivity of cells is not defined.
3498 * \throw If the coordinates array is not set.
3499 * \throw If \a this->getMeshDimension() != 1.
3500 * \throw If \a this mesh includes cells of type other than SEG2.
3502 MEDCouplingFieldDouble *MEDCouplingUMesh::buildDirectionVectorField() const
3504 if(getMeshDimension()!=1)
3505 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for buildDirectionVectorField !");
3506 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3507 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for buildDirectionVectorField !");
3508 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
3509 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> array=DataArrayDouble::New();
3510 int nbOfCells=getNumberOfCells();
3511 int spaceDim=getSpaceDimension();
3512 array->alloc(nbOfCells,spaceDim);
3513 double *pt=array->getPointer();
3514 const double *coo=getCoords()->getConstPointer();
3515 std::vector<int> conn;
3517 for(int i=0;i<nbOfCells;i++)
3520 getNodeIdsOfCell(i,conn);
3521 pt=std::transform(coo+conn[1]*spaceDim,coo+(conn[1]+1)*spaceDim,coo+conn[0]*spaceDim,pt,std::minus<double>());
3523 ret->setArray(array);
3525 ret->synchronizeTimeWithSupport();
3530 * Creates a 2D mesh by cutting \a this 3D mesh with a plane. In addition to the mesh,
3531 * returns a new DataArrayInt, of length equal to the number of 2D cells in the result
3532 * mesh, holding, for each cell in the result mesh, an id of a 3D cell it comes
3533 * from. If a result face is shared by two 3D cells, then the face in included twice in
3535 * \param [in] origin - 3 components of a point defining location of the plane.
3536 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3537 * must be greater than 1e-6.
3538 * \param [in] eps - half-thickness of the plane.
3539 * \param [out] cellIds - a new instance of DataArrayInt holding ids of 3D cells
3540 * producing correspondent 2D cells. The caller is to delete this array
3541 * using decrRef() as it is no more needed.
3542 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This mesh does
3543 * not share the node coordinates array with \a this mesh. The caller is to
3544 * delete this mesh using decrRef() as it is no more needed.
3545 * \throw If the coordinates array is not set.
3546 * \throw If the nodal connectivity of cells is not defined.
3547 * \throw If \a this->getMeshDimension() != 3 or \a this->getSpaceDimension() != 3.
3548 * \throw If magnitude of \a vec is less than 1e-6.
3549 * \throw If the plane does not intersect any 3D cell of \a this mesh.
3550 * \throw If \a this includes quadratic cells.
3552 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3D(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3554 checkFullyDefined();
3555 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
3556 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
3557 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3558 if(candidates->empty())
3559 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane considering bounding boxes !");
3560 std::vector<int> nodes;
3561 DataArrayInt *cellIds1D=0;
3562 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3563 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3564 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New(),desc2=DataArrayInt::New();
3565 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New(),descIndx2=DataArrayInt::New();
3566 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New(),revDesc2=DataArrayInt::New();
3567 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New(),revDescIndx2=DataArrayInt::New();
3568 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc2=subMesh->buildDescendingConnectivity(desc2,descIndx2,revDesc2,revDescIndx2);//meshDim==2 spaceDim==3
3569 revDesc2=0; revDescIndx2=0;
3570 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=mDesc2->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3571 revDesc1=0; revDescIndx1=0;
3572 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3573 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3575 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3576 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3578 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3579 std::vector< std::pair<int,int> > cut3DSurf(mDesc2->getNumberOfCells());
3580 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,mDesc2->getNodalConnectivity()->getConstPointer(),mDesc2->getNodalConnectivityIndex()->getConstPointer(),
3581 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3582 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3583 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New());
3584 connI->pushBackSilent(0); conn->alloc(0,1); cellIds2->alloc(0,1);
3585 subMesh->assemblyForSplitFrom3DSurf(cut3DSurf,desc2->getConstPointer(),descIndx2->getConstPointer(),conn,connI,cellIds2);
3586 if(cellIds2->empty())
3587 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D : No 3D cells in this intercepts the specified plane !");
3588 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3D",2);
3589 ret->setCoords(mDesc1->getCoords());
3590 ret->setConnectivity(conn,connI,true);
3591 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3596 * Creates an 1D mesh by cutting \a this 2D mesh in 3D space with a plane. In
3597 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
3598 from. If a result segment is shared by two 2D cells, then the segment in included twice in
3600 * \param [in] origin - 3 components of a point defining location of the plane.
3601 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3602 * must be greater than 1e-6.
3603 * \param [in] eps - half-thickness of the plane.
3604 * \param [out] cellIds - a new instance of DataArrayInt holding ids of faces
3605 * producing correspondent segments. The caller is to delete this array
3606 * using decrRef() as it is no more needed.
3607 * \return MEDCouplingUMesh * - a new instance of MEDCouplingUMesh. This is an 1D
3608 * mesh in 3D space. This mesh does not share the node coordinates array with
3609 * \a this mesh. The caller is to delete this mesh using decrRef() as it is
3611 * \throw If the coordinates array is not set.
3612 * \throw If the nodal connectivity of cells is not defined.
3613 * \throw If \a this->getMeshDimension() != 2 or \a this->getSpaceDimension() != 3.
3614 * \throw If magnitude of \a vec is less than 1e-6.
3615 * \throw If the plane does not intersect any 2D cell of \a this mesh.
3616 * \throw If \a this includes quadratic cells.
3618 MEDCouplingUMesh *MEDCouplingUMesh::buildSlice3DSurf(const double *origin, const double *vec, double eps, DataArrayInt *&cellIds) const throw(INTERP_KERNEL::Exception)
3620 checkFullyDefined();
3621 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
3622 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf works on umeshes with meshdim equal to 2 and spaceDim equal to 3 !");
3623 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> candidates=getCellIdsCrossingPlane(origin,vec,eps);
3624 if(candidates->empty())
3625 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3D surf cells in this intercepts the specified plane considering bounding boxes !");
3626 std::vector<int> nodes;
3627 DataArrayInt *cellIds1D=0;
3628 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> subMesh=static_cast<MEDCouplingUMesh*>(buildPartOfMySelf(candidates->begin(),candidates->end(),false));
3629 subMesh->findNodesOnPlane(origin,vec,eps,nodes);
3630 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
3631 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
3632 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
3633 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
3634 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc1=subMesh->buildDescendingConnectivity(desc1,descIndx1,revDesc1,revDescIndx1);//meshDim==1 spaceDim==3
3635 mDesc1->fillCellIdsToKeepFromNodeIds(&nodes[0],&nodes[0]+nodes.size(),true,cellIds1D);
3636 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds1DTmp(cellIds1D);
3638 std::vector<int> cut3DCurve(mDesc1->getNumberOfCells(),-2);
3639 for(const int *it=cellIds1D->begin();it!=cellIds1D->end();it++)
3641 mDesc1->split3DCurveWithPlane(origin,vec,eps,cut3DCurve);
3642 int ncellsSub=subMesh->getNumberOfCells();
3643 std::vector< std::pair<int,int> > cut3DSurf(ncellsSub);
3644 AssemblyForSplitFrom3DCurve(cut3DCurve,nodes,subMesh->getNodalConnectivity()->getConstPointer(),subMesh->getNodalConnectivityIndex()->getConstPointer(),
3645 mDesc1->getNodalConnectivity()->getConstPointer(),mDesc1->getNodalConnectivityIndex()->getConstPointer(),
3646 desc1->getConstPointer(),descIndx1->getConstPointer(),cut3DSurf);
3647 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn(DataArrayInt::New()),connI(DataArrayInt::New()),cellIds2(DataArrayInt::New()); connI->pushBackSilent(0);
3649 const int *nodal=subMesh->getNodalConnectivity()->getConstPointer();
3650 const int *nodalI=subMesh->getNodalConnectivityIndex()->getConstPointer();
3651 for(int i=0;i<ncellsSub;i++)
3653 if(cut3DSurf[i].first!=-1 && cut3DSurf[i].second!=-1)
3655 if(cut3DSurf[i].first!=-2)
3657 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(cut3DSurf[i].first); conn->pushBackSilent(cut3DSurf[i].second);
3658 connI->pushBackSilent(conn->getNumberOfTuples());
3659 cellIds2->pushBackSilent(i);
3663 int cellId3DSurf=cut3DSurf[i].second;
3664 int offset=nodalI[cellId3DSurf]+1;
3665 int nbOfEdges=nodalI[cellId3DSurf+1]-offset;
3666 for(int j=0;j<nbOfEdges;j++)
3668 conn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG2); conn->pushBackSilent(nodal[offset+j]); conn->pushBackSilent(nodal[offset+(j+1)%nbOfEdges]);
3669 connI->pushBackSilent(conn->getNumberOfTuples());
3670 cellIds2->pushBackSilent(cellId3DSurf);
3675 if(cellIds2->empty())
3676 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3DSurf : No 3DSurf cells in this intercepts the specified plane !");
3677 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Slice3DSurf",1);
3678 ret->setCoords(mDesc1->getCoords());
3679 ret->setConnectivity(conn,connI,true);
3680 cellIds=candidates->selectByTupleId(cellIds2->begin(),cellIds2->end());
3685 * Finds cells whose bounding boxes intersect a given plane.
3686 * \param [in] origin - 3 components of a point defining location of the plane.
3687 * \param [in] vec - 3 components of a vector normal to the plane. Vector magnitude
3688 * must be greater than 1e-6.
3689 * \param [in] eps - half-thickness of the plane.
3690 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of the found
3691 * cells. The caller is to delete this array using decrRef() as it is no more
3693 * \throw If the coordinates array is not set.
3694 * \throw If the nodal connectivity of cells is not defined.
3695 * \throw If \a this->getSpaceDimension() != 3.
3696 * \throw If magnitude of \a vec is less than 1e-6.
3697 * \sa buildSlice3D()
3699 DataArrayInt *MEDCouplingUMesh::getCellIdsCrossingPlane(const double *origin, const double *vec, double eps) const throw(INTERP_KERNEL::Exception)
3701 checkFullyDefined();
3702 if(getSpaceDimension()!=3)
3703 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSlice3D works on umeshes with spaceDim equal to 3 !");
3704 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
3706 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellIdsCrossingPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
3708 vec2[0]=vec[1]; vec2[1]=-vec[0]; vec2[2]=0.;//vec2 is the result of cross product of vec with (0,0,1)
3709 double angle=acos(vec[2]/normm);
3710 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cellIds;
3714 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->deepCpy();
3715 MEDCouplingPointSet::Rotate3DAlg(origin,vec2,angle,coo->getNumberOfTuples(),coo->getPointer());
3716 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mw=clone(false);//false -> shallow copy
3718 mw->getBoundingBox(bbox);
3719 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3720 cellIds=mw->getCellsInBoundingBox(bbox,eps);
3724 getBoundingBox(bbox);
3725 bbox[4]=origin[2]-eps; bbox[5]=origin[2]+eps;
3726 cellIds=getCellsInBoundingBox(bbox,eps);
3728 return cellIds.retn();
3732 * This method checks that \a this is a contiguous mesh. The user is expected to call this method on a mesh with meshdim==1.
3733 * If not an exception will thrown. If this is an empty mesh with no cell an exception will be thrown too.
3734 * No consideration of coordinate is done by this method.
3735 * 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)
3736 * If not false is returned. In case that false is returned a call to ParaMEDMEM::MEDCouplingUMesh::mergeNodes could be usefull.
3738 bool MEDCouplingUMesh::isContiguous1D() const throw(INTERP_KERNEL::Exception)
3740 if(getMeshDimension()!=1)
3741 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense only for 1D mesh !");
3742 int nbCells=getNumberOfCells();
3744 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::isContiguous1D : this method has a sense for non empty mesh !");
3745 const int *connI=_nodal_connec_index->getConstPointer();
3746 const int *conn=_nodal_connec->getConstPointer();
3747 int ref=conn[connI[0]+2];
3748 for(int i=1;i<nbCells;i++)
3750 if(conn[connI[i]+1]!=ref)
3752 ref=conn[connI[i]+2];
3758 * This method is only callable on mesh with meshdim == 1 containing only SEG2 and spaceDim==3.
3759 * This method projects this on the 3D line defined by (pt,v). This methods first checks that all SEG2 are along v vector.
3760 * \param pt reference point of the line
3761 * \param v normalized director vector of the line
3762 * \param eps max precision before throwing an exception
3763 * \param res output of size this->getNumberOfCells
3765 void MEDCouplingUMesh::project1D(const double *pt, const double *v, double eps, double *res) const
3767 if(getMeshDimension()!=1)
3768 throw INTERP_KERNEL::Exception("Expected a umesh with meshDim == 1 for project1D !");
3769 if(_types.size()!=1 || *(_types.begin())!=INTERP_KERNEL::NORM_SEG2)
3770 throw INTERP_KERNEL::Exception("Expected a umesh with only NORM_SEG2 type of elements for project1D !");
3771 if(getSpaceDimension()!=3)
3772 throw INTERP_KERNEL::Exception("Expected a umesh with spaceDim==3 for project1D !");
3773 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> f=buildDirectionVectorField();
3774 const double *fPtr=f->getArray()->getConstPointer();
3776 for(int i=0;i<getNumberOfCells();i++)
3778 const double *tmp1=fPtr+3*i;
3779 tmp[0]=tmp1[1]*v[2]-tmp1[2]*v[1];
3780 tmp[1]=tmp1[2]*v[0]-tmp1[0]*v[2];
3781 tmp[2]=tmp1[0]*v[1]-tmp1[1]*v[0];
3782 double n1=INTERP_KERNEL::norm<3>(tmp);
3783 n1/=INTERP_KERNEL::norm<3>(tmp1);
3785 throw INTERP_KERNEL::Exception("UMesh::Projection 1D failed !");
3787 const double *coo=getCoords()->getConstPointer();
3788 for(int i=0;i<getNumberOfNodes();i++)
3790 std::transform(coo+i*3,coo+i*3+3,pt,tmp,std::minus<double>());
3791 std::transform(tmp,tmp+3,v,tmp,std::multiplies<double>());
3792 res[i]=std::accumulate(tmp,tmp+3,0.);
3797 * 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.
3798 * \a this is expected to be a mesh so that its space dimension is equal to its
3799 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3800 * 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).
3802 * 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
3803 * 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).
3804 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3806 * So this method is more accurate (so, more costly) than simply searching for the closest point in \a this.
3807 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3809 * \param [in] ptBg the start pointer (included) of the coordinates of the point
3810 * \param [in] ptEnd the end pointer (not included) of the coordinates of the point
3811 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3812 * \return the positive value of the distance.
3813 * \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
3815 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoints
3817 double MEDCouplingUMesh::distanceToPoint(const double *ptBg, const double *ptEnd, int& cellId) const throw(INTERP_KERNEL::Exception)
3819 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3820 if(meshDim!=spaceDim-1)
3821 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint works only for spaceDim=meshDim+1 !");
3822 if(meshDim!=2 && meshDim!=1)
3823 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint : only mesh dimension 2 and 1 are implemented !");
3824 checkFullyDefined();
3825 if((int)std::distance(ptBg,ptEnd)!=spaceDim)
3826 { 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()); }
3827 DataArrayInt *ret1=0;
3828 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=DataArrayDouble::New(); pts->useArray(ptBg,false,C_DEALLOC,1,spaceDim);
3829 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=distanceToPoints(pts,ret1);
3830 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1Safe(ret1);
3831 cellId=*ret1Safe->begin();
3832 return *ret0->begin();
3836 * This method computes the distance from each point of points serie \a pts (stored in a DataArrayDouble in which each tuple represents a point)
3837 * to \a this and the first \a cellId in \a this corresponding to the returned distance.
3838 * 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
3839 * 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).
3840 * A user that needs to consider orphan nodes should invoke DataArrayDouble::minimalDistanceTo method on the coordinates array of \a this.
3842 * \a this is expected to be a mesh so that its space dimension is equal to its
3843 * mesh dimension + 1. Furthermore only mesh dimension 1 and 2 are supported for the moment.
3844 * 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).
3846 * So this method is more accurate (so, more costly) than simply searching for each point in \a pts the closest point in \a this.
3847 * If only this information is enough for you simply call \c getCoords()->distanceToTuple on \a this.
3849 * \param [in] pts the list of points in which each tuple represents a point
3850 * \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.
3851 * \return a newly allocated object to be dealed by the caller that tells for each point in \a pts the distance to \a this.
3852 * \throw if number of components of \a pts is not equal to the space dimension.
3853 * \throw if mesh dimension of \a this is not equal to space dimension - 1.
3854 * \sa DataArrayDouble::distanceToTuple, MEDCouplingUMesh::distanceToPoint
3856 DataArrayDouble *MEDCouplingUMesh::distanceToPoints(const DataArrayDouble *pts, DataArrayInt *& cellIds) const throw(INTERP_KERNEL::Exception)
3859 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : input points pointer is NULL !");
3860 pts->checkAllocated();
3861 int meshDim=getMeshDimension(),spaceDim=getSpaceDimension();
3862 if(meshDim!=spaceDim-1)
3863 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints works only for spaceDim=meshDim+1 !");
3864 if(meshDim!=2 && meshDim!=1)
3865 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only mesh dimension 2 and 1 are implemented !");
3866 if(pts->getNumberOfComponents()!=spaceDim)
3868 std::ostringstream oss; oss << "MEDCouplingUMesh::distanceToPoints : input pts DataArrayDouble has " << pts->getNumberOfComponents() << " components whereas it should be equal to " << spaceDim << " (mesh spaceDimension) !";
3869 throw INTERP_KERNEL::Exception(oss.str().c_str());
3871 checkFullyDefined();
3872 int nbCells=getNumberOfCells();
3874 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : no cells in this !");
3875 int nbOfPts=pts->getNumberOfTuples();
3876 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret0=DataArrayDouble::New(); ret0->alloc(nbOfPts,1);
3877 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1=DataArrayInt::New(); ret1->alloc(nbOfPts,1);
3878 const int *nc=_nodal_connec->begin(),*ncI=_nodal_connec_index->begin(); const double *coords=_coords->begin();
3879 double *ret0Ptr=ret0->getPointer(); int *ret1Ptr=ret1->getPointer(); const double *ptsPtr=pts->begin();
3880 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
3881 const double *bbox(bboxArr->begin());
3886 BBTreeDst<3> myTree(bbox,0,0,nbCells);
3887 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=3)
3889 double x=std::numeric_limits<double>::max();
3890 std::vector<int> elems;
3891 myTree.getMinDistanceOfMax(ptsPtr,x);
3892 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3893 DistanceToPoint3DSurfAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3899 BBTreeDst<2> myTree(bbox,0,0,nbCells);
3900 for(int i=0;i<nbOfPts;i++,ret0Ptr++,ret1Ptr++,ptsPtr+=2)
3902 double x=std::numeric_limits<double>::max();
3903 std::vector<int> elems;
3904 myTree.getMinDistanceOfMax(ptsPtr,x);
3905 myTree.getElemsWhoseMinDistanceToPtSmallerThan(ptsPtr,x,elems);
3906 DistanceToPoint2DCurveAlg(ptsPtr,&elems[0],&elems[0]+elems.size(),coords,nc,ncI,*ret0Ptr,*ret1Ptr);
3911 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoints : only spacedim 2 and 3 supported !");
3913 cellIds=ret1.retn();
3918 * \param [in] pt the start pointer (included) of the coordinates of the point
3919 * \param [in] cellIdsBg the start pointer (included) of cellIds
3920 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3921 * \param [in] nc nodal connectivity
3922 * \param [in] ncI nodal connectivity index
3923 * \param [in,out] ret0 the min distance between \a this and the external input point
3924 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3925 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3927 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)
3930 ret0=std::numeric_limits<double>::max();
3931 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3933 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3935 case INTERP_KERNEL::NORM_TRI3:
3937 double tmp=INTERP_KERNEL::DistanceFromPtToTriInSpaceDim3(pt,coords+3*nc[ncI[*zeCell]+1],coords+3*nc[ncI[*zeCell]+2],coords+3*nc[ncI[*zeCell]+3]);
3939 { ret0=tmp; cellId=*zeCell; }
3942 case INTERP_KERNEL::NORM_QUAD4:
3943 case INTERP_KERNEL::NORM_POLYGON:
3945 double tmp=INTERP_KERNEL::DistanceFromPtToPolygonInSpaceDim3(pt,nc+ncI[*zeCell]+1,nc+ncI[*zeCell+1],coords);
3947 { ret0=tmp; cellId=*zeCell; }
3951 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint3DSurfAlg : not managed cell type ! Supporting TRI3, QUAD4 and POLYGON !");
3957 * \param [in] pt the start pointer (included) of the coordinates of the point
3958 * \param [in] cellIdsBg the start pointer (included) of cellIds
3959 * \param [in] cellIdsEnd the end pointer (excluded) of cellIds
3960 * \param [in] nc nodal connectivity
3961 * \param [in] ncI nodal connectivity index
3962 * \param [in,out] ret0 the min distance between \a this and the external input point
3963 * \param [out] cellId that corresponds to minimal distance. If the closer node is not linked to any cell in \a this -1 is returned.
3964 * \sa MEDCouplingUMesh::distanceToPoint, MEDCouplingUMesh::distanceToPoints
3966 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)
3969 ret0=std::numeric_limits<double>::max();
3970 for(const int *zeCell=cellIdsBg;zeCell!=cellIdsEnd;zeCell++)
3972 switch((INTERP_KERNEL::NormalizedCellType)nc[ncI[*zeCell]])
3974 case INTERP_KERNEL::NORM_SEG2:
3976 std::size_t uselessEntry=0;
3977 double tmp=INTERP_KERNEL::SquareDistanceFromPtToSegInSpaceDim2(pt,coords+2*nc[ncI[*zeCell]+1],coords+2*nc[ncI[*zeCell]+2],uselessEntry);
3980 { ret0=tmp; cellId=*zeCell; }
3984 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::distanceToPoint2DCurveAlg : not managed cell type ! Supporting SEG2 !");
3990 * Finds cells in contact with a ball (i.e. a point with precision).
3991 * \warning This method is suitable if the caller intends to evaluate only one
3992 * point, for more points getCellsContainingPoints() is recommended as it is
3994 * \param [in] pos - array of coordinates of the ball central point.
3995 * \param [in] eps - ball radius.
3996 * \return int - a smallest id of cells being in contact with the ball, -1 in case
3997 * if there are no such cells.
3998 * \throw If the coordinates array is not set.
3999 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4001 int MEDCouplingUMesh::getCellContainingPoint(const double *pos, double eps) const
4003 std::vector<int> elts;
4004 getCellsContainingPoint(pos,eps,elts);
4007 return elts.front();
4011 * Finds cells in contact with a ball (i.e. a point with precision).
4012 * \warning This method is suitable if the caller intends to evaluate only one
4013 * point, for more points getCellsContainingPoints() is recommended as it is
4015 * \param [in] pos - array of coordinates of the ball central point.
4016 * \param [in] eps - ball radius.
4017 * \param [in,out] elts - vector returning ids of the found cells. It is cleared
4018 * before inserting ids.
4019 * \throw If the coordinates array is not set.
4020 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4022 * \ref cpp_mcumesh_getCellsContainingPoint "Here is a C++ example".<br>
4023 * \ref py_mcumesh_getCellsContainingPoint "Here is a Python example".
4025 void MEDCouplingUMesh::getCellsContainingPoint(const double *pos, double eps, std::vector<int>& elts) const
4027 std::vector<int> eltsIndex;
4028 getCellsContainingPoints(pos,1,eps,elts,eltsIndex);
4033 namespace ParaMEDMEM
4035 template<const int SPACEDIMM>
4039 static const int MY_SPACEDIM=SPACEDIMM;
4040 static const int MY_MESHDIM=8;
4041 typedef int MyConnType;
4042 static const INTERP_KERNEL::NumberingPolicy My_numPol=INTERP_KERNEL::ALL_C_MODE;
4044 // useless, but for windows compilation ...
4045 const double* getCoordinatesPtr() const { return 0; }
4046 const int* getConnectivityPtr() const { return 0; }
4047 const int* getConnectivityIndexPtr() const { return 0; }
4048 INTERP_KERNEL::NormalizedCellType getTypeOfElement(int) const { return (INTERP_KERNEL::NormalizedCellType)0; }
4052 INTERP_KERNEL::Edge *MEDCouplingUMeshBuildQPFromEdge(INTERP_KERNEL::NormalizedCellType typ, std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >& mapp2, const int *bg)
4054 INTERP_KERNEL::Edge *ret=0;
4057 case INTERP_KERNEL::NORM_SEG2:
4059 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4062 case INTERP_KERNEL::NORM_SEG3:
4064 INTERP_KERNEL::EdgeLin *e1=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[2]].first);
4065 INTERP_KERNEL::EdgeLin *e2=new INTERP_KERNEL::EdgeLin(mapp2[bg[2]].first,mapp2[bg[1]].first);
4066 INTERP_KERNEL::SegSegIntersector inters(*e1,*e2);
4067 bool colinearity=inters.areColinears();
4068 delete e1; delete e2;
4070 ret=new INTERP_KERNEL::EdgeLin(mapp2[bg[0]].first,mapp2[bg[1]].first);
4072 ret=new INTERP_KERNEL::EdgeArcCircle(mapp2[bg[0]].first,mapp2[bg[2]].first,mapp2[bg[1]].first);
4073 mapp2[bg[2]].second=false;
4077 throw INTERP_KERNEL::Exception("MEDCouplingUMeshBuildQPFromEdge : Expecting a mesh with spaceDim==2 and meshDim==1 !");
4083 * 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'.
4084 * The input meth 'mDesc' must be so that mDim==1 et spaceDim==3.
4085 * 'mapp' contains a mapping between local numbering in submesh and the global node numbering in 'mDesc'.
4087 INTERP_KERNEL::QuadraticPolygon *MEDCouplingUMeshBuildQPFromMesh(const MEDCouplingUMesh *mDesc, const std::vector<int>& candidates, std::map<INTERP_KERNEL::Node *,int>& mapp) throw(INTERP_KERNEL::Exception)
4090 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.
4091 const double *coo=mDesc->getCoords()->getConstPointer();
4092 const int *c=mDesc->getNodalConnectivity()->getConstPointer();
4093 const int *cI=mDesc->getNodalConnectivityIndex()->getConstPointer();
4095 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4096 s.insert(c+cI[*it]+1,c+cI[(*it)+1]);
4097 for(std::set<int>::const_iterator it2=s.begin();it2!=s.end();it2++)
4099 INTERP_KERNEL::Node *n=new INTERP_KERNEL::Node(coo[2*(*it2)],coo[2*(*it2)+1]);
4100 mapp2[*it2]=std::pair<INTERP_KERNEL::Node *,bool>(n,true);
4102 INTERP_KERNEL::QuadraticPolygon *ret=new INTERP_KERNEL::QuadraticPolygon;
4103 for(std::vector<int>::const_iterator it=candidates.begin();it!=candidates.end();it++)
4105 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[*it]];
4106 ret->pushBack(MEDCouplingUMeshBuildQPFromEdge(typ,mapp2,c+cI[*it]+1));
4108 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it2=mapp2.begin();it2!=mapp2.end();it2++)
4110 if((*it2).second.second)
4111 mapp[(*it2).second.first]=(*it2).first;
4112 ((*it2).second.first)->decrRef();
4117 INTERP_KERNEL::Node *MEDCouplingUMeshBuildQPNode(int nodeId, const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo)
4121 int locId=nodeId-offset2;
4122 return new INTERP_KERNEL::Node(addCoo[2*locId],addCoo[2*locId+1]);
4126 int locId=nodeId-offset1;
4127 return new INTERP_KERNEL::Node(coo2[2*locId],coo2[2*locId+1]);
4129 return new INTERP_KERNEL::Node(coo1[2*nodeId],coo1[2*nodeId+1]);
4132 void MEDCouplingUMeshBuildQPFromMesh3(const double *coo1, int offset1, const double *coo2, int offset2, const std::vector<double>& addCoo,
4133 const int *desc1Bg, const int *desc1End, const std::vector<std::vector<int> >& intesctEdges1,
4134 /*output*/std::map<INTERP_KERNEL::Node *,int>& mapp, std::map<int,INTERP_KERNEL::Node *>& mappRev)
4136 for(const int *desc1=desc1Bg;desc1!=desc1End;desc1++)
4138 int eltId1=abs(*desc1)-1;
4139 for(std::vector<int>::const_iterator it1=intesctEdges1[eltId1].begin();it1!=intesctEdges1[eltId1].end();it1++)
4141 std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.find(*it1);
4142 if(it==mappRev.end())
4144 INTERP_KERNEL::Node *node=MEDCouplingUMeshBuildQPNode(*it1,coo1,offset1,coo2,offset2,addCoo);
4155 template<int SPACEDIM>
4156 void MEDCouplingUMesh::getCellsContainingPointsAlg(const double *coords, const double *pos, int nbOfPoints,
4157 double eps, std::vector<int>& elts, std::vector<int>& eltsIndex) const
4159 eltsIndex.resize(nbOfPoints+1);
4162 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bboxArr(getBoundingBoxForBBTree());
4163 const double *bbox(bboxArr->begin());
4164 int nbOfCells=getNumberOfCells();
4165 const int *conn=_nodal_connec->getConstPointer();
4166 const int *connI=_nodal_connec_index->getConstPointer();
4167 double bb[2*SPACEDIM];
4168 BBTree<SPACEDIM,int> myTree(&bbox[0],0,0,nbOfCells,-eps);
4169 for(int i=0;i<nbOfPoints;i++)
4171 eltsIndex[i+1]=eltsIndex[i];
4172 for(int j=0;j<SPACEDIM;j++)
4174 bb[2*j]=pos[SPACEDIM*i+j];
4175 bb[2*j+1]=pos[SPACEDIM*i+j];
4177 std::vector<int> candidates;
4178 myTree.getIntersectingElems(bb,candidates);
4179 for(std::vector<int>::const_iterator iter=candidates.begin();iter!=candidates.end();iter++)
4181 int sz=connI[(*iter)+1]-connI[*iter]-1;
4182 if(INTERP_KERNEL::PointLocatorAlgos<DummyClsMCUG<SPACEDIM> >::isElementContainsPoint(pos+i*SPACEDIM,
4183 (INTERP_KERNEL::NormalizedCellType)conn[connI[*iter]],
4184 coords,conn+connI[*iter]+1,sz,eps))
4187 elts.push_back(*iter);
4193 * Finds cells in contact with several balls (i.e. points with precision).
4194 * This method is an extension of getCellContainingPoint() and
4195 * getCellsContainingPoint() for the case of multiple points.
4196 * \param [in] pos - an array of coordinates of points in full interlace mode :
4197 * X0,Y0,Z0,X1,Y1,Z1,... Size of the array must be \a
4198 * this->getSpaceDimension() * \a nbOfPoints
4199 * \param [in] nbOfPoints - number of points to locate within \a this mesh.
4200 * \param [in] eps - radius of balls (i.e. the precision).
4201 * \param [in,out] elts - vector returning ids of found cells.
4202 * \param [in,out] eltsIndex - an array, of length \a nbOfPoints + 1,
4203 * dividing cell ids in \a elts into groups each referring to one
4204 * point. Its every element (except the last one) is an index pointing to the
4205 * first id of a group of cells. For example cells in contact with the *i*-th
4206 * point are described by following range of indices:
4207 * [ \a eltsIndex[ *i* ], \a eltsIndex[ *i*+1 ] ) and the cell ids are
4208 * \a elts[ \a eltsIndex[ *i* ]], \a elts[ \a eltsIndex[ *i* ] + 1 ], ...
4209 * Number of cells in contact with the *i*-th point is
4210 * \a eltsIndex[ *i*+1 ] - \a eltsIndex[ *i* ].
4211 * \throw If the coordinates array is not set.
4212 * \throw If \a this->getMeshDimension() != \a this->getSpaceDimension().
4214 * \ref cpp_mcumesh_getCellsContainingPoints "Here is a C++ example".<br>
4215 * \ref py_mcumesh_getCellsContainingPoints "Here is a Python example".
4217 void MEDCouplingUMesh::getCellsContainingPoints(const double *pos, int nbOfPoints, double eps,
4218 std::vector<int>& elts, std::vector<int>& eltsIndex) const
4220 int spaceDim=getSpaceDimension();
4221 int mDim=getMeshDimension();
4226 const double *coords=_coords->getConstPointer();
4227 getCellsContainingPointsAlg<3>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4234 throw INTERP_KERNEL::Exception("For spaceDim==3 only meshDim==3 implemented for getelementscontainingpoints !");
4236 else if(spaceDim==2)
4240 const double *coords=_coords->getConstPointer();
4241 getCellsContainingPointsAlg<2>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4244 throw INTERP_KERNEL::Exception("For spaceDim==2 only meshDim==2 implemented for getelementscontainingpoints !");
4246 else if(spaceDim==1)
4250 const double *coords=_coords->getConstPointer();
4251 getCellsContainingPointsAlg<1>(coords,pos,nbOfPoints,eps,elts,eltsIndex);
4254 throw INTERP_KERNEL::Exception("For spaceDim==1 only meshDim==1 implemented for getelementscontainingpoints !");
4257 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getCellsContainingPoints : not managed for mdim not in [1,2,3] !");
4261 * Finds butterfly cells in \a this mesh. A 2D cell is considered to be butterfly if at
4262 * least two its edges intersect each other anywhere except their extremities. An
4263 * INTERP_KERNEL::NORM_NORI3 cell can \b not be butterfly.
4264 * \param [in,out] cells - a vector returning ids of the found cells. It is not
4265 * cleared before filling in.
4266 * \param [in] eps - precision.
4267 * \throw If \a this->getMeshDimension() != 2.
4268 * \throw If \a this->getSpaceDimension() != 2 && \a this->getSpaceDimension() != 3.
4270 void MEDCouplingUMesh::checkButterflyCells(std::vector<int>& cells, double eps) const
4272 const char msg[]="Butterfly detection work only for 2D cells with spaceDim==2 or 3!";
4273 if(getMeshDimension()!=2)
4274 throw INTERP_KERNEL::Exception(msg);
4275 int spaceDim=getSpaceDimension();
4276 if(spaceDim!=2 && spaceDim!=3)
4277 throw INTERP_KERNEL::Exception(msg);
4278 const int *conn=_nodal_connec->getConstPointer();
4279 const int *connI=_nodal_connec_index->getConstPointer();
4280 int nbOfCells=getNumberOfCells();
4281 std::vector<double> cell2DinS2;
4282 for(int i=0;i<nbOfCells;i++)
4284 int offset=connI[i];
4285 int nbOfNodesForCell=connI[i+1]-offset-1;
4286 if(nbOfNodesForCell<=3)
4288 bool isQuad=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[offset]).isQuadratic();
4289 project2DCellOnXY(conn+offset+1,conn+connI[i+1],cell2DinS2);
4290 if(isButterfly2DCell(cell2DinS2,isQuad,eps))
4297 * This method is typically requested to unbutterfly 2D linear cells in \b this.
4299 * 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.
4300 * 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.
4302 * For each 2D linear cell in \b this, this method builds the convex envelop (or the convex hull) of the current cell.
4303 * This convex envelop is computed using Jarvis march algorithm.
4304 * The coordinates and the number of cells of \b this remain unchanged on invocation of this method.
4305 * 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)
4306 * 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.
4308 * \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.
4310 DataArrayInt *MEDCouplingUMesh::convexEnvelop2D() throw(INTERP_KERNEL::Exception)
4312 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
4313 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convexEnvelop2D works only for meshDim=2 and spaceDim=2 !");
4314 checkFullyDefined();
4315 const double *coords=getCoords()->getConstPointer();
4316 int nbOfCells=getNumberOfCells();
4317 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecIndexOut=DataArrayInt::New();
4318 nodalConnecIndexOut->alloc(nbOfCells+1,1);
4319 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalConnecOut(DataArrayInt::New());
4320 int *workIndexOut=nodalConnecIndexOut->getPointer();
4322 const int *nodalConnecIn=_nodal_connec->getConstPointer();
4323 const int *nodalConnecIndexIn=_nodal_connec_index->getConstPointer();
4324 std::set<INTERP_KERNEL::NormalizedCellType> types;
4325 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> isChanged(DataArrayInt::New());
4326 isChanged->alloc(0,1);
4327 for(int i=0;i<nbOfCells;i++,workIndexOut++)
4329 int pos=nodalConnecOut->getNumberOfTuples();
4330 if(BuildConvexEnvelopOf2DCellJarvis(coords,nodalConnecIn+nodalConnecIndexIn[i],nodalConnecIn+nodalConnecIndexIn[i+1],nodalConnecOut))
4331 isChanged->pushBackSilent(i);
4332 types.insert((INTERP_KERNEL::NormalizedCellType)nodalConnecOut->getIJ(pos,0));
4333 workIndexOut[1]=nodalConnecOut->getNumberOfTuples();
4335 if(isChanged->empty())
4337 setConnectivity(nodalConnecOut,nodalConnecIndexOut,false);
4339 return isChanged.retn();
4343 * This method is \b NOT const because it can modify \a this.
4344 * \a this is expected to be an unstructured mesh with meshDim==2 and spaceDim==3. If not an exception will be thrown.
4345 * \param mesh1D is an unstructured mesh with MeshDim==1 and spaceDim==3. If not an exception will be thrown.
4346 * \param policy specifies the type of extrusion chosen. \b 0 for translation (most simple),
4347 * \b 1 for translation and rotation around point of 'mesh1D'.
4348 * \return an unstructured mesh with meshDim==3 and spaceDim==3. The returned mesh has the same coords than \a this.
4350 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMesh(const MEDCouplingUMesh *mesh1D, int policy)
4352 checkFullyDefined();
4353 mesh1D->checkFullyDefined();
4354 if(!mesh1D->isContiguous1D())
4355 throw INTERP_KERNEL::Exception("buildExtrudedMesh : 1D mesh passed in parameter is not contiguous !");
4356 if(getSpaceDimension()!=mesh1D->getSpaceDimension())
4357 throw INTERP_KERNEL::Exception("Invalid call to buildExtrudedMesh this and mesh1D must have same space dimension !");
4358 if((getMeshDimension()!=2 || getSpaceDimension()!=3) && (getMeshDimension()!=1 || getSpaceDimension()!=2))
4359 throw INTERP_KERNEL::Exception("Invalid 'this' for buildExtrudedMesh method : must be (meshDim==2 and spaceDim==3) or (meshDim==1 and spaceDim==2) !");
4360 if(mesh1D->getMeshDimension()!=1)
4361 throw INTERP_KERNEL::Exception("Invalid 'mesh1D' for buildExtrudedMesh method : must be meshDim==1 !");
4363 if(isPresenceOfQuadratic())
4365 if(mesh1D->isFullyQuadratic())
4368 throw INTERP_KERNEL::Exception("Invalid 2D mesh and 1D mesh because 2D mesh has quadratic cells and 1D is not fully quadratic !");
4371 int oldNbOfNodes=getNumberOfNodes();
4372 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords;
4377 newCoords=fillExtCoordsUsingTranslation(mesh1D,isQuad);
4382 newCoords=fillExtCoordsUsingTranslAndAutoRotation(mesh1D,isQuad);
4386 throw INTERP_KERNEL::Exception("Not implemented extrusion policy : must be in (0) !");
4388 setCoords(newCoords);
4389 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=buildExtrudedMeshFromThisLowLev(oldNbOfNodes,isQuad);
4395 * This method works on a 3D curve linear mesh that is to say (meshDim==1 and spaceDim==3).
4396 * If it is not the case an exception will be thrown.
4397 * This method is non const because the coordinate of \a this can be appended with some new points issued from
4398 * intersection of plane defined by ('origin','vec').
4399 * This method has one in/out parameter : 'cut3DCurve'.
4400 * Param 'cut3DCurve' is expected to be of size 'this->getNumberOfCells()'. For each i in [0,'this->getNumberOfCells()')
4401 * if cut3DCurve[i]==-2, it means that for cell #i in \a this nothing has been detected previously.
4402 * if cut3DCurve[i]==-1, it means that cell#i has been already detected to be fully part of plane defined by ('origin','vec').
4403 * This method will throw an exception if \a this contains a non linear segment.
4405 void MEDCouplingUMesh::split3DCurveWithPlane(const double *origin, const double *vec, double eps, std::vector<int>& cut3DCurve) throw(INTERP_KERNEL::Exception)
4407 checkFullyDefined();
4408 if(getMeshDimension()!=1 || getSpaceDimension()!=3)
4409 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane works on umeshes with meshdim equal to 1 and spaceDim equal to 3 !");
4410 int ncells=getNumberOfCells();
4411 int nnodes=getNumberOfNodes();
4412 double vec2[3],vec3[3],vec4[3];
4413 double normm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
4415 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : parameter 'vec' should have a norm2 greater than 1e-6 !");
4416 vec2[0]=vec[0]/normm; vec2[1]=vec[1]/normm; vec2[2]=vec[2]/normm;
4417 const int *conn=_nodal_connec->getConstPointer();
4418 const int *connI=_nodal_connec_index->getConstPointer();
4419 const double *coo=_coords->getConstPointer();
4420 std::vector<double> addCoo;
4421 for(int i=0;i<ncells;i++)
4423 if(conn[connI[i]]==(int)INTERP_KERNEL::NORM_SEG2)
4425 if(cut3DCurve[i]==-2)
4427 int st=conn[connI[i]+1],endd=conn[connI[i]+2];
4428 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];
4429 double normm2=sqrt(vec3[0]*vec3[0]+vec3[1]*vec3[1]+vec3[2]*vec3[2]);
4430 double colin=std::abs((vec3[0]*vec2[0]+vec3[1]*vec2[1]+vec3[2]*vec2[2])/normm2);
4431 if(colin>eps)//if colin<=eps -> current SEG2 is colinear to the input plane
4433 const double *st2=coo+3*st;
4434 vec4[0]=st2[0]-origin[0]; vec4[1]=st2[1]-origin[1]; vec4[2]=st2[2]-origin[2];
4435 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]));
4436 if(pos>eps && pos<1-eps)
4438 int nNode=((int)addCoo.size())/3;
4439 vec4[0]=st2[0]+pos*vec3[0]; vec4[1]=st2[1]+pos*vec3[1]; vec4[2]=st2[2]+pos*vec3[2];
4440 addCoo.insert(addCoo.end(),vec4,vec4+3);
4441 cut3DCurve[i]=nnodes+nNode;
4447 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::split3DCurveWithPlane : this method is only available for linear cell (NORM_SEG2) !");
4451 int newNbOfNodes=nnodes+((int)addCoo.size())/3;
4452 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo2=DataArrayDouble::New();
4453 coo2->alloc(newNbOfNodes,3);
4454 double *tmp=coo2->getPointer();
4455 tmp=std::copy(_coords->begin(),_coords->end(),tmp);
4456 std::copy(addCoo.begin(),addCoo.end(),tmp);
4457 DataArrayDouble::SetArrayIn(coo2,_coords);
4462 * This method incarnates the policy 0 for MEDCouplingUMesh::buildExtrudedMesh method.
4463 * \param mesh1D is the input 1D mesh used for translation computation.
4464 * \return newCoords new coords filled by this method.
4466 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslation(const MEDCouplingUMesh *mesh1D, bool isQuad) const
4468 int oldNbOfNodes=getNumberOfNodes();
4469 int nbOf1DCells=mesh1D->getNumberOfCells();
4470 int spaceDim=getSpaceDimension();
4471 DataArrayDouble *ret=DataArrayDouble::New();
4472 std::vector<bool> isQuads;
4473 int nbOfLevsInVec=isQuad?2*nbOf1DCells+1:nbOf1DCells+1;
4474 ret->alloc(oldNbOfNodes*nbOfLevsInVec,spaceDim);
4475 double *retPtr=ret->getPointer();
4476 const double *coords=getCoords()->getConstPointer();
4477 double *work=std::copy(coords,coords+spaceDim*oldNbOfNodes,retPtr);
4479 std::vector<double> c;
4483 for(int i=0;i<nbOf1DCells;i++)
4486 mesh1D->getNodeIdsOfCell(i,v);
4488 mesh1D->getCoordinatesOfNode(v[isQuad?2:1],c);
4489 mesh1D->getCoordinatesOfNode(v[0],c);
4490 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4491 for(int j=0;j<oldNbOfNodes;j++)
4492 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4496 mesh1D->getCoordinatesOfNode(v[1],c);
4497 mesh1D->getCoordinatesOfNode(v[0],c);
4498 std::transform(c.begin(),c.begin()+spaceDim,c.begin()+spaceDim,vec,std::minus<double>());
4499 for(int j=0;j<oldNbOfNodes;j++)
4500 work=std::transform(vec,vec+spaceDim,retPtr+spaceDim*(i*oldNbOfNodes+j),work,std::plus<double>());
4503 ret->copyStringInfoFrom(*getCoords());
4508 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4509 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4510 * \return newCoords new coords filled by this method.
4512 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4514 if(mesh1D->getSpaceDimension()==2)
4515 return fillExtCoordsUsingTranslAndAutoRotation2D(mesh1D,isQuad);
4516 if(mesh1D->getSpaceDimension()==3)
4517 return fillExtCoordsUsingTranslAndAutoRotation3D(mesh1D,isQuad);
4518 throw INTERP_KERNEL::Exception("Not implemented rotation and translation alg. for spacedim other than 2 and 3 !");
4522 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4523 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4524 * \return newCoords new coords filled by this method.
4526 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4529 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : not implemented for quadratic cells !");
4530 int oldNbOfNodes=getNumberOfNodes();
4531 int nbOf1DCells=mesh1D->getNumberOfCells();
4533 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation2D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4534 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4535 int nbOfLevsInVec=nbOf1DCells+1;
4536 ret->alloc(oldNbOfNodes*nbOfLevsInVec,2);
4537 double *retPtr=ret->getPointer();
4538 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4539 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4540 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4541 tmp->setCoords(tmp2);
4542 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4543 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4544 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4545 for(int i=1;i<nbOfLevsInVec;i++)
4547 const double *begin=coo1D+2*conn1D[connI1D[i-1]+1];
4548 const double *end=coo1D+2*conn1D[connI1D[i-1]+2];
4549 const double *third=i+1<nbOfLevsInVec?coo1D+2*conn1D[connI1D[i]+2]:coo1D+2*conn1D[connI1D[i-2]+1];
4550 const double vec[2]={end[0]-begin[0],end[1]-begin[1]};
4551 tmp->translate(vec);
4552 double tmp3[2],radius,alpha,alpha0;
4553 const double *p0=i+1<nbOfLevsInVec?begin:third;
4554 const double *p1=i+1<nbOfLevsInVec?end:begin;
4555 const double *p2=i+1<nbOfLevsInVec?third:end;
4556 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0,p1,p2,tmp3,radius,alpha,alpha0);
4557 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]);
4558 double angle=acos(cosangle/(radius*radius));
4559 tmp->rotate(end,0,angle);
4560 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4566 * This method incarnates the policy 1 for MEDCouplingUMesh::buildExtrudedMesh method.
4567 * \param mesh1D is the input 1D mesh used for translation and automatic rotation computation.
4568 * \return newCoords new coords filled by this method.
4570 DataArrayDouble *MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D(const MEDCouplingUMesh *mesh1D, bool isQuad) const throw(INTERP_KERNEL::Exception)
4573 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : not implemented for quadratic cells !");
4574 int oldNbOfNodes=getNumberOfNodes();
4575 int nbOf1DCells=mesh1D->getNumberOfCells();
4577 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::fillExtCoordsUsingTranslAndAutoRotation3D : impossible to detect any angle of rotation ! Change extrusion policy 1->0 !");
4578 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
4579 int nbOfLevsInVec=nbOf1DCells+1;
4580 ret->alloc(oldNbOfNodes*nbOfLevsInVec,3);
4581 double *retPtr=ret->getPointer();
4582 retPtr=std::copy(getCoords()->getConstPointer(),getCoords()->getConstPointer()+getCoords()->getNbOfElems(),retPtr);
4583 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
4584 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp2=getCoords()->deepCpy();
4585 tmp->setCoords(tmp2);
4586 const double *coo1D=mesh1D->getCoords()->getConstPointer();
4587 const int *conn1D=mesh1D->getNodalConnectivity()->getConstPointer();
4588 const int *connI1D=mesh1D->getNodalConnectivityIndex()->getConstPointer();
4589 for(int i=1;i<nbOfLevsInVec;i++)
4591 const double *begin=coo1D+3*conn1D[connI1D[i-1]+1];
4592 const double *end=coo1D+3*conn1D[connI1D[i-1]+2];
4593 const double *third=i+1<nbOfLevsInVec?coo1D+3*conn1D[connI1D[i]+2]:coo1D+3*conn1D[connI1D[i-2]+1];
4594 const double vec[3]={end[0]-begin[0],end[1]-begin[1],end[2]-begin[2]};
4595 tmp->translate(vec);
4596 double tmp3[2],radius,alpha,alpha0;
4597 const double *p0=i+1<nbOfLevsInVec?begin:third;
4598 const double *p1=i+1<nbOfLevsInVec?end:begin;
4599 const double *p2=i+1<nbOfLevsInVec?third:end;
4600 double vecPlane[3]={
4601 (p1[1]-p0[1])*(p2[2]-p1[2])-(p1[2]-p0[2])*(p2[1]-p1[1]),
4602 (p1[2]-p0[2])*(p2[0]-p1[0])-(p1[0]-p0[0])*(p2[2]-p1[2]),
4603 (p1[0]-p0[0])*(p2[1]-p1[1])-(p1[1]-p0[1])*(p2[0]-p1[0]),
4605 double norm=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]+vecPlane[2]*vecPlane[2]);
4608 vecPlane[0]/=norm; vecPlane[1]/=norm; vecPlane[2]/=norm;
4609 double norm2=sqrt(vecPlane[0]*vecPlane[0]+vecPlane[1]*vecPlane[1]);
4610 double vec2[2]={vecPlane[1]/norm2,-vecPlane[0]/norm2};
4612 double c2=cos(asin(s2));
4614 {vec2[0]*vec2[0]*(1-c2)+c2, vec2[0]*vec2[1]*(1-c2), vec2[1]*s2},
4615 {vec2[0]*vec2[1]*(1-c2), vec2[1]*vec2[1]*(1-c2)+c2, -vec2[0]*s2},
4616 {-vec2[1]*s2, vec2[0]*s2, c2}
4618 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]};
4619 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]};
4620 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]};
4621 INTERP_KERNEL::EdgeArcCircle::GetArcOfCirclePassingThru(p0r,p1r,p2r,tmp3,radius,alpha,alpha0);
4622 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]);
4623 double angle=acos(cosangle/(radius*radius));
4624 tmp->rotate(end,vecPlane,angle);
4627 retPtr=std::copy(tmp2->getConstPointer(),tmp2->getConstPointer()+tmp2->getNbOfElems(),retPtr);
4633 * This method is private because not easy to use for end user. This method is const contrary to
4634 * MEDCouplingUMesh::buildExtrudedMesh method because this->_coords are expected to contain
4635 * the coords sorted slice by slice.
4636 * \param isQuad specifies presence of quadratic cells.
4638 MEDCouplingUMesh *MEDCouplingUMesh::buildExtrudedMeshFromThisLowLev(int nbOfNodesOf1Lev, bool isQuad) const
4640 int nbOf1DCells=getNumberOfNodes()/nbOfNodesOf1Lev-1;
4641 int nbOf2DCells=getNumberOfCells();
4642 int nbOf3DCells=nbOf2DCells*nbOf1DCells;
4643 MEDCouplingUMesh *ret=MEDCouplingUMesh::New("Extruded",getMeshDimension()+1);
4644 const int *conn=_nodal_connec->getConstPointer();
4645 const int *connI=_nodal_connec_index->getConstPointer();
4646 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4647 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4648 newConnI->alloc(nbOf3DCells+1,1);
4649 int *newConnIPtr=newConnI->getPointer();
4651 std::vector<int> newc;
4652 for(int j=0;j<nbOf2DCells;j++)
4654 AppendExtrudedCell(conn+connI[j],conn+connI[j+1],nbOfNodesOf1Lev,isQuad,newc);
4655 *newConnIPtr++=(int)newc.size();
4657 newConn->alloc((int)(newc.size())*nbOf1DCells,1);
4658 int *newConnPtr=newConn->getPointer();
4659 int deltaPerLev=isQuad?2*nbOfNodesOf1Lev:nbOfNodesOf1Lev;
4660 newConnIPtr=newConnI->getPointer();
4661 for(int iz=0;iz<nbOf1DCells;iz++)
4664 std::transform(newConnIPtr+1,newConnIPtr+1+nbOf2DCells,newConnIPtr+1+iz*nbOf2DCells,std::bind2nd(std::plus<int>(),newConnIPtr[iz*nbOf2DCells]));
4665 for(std::vector<int>::const_iterator iter=newc.begin();iter!=newc.end();iter++,newConnPtr++)
4667 int icell=(int)(iter-newc.begin());
4668 if(std::find(newConnIPtr,newConnIPtr+nbOf2DCells,icell)==newConnIPtr+nbOf2DCells)
4671 *newConnPtr=(*iter)+iz*deltaPerLev;
4676 *newConnPtr=(*iter);
4679 ret->setConnectivity(newConn,newConnI,true);
4680 ret->setCoords(getCoords());
4685 * Checks if \a this mesh is constituted by only quadratic cells.
4686 * \return bool - \c true if there are only quadratic cells in \a this mesh.
4687 * \throw If the coordinates array is not set.
4688 * \throw If the nodal connectivity of cells is not defined.
4690 bool MEDCouplingUMesh::isFullyQuadratic() const
4692 checkFullyDefined();
4694 int nbOfCells=getNumberOfCells();
4695 for(int i=0;i<nbOfCells && ret;i++)
4697 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4698 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4699 ret=cm.isQuadratic();
4705 * Checks if \a this mesh includes any quadratic cell.
4706 * \return bool - \c true if there is at least one quadratic cells in \a this mesh.
4707 * \throw If the coordinates array is not set.
4708 * \throw If the nodal connectivity of cells is not defined.
4710 bool MEDCouplingUMesh::isPresenceOfQuadratic() const
4712 checkFullyDefined();
4714 int nbOfCells=getNumberOfCells();
4715 for(int i=0;i<nbOfCells && !ret;i++)
4717 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4718 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4719 ret=cm.isQuadratic();
4725 * Converts all quadratic cells to linear ones. If there are no quadratic cells in \a
4726 * this mesh, it remains unchanged.
4727 * \throw If the coordinates array is not set.
4728 * \throw If the nodal connectivity of cells is not defined.
4730 void MEDCouplingUMesh::convertQuadraticCellsToLinear() throw(INTERP_KERNEL::Exception)
4732 checkFullyDefined();
4733 int nbOfCells=getNumberOfCells();
4735 const int *iciptr=_nodal_connec_index->getConstPointer();
4736 for(int i=0;i<nbOfCells;i++)
4738 INTERP_KERNEL::NormalizedCellType type=getTypeOfCell(i);
4739 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4740 if(cm.isQuadratic())
4742 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4743 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4744 if(!cml.isDynamic())
4745 delta+=cm.getNumberOfNodes()-cml.getNumberOfNodes();
4747 delta+=(iciptr[i+1]-iciptr[i]-1)/2;
4752 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
4753 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
4754 const int *icptr=_nodal_connec->getConstPointer();
4755 newConn->alloc(getMeshLength()-delta,1);
4756 newConnI->alloc(nbOfCells+1,1);
4757 int *ocptr=newConn->getPointer();
4758 int *ociptr=newConnI->getPointer();
4761 for(int i=0;i<nbOfCells;i++,ociptr++)
4763 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)icptr[iciptr[i]];
4764 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(type);
4765 if(!cm.isQuadratic())
4767 _types.insert(type);
4768 ocptr=std::copy(icptr+iciptr[i],icptr+iciptr[i+1],ocptr);
4769 ociptr[1]=ociptr[0]+iciptr[i+1]-iciptr[i];
4773 INTERP_KERNEL::NormalizedCellType typel=cm.getLinearType();
4774 _types.insert(typel);
4775 const INTERP_KERNEL::CellModel& cml=INTERP_KERNEL::CellModel::GetCellModel(typel);
4776 int newNbOfNodes=cml.getNumberOfNodes();
4778 newNbOfNodes=(iciptr[i+1]-iciptr[i]-1)/2;
4779 *ocptr++=(int)typel;
4780 ocptr=std::copy(icptr+iciptr[i]+1,icptr+iciptr[i]+newNbOfNodes+1,ocptr);
4781 ociptr[1]=ociptr[0]+newNbOfNodes+1;
4784 setConnectivity(newConn,newConnI,false);
4788 * This method converts all linear cell in \a this to quadratic one.
4789 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, here it is needed to specify the target
4790 * 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)
4791 * 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.
4792 * Contrary to MEDCouplingUMesh::convertQuadraticCellsToLinear method, the coordinates in \a this can be become bigger. All created nodes will be put at the
4793 * end of the existing coordinates.
4795 * \param [in] conversionType specifies the type of conversion expected. Only 0 (default) and 1 are supported presently. 0 those that creates the 'most' simple
4796 * corresponding quadratic cells. 1 is those creating the 'most' complex.
4797 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4799 * \throw if \a this is not fully defined. It throws too if \a conversionType is not in [0,1].
4801 * \sa MEDCouplingUMesh::convertQuadraticCellsToLinear
4803 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic(int conversionType) throw(INTERP_KERNEL::Exception)
4805 DataArrayInt *conn=0,*connI=0;
4806 DataArrayDouble *coords=0;
4807 std::set<INTERP_KERNEL::NormalizedCellType> types;
4808 checkFullyDefined();
4809 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret,connSafe,connISafe;
4810 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsSafe;
4811 int meshDim=getMeshDimension();
4812 switch(conversionType)
4818 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);
4819 connSafe=conn; connISafe=connI; coordsSafe=coords;
4822 ret=convertLinearCellsToQuadratic2D0(conn,connI,coords,types);
4823 connSafe=conn; connISafe=connI; coordsSafe=coords;
4826 ret=convertLinearCellsToQuadratic3D0(conn,connI,coords,types);
4827 connSafe=conn; connISafe=connI; coordsSafe=coords;
4830 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 0 mesh dimensions available are [1,2,3] !");
4838 ret=convertLinearCellsToQuadratic1D0(conn,connI,coords,types);//it is not a bug. In 1D policy 0 and 1 are equals
4839 connSafe=conn; connISafe=connI; coordsSafe=coords;
4842 ret=convertLinearCellsToQuadratic2D1(conn,connI,coords,types);
4843 connSafe=conn; connISafe=connI; coordsSafe=coords;
4846 ret=convertLinearCellsToQuadratic3D1(conn,connI,coords,types);
4847 connSafe=conn; connISafe=connI; coordsSafe=coords;
4850 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion of type 1 mesh dimensions available are [1,2,3] !");
4855 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertLinearCellsToQuadratic : conversion type available are 0 (default, the simplest) and 1 (the most complex) !");
4857 setConnectivity(connSafe,connISafe,false);
4859 setCoords(coordsSafe);
4864 * Implementes \a conversionType 0 for meshes with meshDim = 1, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4865 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4866 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4868 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic1D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4870 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4871 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4872 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4873 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4874 int nbOfCells=getNumberOfCells();
4875 int nbOfNodes=getNumberOfNodes();
4876 const int *cPtr=_nodal_connec->getConstPointer();
4877 const int *icPtr=_nodal_connec_index->getConstPointer();
4878 int lastVal=0,offset=nbOfNodes;
4879 for(int i=0;i<nbOfCells;i++,icPtr++)
4881 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4882 if(type==INTERP_KERNEL::NORM_SEG2)
4884 types.insert(INTERP_KERNEL::NORM_SEG3);
4885 newConn->pushBackSilent((int)INTERP_KERNEL::NORM_SEG3);
4886 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[0]+3);
4887 newConn->pushBackSilent(offset++);
4889 newConnI->pushBackSilent(lastVal);
4890 ret->pushBackSilent(i);
4895 lastVal+=(icPtr[1]-icPtr[0]);
4896 newConnI->pushBackSilent(lastVal);
4897 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4900 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
4901 coords=DataArrayDouble::Aggregate(getCoords(),tmp); conn=newConn.retn(); connI=newConnI.retn();
4905 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)
4907 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4908 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4909 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4911 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4912 DataArrayInt *conn1D=0,*conn1DI=0;
4913 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4914 DataArrayDouble *coordsTmp=0;
4915 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4916 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4917 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4918 const int *c1DPtr=conn1D->begin();
4919 const int *c1DIPtr=conn1DI->begin();
4920 int nbOfCells=getNumberOfCells();
4921 const int *cPtr=_nodal_connec->getConstPointer();
4922 const int *icPtr=_nodal_connec_index->getConstPointer();
4924 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4926 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4927 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4928 if(!cm.isQuadratic())
4930 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType();
4931 types.insert(typ2); newConn->pushBackSilent(typ2);
4932 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4933 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4934 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4935 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0]);
4936 newConnI->pushBackSilent(lastVal);
4937 ret->pushBackSilent(i);
4942 lastVal+=(icPtr[1]-icPtr[0]);
4943 newConnI->pushBackSilent(lastVal);
4944 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
4947 conn=newConn.retn(); connI=newConnI.retn(); coords=coordsTmpSafe.retn();
4952 * Implementes \a conversionType 0 for meshes with meshDim = 2, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
4953 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
4954 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
4956 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4959 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4960 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4961 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
4964 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic2D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
4966 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
4967 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=buildDescendingConnectivity(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
4969 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
4970 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
4971 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
4973 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
4974 const int *descPtr(desc->begin()),*descIPtr(descI->begin());
4975 DataArrayInt *conn1D=0,*conn1DI=0;
4976 std::set<INTERP_KERNEL::NormalizedCellType> types1D;
4977 DataArrayDouble *coordsTmp=0;
4978 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=0;
4979 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
4980 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
4981 const int *c1DPtr=conn1D->begin();
4982 const int *c1DIPtr=conn1DI->begin();
4983 int nbOfCells=getNumberOfCells();
4984 const int *cPtr=_nodal_connec->getConstPointer();
4985 const int *icPtr=_nodal_connec_index->getConstPointer();
4986 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
4987 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++)
4989 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
4990 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
4991 if(!cm.isQuadratic())
4993 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
4994 types.insert(typ2); newConn->pushBackSilent(typ2);
4995 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
4996 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
4997 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
4998 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
4999 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+1;
5000 newConnI->pushBackSilent(lastVal);
5001 ret->pushBackSilent(i);
5006 lastVal+=(icPtr[1]-icPtr[0]);
5007 newConnI->pushBackSilent(lastVal);
5008 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5011 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5012 coords=DataArrayDouble::Aggregate(coordsTmpSafe,tmp); conn=newConn.retn(); connI=newConnI.retn();
5017 * Implementes \a conversionType 0 for meshes with meshDim = 3, of MEDCouplingUMesh::convertLinearCellsToQuadratic method.
5018 * \return a newly created DataArrayInt instance that the caller should deal with containing cell ids of converted cells.
5019 * \sa MEDCouplingUMesh::convertLinearCellsToQuadratic.
5021 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D0(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5023 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc(DataArrayInt::New()),descI(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5024 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc,descI,tmp2,tmp3); tmp2=0; tmp3=0;
5025 return convertLinearCellsToQuadratic2DAnd3D0(m1D,desc,descI,conn,connI,coords,types);
5028 DataArrayInt *MEDCouplingUMesh::convertLinearCellsToQuadratic3D1(DataArrayInt *&conn, DataArrayInt *&connI, DataArrayDouble *& coords, std::set<INTERP_KERNEL::NormalizedCellType>& types) const throw(INTERP_KERNEL::Exception)
5030 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc2(DataArrayInt::New()),desc2I(DataArrayInt::New()),tmp2(DataArrayInt::New()),tmp3(DataArrayInt::New());
5031 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m2D=buildDescendingConnectivityGen<MinusOneSonsGeneratorBiQuadratic>(desc2,desc2I,tmp2,tmp3,MEDCouplingFastNbrer); tmp2=0; tmp3=0;
5032 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1(DataArrayInt::New()),desc1I(DataArrayInt::New()),tmp4(DataArrayInt::New()),tmp5(DataArrayInt::New());
5033 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1D=explode3DMeshTo1D(desc1,desc1I,tmp4,tmp5); tmp4=0; tmp5=0;
5035 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New(); newConn->alloc(0,1);
5036 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New(); newConnI->alloc(1,1); newConnI->setIJ(0,0,0);
5037 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(),ret2=DataArrayInt::New(); ret->alloc(0,1); ret2->alloc(0,1);
5039 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bary=getBarycenterAndOwner();
5040 const int *descPtr(desc1->begin()),*descIPtr(desc1I->begin()),*desc2Ptr(desc2->begin()),*desc2IPtr(desc2I->begin());
5041 DataArrayInt *conn1D=0,*conn1DI=0,*conn2D=0,*conn2DI=0;
5042 std::set<INTERP_KERNEL::NormalizedCellType> types1D,types2D;
5043 DataArrayDouble *coordsTmp=0,*coordsTmp2=0;
5044 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1D=m1D->convertLinearCellsToQuadratic1D0(conn1D,conn1DI,coordsTmp,types1D); ret1D=DataArrayInt::New(); ret1D->alloc(0,1);
5045 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn1DSafe(conn1D),conn1DISafe(conn1DI);
5046 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmpSafe(coordsTmp);
5047 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret2D=m2D->convertLinearCellsToQuadratic2D1(conn2D,conn2DI,coordsTmp2,types2D); ret2D=DataArrayInt::New(); ret2D->alloc(0,1);
5048 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coordsTmp2Safe(coordsTmp2);
5049 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn2DSafe(conn2D),conn2DISafe(conn2DI);
5050 const int *c1DPtr=conn1D->begin(),*c1DIPtr=conn1DI->begin(),*c2DPtr=conn2D->begin(),*c2DIPtr=conn2DI->begin();
5051 int nbOfCells=getNumberOfCells();
5052 const int *cPtr=_nodal_connec->getConstPointer();
5053 const int *icPtr=_nodal_connec_index->getConstPointer();
5054 int lastVal=0,offset=coordsTmpSafe->getNumberOfTuples();
5055 for(int i=0;i<nbOfCells;i++,icPtr++,descIPtr++,desc2IPtr++)
5057 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)cPtr[*icPtr];
5058 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
5059 if(!cm.isQuadratic())
5061 INTERP_KERNEL::NormalizedCellType typ2=cm.getQuadraticType2();
5062 if(typ2==INTERP_KERNEL::NORM_ERROR)
5064 std::ostringstream oss; oss << "MEDCouplingUMesh::convertLinearCellsToQuadratic3D1 : On cell #" << i << " the linear cell type does not support advanced quadratization !";
5065 throw INTERP_KERNEL::Exception(oss.str().c_str());
5067 types.insert(typ2); newConn->pushBackSilent(typ2);
5068 newConn->pushBackValsSilent(cPtr+icPtr[0]+1,cPtr+icPtr[1]);
5069 for(const int *d=descPtr+descIPtr[0];d!=descPtr+descIPtr[1];d++)
5070 newConn->pushBackSilent(c1DPtr[c1DIPtr[*d]+3]);
5071 for(const int *d=desc2Ptr+desc2IPtr[0];d!=desc2Ptr+desc2IPtr[1];d++)
5073 int nodeId2=c2DPtr[c2DIPtr[(*d)+1]-1];
5074 int tmpPos=newConn->getNumberOfTuples();
5075 newConn->pushBackSilent(nodeId2);
5076 ret2D->pushBackSilent(nodeId2); ret1D->pushBackSilent(tmpPos);
5078 newConn->pushBackSilent(offset+ret->getNumberOfTuples());
5079 lastVal+=(icPtr[1]-icPtr[0])+(descIPtr[1]-descIPtr[0])+(desc2IPtr[1]-desc2IPtr[0])+1;
5080 newConnI->pushBackSilent(lastVal);
5081 ret->pushBackSilent(i);
5086 lastVal+=(icPtr[1]-icPtr[0]);
5087 newConnI->pushBackSilent(lastVal);
5088 newConn->pushBackValsSilent(cPtr+icPtr[0],cPtr+icPtr[1]);
5091 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> diffRet2D=ret2D->getDifferentValues();
5092 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2nRet2D=diffRet2D->invertArrayN2O2O2N(coordsTmp2Safe->getNumberOfTuples());
5093 coordsTmp2Safe=coordsTmp2Safe->selectByTupleId(diffRet2D->begin(),diffRet2D->end());
5094 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmp=bary->selectByTupleIdSafe(ret->begin(),ret->end());
5095 std::vector<const DataArrayDouble *> v(3); v[0]=coordsTmpSafe; v[1]=coordsTmp2Safe; v[2]=tmp;
5096 int *c=newConn->getPointer();
5097 const int *cI(newConnI->begin());
5098 for(const int *elt=ret1D->begin();elt!=ret1D->end();elt++)
5099 c[*elt]=o2nRet2D->getIJ(c[*elt],0)+offset;
5100 offset=coordsTmp2Safe->getNumberOfTuples();
5101 for(const int *elt=ret->begin();elt!=ret->end();elt++)
5102 c[cI[(*elt)+1]-1]+=offset;
5103 coords=DataArrayDouble::Aggregate(v); conn=newConn.retn(); connI=newConnI.retn();
5108 * Tessellates \a this 2D mesh by dividing not straight edges of quadratic faces,
5109 * so that the number of cells remains the same. Quadratic faces are converted to
5110 * polygons. This method works only for 2D meshes in
5111 * 2D space. If no cells are quadratic (INTERP_KERNEL::NORM_QUAD8,
5112 * INTERP_KERNEL::NORM_TRI6, INTERP_KERNEL::NORM_QPOLYG ), \a this mesh remains unchanged.
5113 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5114 * \param [in] eps - specifies the maximal angle (in radians) between 2 sub-edges of
5115 * a polylinized edge constituting the input polygon.
5116 * \throw If the coordinates array is not set.
5117 * \throw If the nodal connectivity of cells is not defined.
5118 * \throw If \a this->getMeshDimension() != 2.
5119 * \throw If \a this->getSpaceDimension() != 2.
5121 void MEDCouplingUMesh::tessellate2D(double eps) throw(INTERP_KERNEL::Exception)
5123 checkFullyDefined();
5124 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
5125 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2D works on umeshes with meshdim equal to 2 and spaceDim equal to 2 too!");
5126 double epsa=fabs(eps);
5127 if(epsa<std::numeric_limits<double>::min())
5128 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 !");
5129 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> desc1=DataArrayInt::New();
5130 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> descIndx1=DataArrayInt::New();
5131 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDesc1=DataArrayInt::New();
5132 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revDescIndx1=DataArrayInt::New();
5133 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mDesc=buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
5134 revDesc1=0; revDescIndx1=0;
5135 mDesc->tessellate2DCurve(eps);
5136 subDivide2DMesh(mDesc->_nodal_connec->getConstPointer(),mDesc->_nodal_connec_index->getConstPointer(),desc1->getConstPointer(),descIndx1->getConstPointer());
5137 setCoords(mDesc->getCoords());
5141 * Tessellates \a this 1D mesh in 2D space by dividing not straight quadratic edges.
5142 * \warning This method can lead to a huge amount of nodes if \a eps is very low.
5143 * \param [in] eps - specifies the maximal angle (in radian) between 2 sub-edges of
5144 * a sub-divided edge.
5145 * \throw If the coordinates array is not set.
5146 * \throw If the nodal connectivity of cells is not defined.
5147 * \throw If \a this->getMeshDimension() != 1.
5148 * \throw If \a this->getSpaceDimension() != 2.
5150 void MEDCouplingUMesh::tessellate2DCurve(double eps) throw(INTERP_KERNEL::Exception)
5152 checkFullyDefined();
5153 if(getMeshDimension()!=1 || getSpaceDimension()!=2)
5154 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tessellate2DCurve works on umeshes with meshdim equal to 1 and spaceDim equal to 2 too!");
5155 double epsa=fabs(eps);
5156 if(epsa<std::numeric_limits<double>::min())
5157 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 !");
5158 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=1.e-10;
5159 int nbCells=getNumberOfCells();
5160 int nbNodes=getNumberOfNodes();
5161 const int *conn=_nodal_connec->getConstPointer();
5162 const int *connI=_nodal_connec_index->getConstPointer();
5163 const double *coords=_coords->getConstPointer();
5164 std::vector<double> addCoo;
5165 std::vector<int> newConn;//no direct DataArrayInt because interface with Geometric2D
5166 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI(DataArrayInt::New());
5167 newConnI->alloc(nbCells+1,1);
5168 int *newConnIPtr=newConnI->getPointer();
5171 INTERP_KERNEL::Node *tmp2[3];
5172 std::set<INTERP_KERNEL::NormalizedCellType> types;
5173 for(int i=0;i<nbCells;i++,newConnIPtr++)
5175 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5176 if(cm.isQuadratic())
5177 {//assert(connI[i+1]-connI[i]-1==3)
5178 tmp1[0]=conn[connI[i]+1+0]; tmp1[1]=conn[connI[i]+1+1]; tmp1[2]=conn[connI[i]+1+2];
5179 tmp2[0]=new INTERP_KERNEL::Node(coords[2*tmp1[0]],coords[2*tmp1[0]+1]);
5180 tmp2[1]=new INTERP_KERNEL::Node(coords[2*tmp1[1]],coords[2*tmp1[1]+1]);
5181 tmp2[2]=new INTERP_KERNEL::Node(coords[2*tmp1[2]],coords[2*tmp1[2]+1]);
5182 INTERP_KERNEL::EdgeArcCircle *eac=INTERP_KERNEL::EdgeArcCircle::BuildFromNodes(tmp2[0],tmp2[2],tmp2[1]);
5185 eac->tesselate(tmp1,nbNodes,epsa,newConn,addCoo);
5186 types.insert((INTERP_KERNEL::NormalizedCellType)newConn[newConnIPtr[0]]);
5188 newConnIPtr[1]=(int)newConn.size();
5192 types.insert(INTERP_KERNEL::NORM_SEG2);
5193 newConn.push_back(INTERP_KERNEL::NORM_SEG2);
5194 newConn.insert(newConn.end(),conn+connI[i]+1,conn+connI[i]+3);
5195 newConnIPtr[1]=newConnIPtr[0]+3;
5200 types.insert((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5201 newConn.insert(newConn.end(),conn+connI[i],conn+connI[i+1]);
5202 newConnIPtr[1]=newConnIPtr[0]+3;
5205 if(addCoo.empty() && ((int)newConn.size())==_nodal_connec->getNumberOfTuples())//nothing happens during tasselation : no update needed
5208 DataArrayInt::SetArrayIn(newConnI,_nodal_connec_index);
5209 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnArr=DataArrayInt::New();
5210 newConnArr->alloc((int)newConn.size(),1);
5211 std::copy(newConn.begin(),newConn.end(),newConnArr->getPointer());
5212 DataArrayInt::SetArrayIn(newConnArr,_nodal_connec);
5213 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=DataArrayDouble::New();
5214 newCoords->alloc(nbNodes+((int)addCoo.size())/2,2);
5215 double *work=std::copy(_coords->begin(),_coords->end(),newCoords->getPointer());
5216 std::copy(addCoo.begin(),addCoo.end(),work);
5217 DataArrayDouble::SetArrayIn(newCoords,_coords);
5222 * Divides every cell of \a this mesh into simplices (triangles in 2D and tetrahedra in 3D).
5223 * In addition, returns an array mapping new cells to old ones. <br>
5224 * This method typically increases the number of cells in \a this mesh
5225 * but the number of nodes remains \b unchanged.
5226 * That's why the 3D splitting policies
5227 * INTERP_KERNEL::GENERAL_24 and INTERP_KERNEL::GENERAL_48 are not available here.
5228 * \param [in] policy - specifies a pattern used for splitting.
5229 * The semantic of \a policy is:
5230 * - 0 - to split QUAD4 by cutting it along 0-2 diagonal (for 2D mesh only).
5231 * - 1 - to split QUAD4 by cutting it along 1-3 diagonal (for 2D mesh only).
5232 * - INTERP_KERNEL::PLANAR_FACE_5 - to split HEXA8 into 5 TETRA4 (for 3D mesh only).
5233 * - INTERP_KERNEL::PLANAR_FACE_6 - to split HEXA8 into 6 TETRA4 (for 3D mesh only).
5234 * \return DataArrayInt * - a new instance of DataArrayInt holding, for each new cell,
5235 * an id of old cell producing it. The caller is to delete this array using
5236 * decrRef() as it is no more needed.
5237 * \throw If \a policy is 0 or 1 and \a this->getMeshDimension() != 2.
5238 * \throw If \a policy is INTERP_KERNEL::PLANAR_FACE_5 or INTERP_KERNEL::PLANAR_FACE_6
5239 * and \a this->getMeshDimension() != 3.
5240 * \throw If \a policy is not one of the four discussed above.
5241 * \throw If the nodal connectivity of cells is not defined.
5242 * \sa MEDCouplingUMesh::tetrahedrize
5244 DataArrayInt *MEDCouplingUMesh::simplexize(int policy) throw(INTERP_KERNEL::Exception)
5249 return simplexizePol0();
5251 return simplexizePol1();
5252 case (int) INTERP_KERNEL::PLANAR_FACE_5:
5253 return simplexizePlanarFace5();
5254 case (int) INTERP_KERNEL::PLANAR_FACE_6:
5255 return simplexizePlanarFace6();
5257 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)");
5262 * Checks if \a this mesh is constituted by simplex cells only. Simplex cells are:
5263 * - 1D: INTERP_KERNEL::NORM_SEG2
5264 * - 2D: INTERP_KERNEL::NORM_TRI3
5265 * - 3D: INTERP_KERNEL::NORM_TETRA4.
5267 * This method is useful for users that need to use P1 field services as
5268 * MEDCouplingFieldDouble::getValueOn(), MEDCouplingField::buildMeasureField() etc.
5269 * All these methods need mesh support containing only simplex cells.
5270 * \return bool - \c true if there are only simplex cells in \a this mesh.
5271 * \throw If the coordinates array is not set.
5272 * \throw If the nodal connectivity of cells is not defined.
5273 * \throw If \a this->getMeshDimension() < 1.
5275 bool MEDCouplingUMesh::areOnlySimplexCells() const throw(INTERP_KERNEL::Exception)
5277 checkFullyDefined();
5278 int mdim=getMeshDimension();
5279 if(mdim<1 || mdim>3)
5280 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::areOnlySimplexCells : only available with meshes having a meshdim 1, 2 or 3 !");
5281 int nbCells=getNumberOfCells();
5282 const int *conn=_nodal_connec->getConstPointer();
5283 const int *connI=_nodal_connec_index->getConstPointer();
5284 for(int i=0;i<nbCells;i++)
5286 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5294 * This method implements policy 0 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5296 DataArrayInt *MEDCouplingUMesh::simplexizePol0() throw(INTERP_KERNEL::Exception)
5298 checkConnectivityFullyDefined();
5299 if(getMeshDimension()!=2)
5300 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5301 int nbOfCells=getNumberOfCells();
5302 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5303 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5304 ret->alloc(nbOfCells+nbOfCutCells,1);
5305 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5306 int *retPt=ret->getPointer();
5307 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5308 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5309 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5310 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5311 int *pt=newConn->getPointer();
5312 int *ptI=newConnI->getPointer();
5314 const int *oldc=_nodal_connec->getConstPointer();
5315 const int *ci=_nodal_connec_index->getConstPointer();
5316 for(int i=0;i<nbOfCells;i++,ci++)
5318 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5320 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+3],
5321 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+3],oldc[ci[0]+4]};
5322 pt=std::copy(tmp,tmp+8,pt);
5331 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5332 ptI[1]=ptI[0]+ci[1]-ci[0];
5337 _nodal_connec->decrRef();
5338 _nodal_connec=newConn.retn();
5339 _nodal_connec_index->decrRef();
5340 _nodal_connec_index=newConnI.retn();
5347 * This method implements policy 1 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5349 DataArrayInt *MEDCouplingUMesh::simplexizePol1() throw(INTERP_KERNEL::Exception)
5351 checkConnectivityFullyDefined();
5352 if(getMeshDimension()!=2)
5353 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePol0 : this policy is only available for mesh with meshdim == 2 !");
5354 int nbOfCells=getNumberOfCells();
5355 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5356 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_QUAD4);
5357 ret->alloc(nbOfCells+nbOfCutCells,1);
5358 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5359 int *retPt=ret->getPointer();
5360 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5361 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5362 newConnI->alloc(nbOfCells+nbOfCutCells+1,1);
5363 newConn->alloc(getMeshLength()+3*nbOfCutCells,1);
5364 int *pt=newConn->getPointer();
5365 int *ptI=newConnI->getPointer();
5367 const int *oldc=_nodal_connec->getConstPointer();
5368 const int *ci=_nodal_connec_index->getConstPointer();
5369 for(int i=0;i<nbOfCells;i++,ci++)
5371 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_QUAD4)
5373 const int tmp[8]={(int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+1],oldc[ci[0]+2],oldc[ci[0]+4],
5374 (int)INTERP_KERNEL::NORM_TRI3,oldc[ci[0]+2],oldc[ci[0]+3],oldc[ci[0]+4]};
5375 pt=std::copy(tmp,tmp+8,pt);
5384 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5385 ptI[1]=ptI[0]+ci[1]-ci[0];
5390 _nodal_connec->decrRef();
5391 _nodal_connec=newConn.retn();
5392 _nodal_connec_index->decrRef();
5393 _nodal_connec_index=newConnI.retn();
5400 * This method implements policy INTERP_KERNEL::PLANAR_FACE_5 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5402 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace5() throw(INTERP_KERNEL::Exception)
5404 checkConnectivityFullyDefined();
5405 if(getMeshDimension()!=3)
5406 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace5 : this policy is only available for mesh with meshdim == 3 !");
5407 int nbOfCells=getNumberOfCells();
5408 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5409 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5410 ret->alloc(nbOfCells+4*nbOfCutCells,1);
5411 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5412 int *retPt=ret->getPointer();
5413 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5414 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5415 newConnI->alloc(nbOfCells+4*nbOfCutCells+1,1);
5416 newConn->alloc(getMeshLength()+16*nbOfCutCells,1);//21
5417 int *pt=newConn->getPointer();
5418 int *ptI=newConnI->getPointer();
5420 const int *oldc=_nodal_connec->getConstPointer();
5421 const int *ci=_nodal_connec_index->getConstPointer();
5422 for(int i=0;i<nbOfCells;i++,ci++)
5424 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5426 for(int j=0;j<5;j++,pt+=5,ptI++)
5428 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5429 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];
5436 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5437 ptI[1]=ptI[0]+ci[1]-ci[0];
5442 _nodal_connec->decrRef();
5443 _nodal_connec=newConn.retn();
5444 _nodal_connec_index->decrRef();
5445 _nodal_connec_index=newConnI.retn();
5452 * This method implements policy INTERP_KERNEL::PLANAR_FACE_6 of virtual method ParaMEDMEM::MEDCouplingUMesh::simplexize.
5454 DataArrayInt *MEDCouplingUMesh::simplexizePlanarFace6() throw(INTERP_KERNEL::Exception)
5456 checkConnectivityFullyDefined();
5457 if(getMeshDimension()!=3)
5458 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::simplexizePlanarFace6 : this policy is only available for mesh with meshdim == 3 !");
5459 int nbOfCells=getNumberOfCells();
5460 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
5461 int nbOfCutCells=getNumberOfCellsWithType(INTERP_KERNEL::NORM_HEXA8);
5462 ret->alloc(nbOfCells+5*nbOfCutCells,1);
5463 if(nbOfCutCells==0) { ret->iota(0); return ret.retn(); }
5464 int *retPt=ret->getPointer();
5465 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5466 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConnI=DataArrayInt::New();
5467 newConnI->alloc(nbOfCells+5*nbOfCutCells+1,1);
5468 newConn->alloc(getMeshLength()+21*nbOfCutCells,1);
5469 int *pt=newConn->getPointer();
5470 int *ptI=newConnI->getPointer();
5472 const int *oldc=_nodal_connec->getConstPointer();
5473 const int *ci=_nodal_connec_index->getConstPointer();
5474 for(int i=0;i<nbOfCells;i++,ci++)
5476 if((INTERP_KERNEL::NormalizedCellType)oldc[ci[0]]==INTERP_KERNEL::NORM_HEXA8)
5478 for(int j=0;j<6;j++,pt+=5,ptI++)
5480 pt[0]=(int)INTERP_KERNEL::NORM_TETRA4;
5481 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];
5488 pt=std::copy(oldc+ci[0],oldc+ci[1],pt);
5489 ptI[1]=ptI[0]+ci[1]-ci[0];
5494 _nodal_connec->decrRef();
5495 _nodal_connec=newConn.retn();
5496 _nodal_connec_index->decrRef();
5497 _nodal_connec_index=newConnI.retn();
5504 * This 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.
5505 * This method completly ignore coordinates.
5506 * \param nodeSubdived is the nodal connectivity of subdivision of edges
5507 * \param nodeIndxSubdived is the nodal connectivity index of subdivision of edges
5508 * \param desc is descending connectivity in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5509 * \param descIndex is descending connectivity index in format specified in MEDCouplingUMesh::buildDescendingConnectivity2
5511 void MEDCouplingUMesh::subDivide2DMesh(const int *nodeSubdived, const int *nodeIndxSubdived, const int *desc, const int *descIndex) throw(INTERP_KERNEL::Exception)
5513 checkFullyDefined();
5514 if(getMeshDimension()!=2)
5515 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : works only on umesh with meshdim==2 !");
5516 int nbOfCells=getNumberOfCells();
5517 int *connI=_nodal_connec_index->getPointer();
5519 for(int i=0;i<nbOfCells;i++,connI++)
5521 int offset=descIndex[i];
5522 int nbOfEdges=descIndex[i+1]-offset;
5524 bool ddirect=desc[offset+nbOfEdges-1]>0;
5525 int eedgeId=std::abs(desc[offset+nbOfEdges-1])-1;
5526 int ref=ddirect?nodeSubdived[nodeIndxSubdived[eedgeId+1]-1]:nodeSubdived[nodeIndxSubdived[eedgeId]+1];
5527 for(int j=0;j<nbOfEdges;j++)
5529 bool direct=desc[offset+j]>0;
5530 int edgeId=std::abs(desc[offset+j])-1;
5531 if(!INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodeSubdived[nodeIndxSubdived[edgeId]]).isQuadratic())
5533 int id1=nodeSubdived[nodeIndxSubdived[edgeId]+1];
5534 int id2=nodeSubdived[nodeIndxSubdived[edgeId+1]-1];
5535 int ref2=direct?id1:id2;
5538 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5539 newConnLgth+=nbOfSubNodes-1;
5544 std::ostringstream oss; oss << "MEDCouplingUMesh::subDivide2DMesh : On polygon #" << i << " edgeid #" << j << " subedges mismatch : end subedge k!=start subedge k+1 !";
5545 throw INTERP_KERNEL::Exception(oss.str().c_str());
5550 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::subDivide2DMesh : this method only subdivides into linear edges !");
5553 newConnLgth++;//+1 is for cell type
5554 connI[1]=newConnLgth;
5557 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn=DataArrayInt::New();
5558 newConn->alloc(newConnLgth,1);
5559 int *work=newConn->getPointer();
5560 for(int i=0;i<nbOfCells;i++)
5562 *work++=INTERP_KERNEL::NORM_POLYGON;
5563 int offset=descIndex[i];
5564 int nbOfEdges=descIndex[i+1]-offset;
5565 for(int j=0;j<nbOfEdges;j++)
5567 bool direct=desc[offset+j]>0;
5568 int edgeId=std::abs(desc[offset+j])-1;
5570 work=std::copy(nodeSubdived+nodeIndxSubdived[edgeId]+1,nodeSubdived+nodeIndxSubdived[edgeId+1]-1,work);
5573 int nbOfSubNodes=nodeIndxSubdived[edgeId+1]-nodeIndxSubdived[edgeId]-1;
5574 std::reverse_iterator<const int *> it(nodeSubdived+nodeIndxSubdived[edgeId+1]);
5575 work=std::copy(it,it+nbOfSubNodes-1,work);
5579 DataArrayInt::SetArrayIn(newConn,_nodal_connec);
5582 _types.insert(INTERP_KERNEL::NORM_POLYGON);
5586 * Converts degenerated 2D or 3D linear cells of \a this mesh into cells of simpler
5587 * type. For example an INTERP_KERNEL::NORM_QUAD4 cell having only three unique nodes in
5588 * its connectivity is transformed into an INTERP_KERNEL::NORM_TRI3 cell. This method
5589 * does \b not perform geometrical checks and checks only nodal connectivity of cells,
5590 * so it can be useful to call mergeNodes() before calling this method.
5591 * \throw If \a this->getMeshDimension() <= 1.
5592 * \throw If the coordinates array is not set.
5593 * \throw If the nodal connectivity of cells is not defined.
5595 void MEDCouplingUMesh::convertDegeneratedCells() throw(INTERP_KERNEL::Exception)
5597 checkFullyDefined();
5598 if(getMeshDimension()<=1)
5599 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertDegeneratedCells works on umeshes with meshdim equals to 2 or 3 !");
5600 int nbOfCells=getNumberOfCells();
5603 int initMeshLgth=getMeshLength();
5604 int *conn=_nodal_connec->getPointer();
5605 int *index=_nodal_connec_index->getPointer();
5609 for(int i=0;i<nbOfCells;i++)
5611 lgthOfCurCell=index[i+1]-posOfCurCell;
5612 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[posOfCurCell];
5614 INTERP_KERNEL::NormalizedCellType newType=INTERP_KERNEL::CellSimplify::simplifyDegeneratedCell(type,conn+posOfCurCell+1,lgthOfCurCell-1,
5615 conn+newPos+1,newLgth);
5616 conn[newPos]=newType;
5618 posOfCurCell=index[i+1];
5621 if(newPos!=initMeshLgth)
5622 _nodal_connec->reAlloc(newPos);
5627 * Finds incorrectly oriented cells of this 2D mesh in 3D space.
5628 * A cell is considered to be oriented correctly if an angle between its
5629 * normal vector and a given vector is less than \c PI / \c 2.
5630 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5632 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5634 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5635 * is not cleared before filling in.
5636 * \throw If \a this->getMeshDimension() != 2.
5637 * \throw If \a this->getSpaceDimension() != 3.
5639 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5640 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5642 void MEDCouplingUMesh::are2DCellsNotCorrectlyOriented(const double *vec, bool polyOnly, std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5644 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5645 throw INTERP_KERNEL::Exception("Invalid mesh to apply are2DCellsNotCorrectlyOriented on it : must be meshDim==2 and spaceDim==3 !");
5646 int nbOfCells=getNumberOfCells();
5647 const int *conn=_nodal_connec->getConstPointer();
5648 const int *connI=_nodal_connec_index->getConstPointer();
5649 const double *coordsPtr=_coords->getConstPointer();
5650 for(int i=0;i<nbOfCells;i++)
5652 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5653 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5655 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5656 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5663 * Reverse connectivity of 2D cells whose orientation is not correct. A cell is
5664 * considered to be oriented correctly if an angle between its normal vector and a
5665 * given vector is less than \c PI / \c 2.
5666 * \param [in] vec - 3 components of the vector specifying the correct orientation of
5668 * \param [in] polyOnly - if \c true, only polygons are checked, else, all cells are
5670 * \throw If \a this->getMeshDimension() != 2.
5671 * \throw If \a this->getSpaceDimension() != 3.
5673 * \ref cpp_mcumesh_are2DCellsNotCorrectlyOriented "Here is a C++ example".<br>
5674 * \ref py_mcumesh_are2DCellsNotCorrectlyOriented "Here is a Python example".
5676 void MEDCouplingUMesh::orientCorrectly2DCells(const double *vec, bool polyOnly) throw(INTERP_KERNEL::Exception)
5678 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5679 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectly2DCells on it : must be meshDim==2 and spaceDim==3 !");
5680 int nbOfCells=getNumberOfCells();
5681 int *conn=_nodal_connec->getPointer();
5682 const int *connI=_nodal_connec_index->getConstPointer();
5683 const double *coordsPtr=_coords->getConstPointer();
5684 bool isModified=false;
5685 for(int i=0;i<nbOfCells;i++)
5687 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5688 if(!polyOnly || (type==INTERP_KERNEL::NORM_POLYGON || type==INTERP_KERNEL::NORM_QPOLYG))
5690 bool isQuadratic=INTERP_KERNEL::CellModel::GetCellModel(type).isQuadratic();
5691 if(!IsPolygonWellOriented(isQuadratic,vec,conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5694 std::vector<int> tmp(connI[i+1]-connI[i]-2);
5695 std::copy(conn+connI[i]+2,conn+connI[i+1],tmp.rbegin());
5696 std::copy(tmp.begin(),tmp.end(),conn+connI[i]+2);
5701 _nodal_connec->declareAsNew();
5706 * Finds incorrectly oriented polyhedral cells, i.e. polyhedrons having correctly
5707 * oriented facets. The normal vector of the facet should point out of the cell.
5708 * \param [in,out] cells - a vector returning ids of incorrectly oriented cells. It
5709 * is not cleared before filling in.
5710 * \throw If \a this->getMeshDimension() != 3.
5711 * \throw If \a this->getSpaceDimension() != 3.
5712 * \throw If the coordinates array is not set.
5713 * \throw If the nodal connectivity of cells is not defined.
5715 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5716 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5718 void MEDCouplingUMesh::arePolyhedronsNotCorrectlyOriented(std::vector<int>& cells) const throw(INTERP_KERNEL::Exception)
5720 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5721 throw INTERP_KERNEL::Exception("Invalid mesh to apply arePolyhedronsNotCorrectlyOriented on it : must be meshDim==3 and spaceDim==3 !");
5722 int nbOfCells=getNumberOfCells();
5723 const int *conn=_nodal_connec->getConstPointer();
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)
5731 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5738 * Tries to fix connectivity of polyhedra, so that normal vector of all facets to point
5740 * \throw If \a this->getMeshDimension() != 3.
5741 * \throw If \a this->getSpaceDimension() != 3.
5742 * \throw If the coordinates array is not set.
5743 * \throw If the nodal connectivity of cells is not defined.
5744 * \throw If the reparation fails.
5746 * \ref cpp_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a C++ example".<br>
5747 * \ref py_mcumesh_arePolyhedronsNotCorrectlyOriented "Here is a Python example".
5748 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5750 void MEDCouplingUMesh::orientCorrectlyPolyhedrons() throw(INTERP_KERNEL::Exception)
5752 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5753 throw INTERP_KERNEL::Exception("Invalid mesh to apply orientCorrectlyPolyhedrons on it : must be meshDim==3 and spaceDim==3 !");
5754 int nbOfCells=getNumberOfCells();
5755 int *conn=_nodal_connec->getPointer();
5756 const int *connI=_nodal_connec_index->getConstPointer();
5757 const double *coordsPtr=_coords->getConstPointer();
5758 for(int i=0;i<nbOfCells;i++)
5760 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5761 if(type==INTERP_KERNEL::NORM_POLYHED)
5765 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5766 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5768 catch(INTERP_KERNEL::Exception& e)
5770 std::ostringstream oss; oss << "Something wrong in polyhedron #" << i << " : " << e.what();
5771 throw INTERP_KERNEL::Exception(oss.str().c_str());
5779 * Finds and fixes incorrectly oriented linear extruded volumes (INTERP_KERNEL::NORM_HEXA8,
5780 * INTERP_KERNEL::NORM_PENTA6, INTERP_KERNEL::NORM_HEXGP12 etc) to respect the MED convention
5781 * according to which the first facet of the cell should be oriented to have the normal vector
5782 * pointing out of cell.
5783 * \return DataArrayInt * - a new instance of DataArrayInt holding ids of fixed
5784 * cells. The caller is to delete this array using decrRef() as it is no more
5786 * \throw If \a this->getMeshDimension() != 3.
5787 * \throw If \a this->getSpaceDimension() != 3.
5788 * \throw If the coordinates array is not set.
5789 * \throw If the nodal connectivity of cells is not defined.
5791 * \ref cpp_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a C++ example".<br>
5792 * \ref py_mcumesh_findAndCorrectBadOriented3DExtrudedCells "Here is a Python example".
5793 * \sa MEDCouplingUMesh::findAndCorrectBadOriented3DCells
5795 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DExtrudedCells() throw(INTERP_KERNEL::Exception)
5797 const char msg[]="check3DCellsWellOriented detection works only for 3D cells !";
5798 if(getMeshDimension()!=3)
5799 throw INTERP_KERNEL::Exception(msg);
5800 int spaceDim=getSpaceDimension();
5802 throw INTERP_KERNEL::Exception(msg);
5804 int nbOfCells=getNumberOfCells();
5805 int *conn=_nodal_connec->getPointer();
5806 const int *connI=_nodal_connec_index->getConstPointer();
5807 const double *coo=getCoords()->getConstPointer();
5808 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cells(DataArrayInt::New()); cells->alloc(0,1);
5809 for(int i=0;i<nbOfCells;i++)
5811 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[connI[i]]);
5812 if(cm.isExtruded() && !cm.isDynamic() && !cm.isQuadratic())
5814 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coo))
5816 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5817 cells->pushBackSilent(i);
5821 return cells.retn();
5825 * This method is a faster method to correct orientation of all 3D cells in \a this.
5826 * 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.
5827 * This method makes the hypothesis that \a this a coherent that is to say MEDCouplingUMesh::checkCoherency2 should throw no exception.
5829 * \ret a newly allocated int array with one components containing cell ids renumbered to fit the convention of MED (MED file and MEDCoupling)
5830 * \sa MEDCouplingUMesh::orientCorrectlyPolyhedrons,
5832 DataArrayInt *MEDCouplingUMesh::findAndCorrectBadOriented3DCells() throw(INTERP_KERNEL::Exception)
5834 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
5835 throw INTERP_KERNEL::Exception("Invalid mesh to apply findAndCorrectBadOriented3DCells on it : must be meshDim==3 and spaceDim==3 !");
5836 int nbOfCells=getNumberOfCells();
5837 int *conn=_nodal_connec->getPointer();
5838 const int *connI=_nodal_connec_index->getConstPointer();
5839 const double *coordsPtr=_coords->getConstPointer();
5840 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(0,1);
5841 for(int i=0;i<nbOfCells;i++)
5843 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)conn[connI[i]];
5846 case INTERP_KERNEL::NORM_TETRA4:
5848 if(!IsTetra4WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5850 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+3));
5851 ret->pushBackSilent(i);
5855 case INTERP_KERNEL::NORM_PYRA5:
5857 if(!IsPyra5WellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5859 std::swap(*(conn+connI[i]+2),*(conn+connI[i]+4));
5860 ret->pushBackSilent(i);
5864 case INTERP_KERNEL::NORM_PENTA6:
5865 case INTERP_KERNEL::NORM_HEXA8:
5866 case INTERP_KERNEL::NORM_HEXGP12:
5868 if(!Is3DExtrudedStaticCellWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5870 CorrectExtrudedStaticCell(conn+connI[i]+1,conn+connI[i+1]);
5871 ret->pushBackSilent(i);
5875 case INTERP_KERNEL::NORM_POLYHED:
5877 if(!IsPolyhedronWellOriented(conn+connI[i]+1,conn+connI[i+1],coordsPtr))
5879 TryToCorrectPolyhedronOrientation(conn+connI[i]+1,conn+connI[i+1],coordsPtr);
5880 ret->pushBackSilent(i);
5885 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 !");
5893 * This method has a sense for meshes with spaceDim==3 and meshDim==2.
5894 * If it is not the case an exception will be thrown.
5895 * This method is fast because the first cell of \a this is used to compute the plane.
5896 * \param vec output of size at least 3 used to store the normal vector (with norm equal to Area ) of searched plane.
5897 * \param pos output of size at least 3 used to store a point owned of searched plane.
5899 void MEDCouplingUMesh::getFastAveragePlaneOfThis(double *vec, double *pos) const throw(INTERP_KERNEL::Exception)
5901 if(getMeshDimension()!=2 || getSpaceDimension()!=3)
5902 throw INTERP_KERNEL::Exception("Invalid mesh to apply getFastAveragePlaneOfThis on it : must be meshDim==2 and spaceDim==3 !");
5903 const int *conn=_nodal_connec->getConstPointer();
5904 const int *connI=_nodal_connec_index->getConstPointer();
5905 const double *coordsPtr=_coords->getConstPointer();
5906 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(conn+1,connI[1]-connI[0]-1,coordsPtr,vec);
5907 std::copy(coordsPtr+3*conn[1],coordsPtr+3*conn[1]+3,pos);
5911 * Creates a new MEDCouplingFieldDouble holding Edge Ratio values of all
5912 * cells. Currently cells of the following types are treated:
5913 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5914 * For a cell of other type an exception is thrown.
5915 * Space dimension of a 2D mesh can be either 2 or 3.
5916 * The Edge Ratio of a cell \f$t\f$ is:
5917 * \f$\frac{|t|_\infty}{|t|_0}\f$,
5918 * where \f$|t|_\infty\f$ and \f$|t|_0\f$ respectively denote the greatest and
5919 * the smallest edge lengths of \f$t\f$.
5920 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5921 * cells and one time, lying on \a this mesh. The caller is to delete this
5922 * field using decrRef() as it is no more needed.
5923 * \throw If the coordinates array is not set.
5924 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5925 * \throw If the connectivity data array has more than one component.
5926 * \throw If the connectivity data array has a named component.
5927 * \throw If the connectivity index data array has more than one component.
5928 * \throw If the connectivity index data array has a named component.
5929 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
5930 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
5931 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
5933 MEDCouplingFieldDouble *MEDCouplingUMesh::getEdgeRatioField() const throw(INTERP_KERNEL::Exception)
5936 int spaceDim=getSpaceDimension();
5937 int meshDim=getMeshDimension();
5938 if(spaceDim!=2 && spaceDim!=3)
5939 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : SpaceDimension must be equal to 2 or 3 !");
5940 if(meshDim!=2 && meshDim!=3)
5941 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : MeshDimension must be equal to 2 or 3 !");
5942 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
5944 int nbOfCells=getNumberOfCells();
5945 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
5946 arr->alloc(nbOfCells,1);
5947 double *pt=arr->getPointer();
5948 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
5949 const int *conn=_nodal_connec->getConstPointer();
5950 const int *connI=_nodal_connec_index->getConstPointer();
5951 const double *coo=_coords->getConstPointer();
5953 for(int i=0;i<nbOfCells;i++,pt++)
5955 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
5958 case INTERP_KERNEL::NORM_TRI3:
5960 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
5961 *pt=INTERP_KERNEL::triEdgeRatio(tmp);
5964 case INTERP_KERNEL::NORM_QUAD4:
5966 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5967 *pt=INTERP_KERNEL::quadEdgeRatio(tmp);
5970 case INTERP_KERNEL::NORM_TETRA4:
5972 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
5973 *pt=INTERP_KERNEL::tetraEdgeRatio(tmp);
5977 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getEdgeRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
5979 conn+=connI[i+1]-connI[i];
5981 ret->setName("EdgeRatio");
5982 ret->synchronizeTimeWithSupport();
5987 * Creates a new MEDCouplingFieldDouble holding Aspect Ratio values of all
5988 * cells. Currently cells of the following types are treated:
5989 * INTERP_KERNEL::NORM_TRI3, INTERP_KERNEL::NORM_QUAD4 and INTERP_KERNEL::NORM_TETRA4.
5990 * For a cell of other type an exception is thrown.
5991 * Space dimension of a 2D mesh can be either 2 or 3.
5992 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
5993 * cells and one time, lying on \a this mesh. The caller is to delete this
5994 * field using decrRef() as it is no more needed.
5995 * \throw If the coordinates array is not set.
5996 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
5997 * \throw If the connectivity data array has more than one component.
5998 * \throw If the connectivity data array has a named component.
5999 * \throw If the connectivity index data array has more than one component.
6000 * \throw If the connectivity index data array has a named component.
6001 * \throw If \a this->getMeshDimension() is neither 2 nor 3.
6002 * \throw If \a this->getSpaceDimension() is neither 2 nor 3.
6003 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6005 MEDCouplingFieldDouble *MEDCouplingUMesh::getAspectRatioField() const throw(INTERP_KERNEL::Exception)
6008 int spaceDim=getSpaceDimension();
6009 int meshDim=getMeshDimension();
6010 if(spaceDim!=2 && spaceDim!=3)
6011 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : SpaceDimension must be equal to 2 or 3 !");
6012 if(meshDim!=2 && meshDim!=3)
6013 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : MeshDimension must be equal to 2 or 3 !");
6014 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6016 int nbOfCells=getNumberOfCells();
6017 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6018 arr->alloc(nbOfCells,1);
6019 double *pt=arr->getPointer();
6020 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6021 const int *conn=_nodal_connec->getConstPointer();
6022 const int *connI=_nodal_connec_index->getConstPointer();
6023 const double *coo=_coords->getConstPointer();
6025 for(int i=0;i<nbOfCells;i++,pt++)
6027 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6030 case INTERP_KERNEL::NORM_TRI3:
6032 FillInCompact3DMode(spaceDim,3,conn+1,coo,tmp);
6033 *pt=INTERP_KERNEL::triAspectRatio(tmp);
6036 case INTERP_KERNEL::NORM_QUAD4:
6038 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6039 *pt=INTERP_KERNEL::quadAspectRatio(tmp);
6042 case INTERP_KERNEL::NORM_TETRA4:
6044 FillInCompact3DMode(spaceDim,4,conn+1,coo,tmp);
6045 *pt=INTERP_KERNEL::tetraAspectRatio(tmp);
6049 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getAspectRatioField : A cell with not manged type (NORM_TRI3, NORM_QUAD4 and NORM_TETRA4) has been detected !");
6051 conn+=connI[i+1]-connI[i];
6053 ret->setName("AspectRatio");
6054 ret->synchronizeTimeWithSupport();
6059 * Creates a new MEDCouplingFieldDouble holding Warping factor values of all
6060 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6061 * treated: INTERP_KERNEL::NORM_QUAD4.
6062 * For a cell of other type an exception is thrown.
6063 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6064 * cells and one time, lying on \a this mesh. The caller is to delete this
6065 * field using decrRef() as it is no more needed.
6066 * \throw If the coordinates array is not set.
6067 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6068 * \throw If the connectivity data array has more than one component.
6069 * \throw If the connectivity data array has a named component.
6070 * \throw If the connectivity index data array has more than one component.
6071 * \throw If the connectivity index data array has a named component.
6072 * \throw If \a this->getMeshDimension() != 2.
6073 * \throw If \a this->getSpaceDimension() != 3.
6074 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6076 MEDCouplingFieldDouble *MEDCouplingUMesh::getWarpField() const throw(INTERP_KERNEL::Exception)
6079 int spaceDim=getSpaceDimension();
6080 int meshDim=getMeshDimension();
6082 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : SpaceDimension must be equal to 3 !");
6084 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : MeshDimension must be equal to 2 !");
6085 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6087 int nbOfCells=getNumberOfCells();
6088 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6089 arr->alloc(nbOfCells,1);
6090 double *pt=arr->getPointer();
6091 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6092 const int *conn=_nodal_connec->getConstPointer();
6093 const int *connI=_nodal_connec_index->getConstPointer();
6094 const double *coo=_coords->getConstPointer();
6096 for(int i=0;i<nbOfCells;i++,pt++)
6098 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6101 case INTERP_KERNEL::NORM_QUAD4:
6103 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6104 *pt=INTERP_KERNEL::quadWarp(tmp);
6108 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getWarpField : A cell with not manged type (NORM_QUAD4) has been detected !");
6110 conn+=connI[i+1]-connI[i];
6112 ret->setName("Warp");
6113 ret->synchronizeTimeWithSupport();
6119 * Creates a new MEDCouplingFieldDouble holding Skew factor values of all
6120 * cells of \a this 2D mesh in 3D space. Currently cells of the following types are
6121 * treated: INTERP_KERNEL::NORM_QUAD4.
6122 * For a cell of other type an exception is thrown.
6123 * \return MEDCouplingFieldDouble * - a new instance of MEDCouplingFieldDouble on
6124 * cells and one time, lying on \a this mesh. The caller is to delete this
6125 * field using decrRef() as it is no more needed.
6126 * \throw If the coordinates array is not set.
6127 * \throw If \a this mesh contains elements of dimension different from the mesh dimension.
6128 * \throw If the connectivity data array has more than one component.
6129 * \throw If the connectivity data array has a named component.
6130 * \throw If the connectivity index data array has more than one component.
6131 * \throw If the connectivity index data array has a named component.
6132 * \throw If \a this->getMeshDimension() != 2.
6133 * \throw If \a this->getSpaceDimension() != 3.
6134 * \throw If \a this mesh includes cells of type different from the ones enumerated above.
6136 MEDCouplingFieldDouble *MEDCouplingUMesh::getSkewField() const throw(INTERP_KERNEL::Exception)
6139 int spaceDim=getSpaceDimension();
6140 int meshDim=getMeshDimension();
6142 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : SpaceDimension must be equal to 3 !");
6144 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : MeshDimension must be equal to 2 !");
6145 MEDCouplingAutoRefCountObjectPtr<MEDCouplingFieldDouble> ret=MEDCouplingFieldDouble::New(ON_CELLS,ONE_TIME);
6147 int nbOfCells=getNumberOfCells();
6148 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> arr=DataArrayDouble::New();
6149 arr->alloc(nbOfCells,1);
6150 double *pt=arr->getPointer();
6151 ret->setArray(arr);//In case of throw to avoid mem leaks arr will be used after decrRef.
6152 const int *conn=_nodal_connec->getConstPointer();
6153 const int *connI=_nodal_connec_index->getConstPointer();
6154 const double *coo=_coords->getConstPointer();
6156 for(int i=0;i<nbOfCells;i++,pt++)
6158 INTERP_KERNEL::NormalizedCellType t=(INTERP_KERNEL::NormalizedCellType)*conn;
6161 case INTERP_KERNEL::NORM_QUAD4:
6163 FillInCompact3DMode(3,4,conn+1,coo,tmp);
6164 *pt=INTERP_KERNEL::quadSkew(tmp);
6168 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::getSkewField : A cell with not manged type (NORM_QUAD4) has been detected !");
6170 conn+=connI[i+1]-connI[i];
6172 ret->setName("Skew");
6173 ret->synchronizeTimeWithSupport();
6178 * This method aggregate the bbox of each cell and put it into bbox parameter.
6180 * \return DataArrayDouble * - newly created object (to be managed by the caller) \a this number of cells tuples and 2*spacedim components.
6182 * \throw If \a this is not fully set (coordinates and connectivity).
6183 * \throw If a cell in \a this has no valid nodeId.
6185 DataArrayDouble *MEDCouplingUMesh::getBoundingBoxForBBTree() const
6187 checkFullyDefined();
6188 int spaceDim(getSpaceDimension()),nbOfCells(getNumberOfCells()),nbOfNodes(getNumberOfNodes());
6189 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret(DataArrayDouble::New()); ret->alloc(nbOfCells,2*spaceDim);
6190 double *bbox(ret->getPointer());
6191 for(int i=0;i<nbOfCells*spaceDim;i++)
6193 bbox[2*i]=std::numeric_limits<double>::max();
6194 bbox[2*i+1]=-std::numeric_limits<double>::max();
6196 const double *coordsPtr(_coords->getConstPointer());
6197 const int *conn(_nodal_connec->getConstPointer()),*connI(_nodal_connec_index->getConstPointer());
6198 for(int i=0;i<nbOfCells;i++)
6200 int offset=connI[i]+1;
6201 int nbOfNodesForCell(connI[i+1]-offset),kk(0);
6202 for(int j=0;j<nbOfNodesForCell;j++)
6204 int nodeId=conn[offset+j];
6205 if(nodeId>=0 && nodeId<nbOfNodes)
6207 for(int k=0;k<spaceDim;k++)
6209 bbox[2*spaceDim*i+2*k]=std::min(bbox[2*spaceDim*i+2*k],coordsPtr[spaceDim*nodeId+k]);
6210 bbox[2*spaceDim*i+2*k+1]=std::max(bbox[2*spaceDim*i+2*k+1],coordsPtr[spaceDim*nodeId+k]);
6217 std::ostringstream oss; oss << "MEDCouplingUMesh::getBoundingBoxForBBTree : cell #" << i << " contains no valid nodeId !";
6218 throw INTERP_KERNEL::Exception(oss.str().c_str());
6226 namespace ParaMEDMEMImpl
6231 ConnReader(const int *c, int val):_conn(c),_val(val) { }
6232 bool operator() (const int& pos) { return _conn[pos]!=_val; }
6241 ConnReader2(const int *c, int val):_conn(c),_val(val) { }
6242 bool operator() (const int& pos) { return _conn[pos]==_val; }
6252 * This method expects that \a this is sorted by types. If not an exception will be thrown.
6253 * This method returns in the same format as code (see MEDCouplingUMesh::checkTypeConsistencyAndContig or MEDCouplingUMesh::splitProfilePerType) how
6254 * \a this is composed in cell types.
6255 * The returned array is of size 3*n where n is the number of different types present in \a this.
6256 * For every k in [0,n] ret[3*k+2]==-1 because it has no sense here.
6257 * This parameter is kept only for compatibility with other methode listed above.
6259 std::vector<int> MEDCouplingUMesh::getDistributionOfTypes() const throw(INTERP_KERNEL::Exception)
6261 checkConnectivityFullyDefined();
6262 const int *conn=_nodal_connec->getConstPointer();
6263 const int *connI=_nodal_connec_index->getConstPointer();
6264 const int *work=connI;
6265 int nbOfCells=getNumberOfCells();
6266 std::size_t n=getAllTypes().size();
6267 std::vector<int> ret(3*n,-1); //ret[3*k+2]==-1 because it has no sense here
6268 std::set<INTERP_KERNEL::NormalizedCellType> types;
6269 for(std::size_t i=0;work!=connI+nbOfCells;i++)
6271 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn[*work];
6272 if(types.find(typ)!=types.end())
6274 std::ostringstream oss; oss << "MEDCouplingUMesh::getDistributionOfTypes : Type " << INTERP_KERNEL::CellModel::GetCellModel(typ).getRepr();
6275 oss << " is not contiguous !";
6276 throw INTERP_KERNEL::Exception(oss.str().c_str());
6280 const int *work2=std::find_if(work+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,typ));
6281 ret[3*i+1]=(int)std::distance(work,work2);
6288 * This method is used to check that this has contiguous cell type in same order than described in \a code.
6289 * only for types cell, type node is not managed.
6290 * Format of \a code is the following. \a code should be of size 3*n and non empty. If not an exception is thrown.
6291 * foreach k in [0,n) on 3*k pos represent the geometric type and 3*k+1 number of elements of type 3*k.
6292 * 3*k+2 refers if different from -1 the pos in 'idsPerType' to get the corresponding array.
6293 * If 2 or more same geometric type is in \a code and exception is thrown too.
6295 * This method firstly checks
6296 * If it exists k so that 3*k geometric type is not in geometric types of this an exception will be thrown.
6297 * If it exists k so that 3*k geometric type exists but the number of consecutive cell types does not match,
6298 * an exception is thrown too.
6300 * If all geometric types in \a code are exactly those in \a this null pointer is returned.
6301 * If it exists a geometric type in \a this \b not in \a code \b no exception is thrown
6302 * and a DataArrayInt instance is returned that the user has the responsability to deallocate.
6304 DataArrayInt *MEDCouplingUMesh::checkTypeConsistencyAndContig(const std::vector<int>& code, const std::vector<const DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6307 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code is empty, should not !");
6308 std::size_t sz=code.size();
6311 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code size is NOT %3 !");
6312 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6314 bool isNoPflUsed=true;
6315 for(std::size_t i=0;i<n;i++)
6316 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)code[3*i])==types.end())
6318 types.push_back((INTERP_KERNEL::NormalizedCellType)code[3*i]);
6320 if(_types.find((INTERP_KERNEL::NormalizedCellType)code[3*i])==_types.end())
6321 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : expected geo types not in this !");
6322 isNoPflUsed=isNoPflUsed && (code[3*i+2]==-1);
6325 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : code contains duplication of types in unstructured mesh !");
6328 if(!checkConsecutiveCellTypesAndOrder(&types[0],&types[0]+types.size()))
6329 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : non contiguous type !");
6330 if(types.size()==_types.size())
6333 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
6335 int *retPtr=ret->getPointer();
6336 const int *connI=_nodal_connec_index->getConstPointer();
6337 const int *conn=_nodal_connec->getConstPointer();
6338 int nbOfCells=getNumberOfCells();
6341 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator it=types.begin();it!=types.end();it++,kk++)
6343 i=std::find_if(i,connI+nbOfCells,ParaMEDMEMImpl::ConnReader2(conn,(int)(*it)));
6344 int offset=(int)std::distance(connI,i);
6345 const int *j=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)(*it)));
6346 int nbOfCellsOfCurType=(int)std::distance(i,j);
6347 if(code[3*kk+2]==-1)
6348 for(int k=0;k<nbOfCellsOfCurType;k++)
6352 int idInIdsPerType=code[3*kk+2];
6353 if(idInIdsPerType>=0 && idInIdsPerType<(int)idsPerType.size())
6355 const DataArrayInt *zePfl=idsPerType[idInIdsPerType];
6358 zePfl->checkAllocated();
6359 if(zePfl->getNumberOfComponents()==1)
6361 for(const int *k=zePfl->begin();k!=zePfl->end();k++,retPtr++)
6363 if(*k>=0 && *k<nbOfCellsOfCurType)
6364 *retPtr=(*k)+offset;
6367 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : the section " << kk << " points to the profile #" << idInIdsPerType;
6368 oss << ", and this profile contains a value " << *k << " should be in [0," << nbOfCellsOfCurType << ") !";
6369 throw INTERP_KERNEL::Exception(oss.str().c_str());
6374 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of a profile with nb of compo != 1 !");
6377 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::checkTypeConsistencyAndContig : presence of null profile !");
6381 std::ostringstream oss; oss << "MEDCouplingUMesh::checkTypeConsistencyAndContig : at section " << kk << " of code it points to the array #" << idInIdsPerType;
6382 oss << " should be in [0," << idsPerType.size() << ") !";
6383 throw INTERP_KERNEL::Exception(oss.str().c_str());
6392 * This method makes the hypothesis that \at this is sorted by type. If not an exception will be thrown.
6393 * 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.
6394 * 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.
6395 * This method has 1 input \a profile and 3 outputs \a code \a idsInPflPerType and \a idsPerType.
6397 * \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.
6398 * \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,
6399 * \a idsInPflPerType[i] stores the tuple ids in \a profile that correspond to the geometric type code[3*i+0]
6400 * \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.
6401 * This vector can be empty in case of all geometric type cells are fully covered in ascending in the given input \a profile.
6402 * \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
6404 void MEDCouplingUMesh::splitProfilePerType(const DataArrayInt *profile, std::vector<int>& code, std::vector<DataArrayInt *>& idsInPflPerType, std::vector<DataArrayInt *>& idsPerType) const throw(INTERP_KERNEL::Exception)
6407 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile is NULL !");
6408 if(profile->getNumberOfComponents()!=1)
6409 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : input profile should have exactly one component !");
6410 checkConnectivityFullyDefined();
6411 const int *conn=_nodal_connec->getConstPointer();
6412 const int *connI=_nodal_connec_index->getConstPointer();
6413 int nbOfCells=getNumberOfCells();
6414 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6415 std::vector<int> typeRangeVals(1);
6416 for(const int *i=connI;i!=connI+nbOfCells;)
6418 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6419 if(std::find(types.begin(),types.end(),curType)!=types.end())
6421 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::splitProfilePerType : current mesh is not sorted by type !");
6423 types.push_back(curType);
6424 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6425 typeRangeVals.push_back((int)std::distance(connI,i));
6428 DataArrayInt *castArr=0,*rankInsideCast=0,*castsPresent=0;
6429 profile->splitByValueRange(&typeRangeVals[0],&typeRangeVals[0]+typeRangeVals.size(),castArr,rankInsideCast,castsPresent);
6430 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=castArr;
6431 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=rankInsideCast;
6432 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp2=castsPresent;
6434 int nbOfCastsFinal=castsPresent->getNumberOfTuples();
6435 code.resize(3*nbOfCastsFinal);
6436 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsInPflPerType2;
6437 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > idsPerType2;
6438 for(int i=0;i<nbOfCastsFinal;i++)
6440 int castId=castsPresent->getIJ(i,0);
6441 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp3=castArr->getIdsEqual(castId);
6442 idsInPflPerType2.push_back(tmp3);
6443 code[3*i]=(int)types[castId];
6444 code[3*i+1]=tmp3->getNumberOfTuples();
6445 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp4=rankInsideCast->selectByTupleId(tmp3->getConstPointer(),tmp3->getConstPointer()+tmp3->getNumberOfTuples());
6446 if(tmp4->getNumberOfTuples()!=typeRangeVals[castId+1]-typeRangeVals[castId] || !tmp4->isIdentity())
6448 tmp4->copyStringInfoFrom(*profile);
6449 idsPerType2.push_back(tmp4);
6450 code[3*i+2]=(int)idsPerType2.size()-1;
6457 std::size_t sz2=idsInPflPerType2.size();
6458 idsInPflPerType.resize(sz2);
6459 for(std::size_t i=0;i<sz2;i++)
6461 DataArrayInt *locDa=idsInPflPerType2[i];
6463 idsInPflPerType[i]=locDa;
6465 std::size_t sz=idsPerType2.size();
6466 idsPerType.resize(sz);
6467 for(std::size_t i=0;i<sz;i++)
6469 DataArrayInt *locDa=idsPerType2[i];
6471 idsPerType[i]=locDa;
6476 * This method is here too emulate the MEDMEM behaviour on BDC (buildDescendingConnectivity). Hoping this method becomes deprecated very soon.
6477 * This method make the assumption that \a this and 'nM1LevMesh' mesh lyies on same coords (same pointer) as MED and MEDMEM does.
6478 * The following equality should be verified 'nM1LevMesh->getMeshDimension()==this->getMeshDimension()-1'
6479 * 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.
6481 MEDCouplingUMesh *MEDCouplingUMesh::emulateMEDMEMBDC(const MEDCouplingUMesh *nM1LevMesh, DataArrayInt *desc, DataArrayInt *descIndx, DataArrayInt *&revDesc, DataArrayInt *&revDescIndx, DataArrayInt *& nM1LevMeshIds, DataArrayInt *&meshnM1Old2New) const throw(INTERP_KERNEL::Exception)
6483 checkFullyDefined();
6484 nM1LevMesh->checkFullyDefined();
6485 if(getMeshDimension()-1!=nM1LevMesh->getMeshDimension())
6486 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : The mesh passed as first argument should have a meshDim equal to this->getMeshDimension()-1 !" );
6487 if(_coords!=nM1LevMesh->getCoords())
6488 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::emulateMEDMEMBDC : 'this' and mesh in first argument should share the same coords : Use tryToShareSameCoords method !");
6489 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp0=DataArrayInt::New();
6490 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1=DataArrayInt::New();
6491 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret1=buildDescendingConnectivity(desc,descIndx,tmp0,tmp1);
6492 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret0=ret1->sortCellsInMEDFileFrmt();
6493 desc->transformWithIndArr(ret0->getConstPointer(),ret0->getConstPointer()+ret0->getNbOfElems());
6494 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=MEDCouplingUMesh::New();
6495 tmp->setConnectivity(tmp0,tmp1);
6496 tmp->renumberCells(ret0->getConstPointer(),false);
6497 revDesc=tmp->getNodalConnectivity();
6498 revDescIndx=tmp->getNodalConnectivityIndex();
6499 DataArrayInt *ret=0;
6500 if(!ret1->areCellsIncludedIn(nM1LevMesh,2,ret))
6503 ret->getMaxValue(tmp2);
6505 std::ostringstream oss; oss << "MEDCouplingUMesh::emulateMEDMEMBDC : input N-1 mesh present a cell not in descending mesh ... Id of cell is " << tmp2 << " !";
6506 throw INTERP_KERNEL::Exception(oss.str().c_str());
6511 revDescIndx->incrRef();
6514 meshnM1Old2New=ret0;
6519 * Permutes the nodal connectivity arrays so that the cells are sorted by type, which is
6520 * necessary for writing the mesh to MED file. Additionally returns a permutation array
6521 * in "Old to New" mode.
6522 * \return DataArrayInt * - a new instance of DataArrayInt. The caller is to delete
6523 * this array using decrRef() as it is no more needed.
6524 * \throw If the nodal connectivity of cells is not defined.
6526 DataArrayInt *MEDCouplingUMesh::sortCellsInMEDFileFrmt() throw(INTERP_KERNEL::Exception)
6528 checkConnectivityFullyDefined();
6529 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=getRenumArrForMEDFileFrmt();
6530 renumberCells(ret->getConstPointer(),false);
6535 * This methods checks that cells are sorted by their types.
6536 * This method makes asumption (no check) that connectivity is correctly set before calling.
6538 bool MEDCouplingUMesh::checkConsecutiveCellTypes() const
6540 checkFullyDefined();
6541 const int *conn=_nodal_connec->getConstPointer();
6542 const int *connI=_nodal_connec_index->getConstPointer();
6543 int nbOfCells=getNumberOfCells();
6544 std::set<INTERP_KERNEL::NormalizedCellType> types;
6545 for(const int *i=connI;i!=connI+nbOfCells;)
6547 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6548 if(types.find(curType)!=types.end())
6550 types.insert(curType);
6551 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6557 * This method is a specialization of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder method that is called here.
6558 * The geometric type order is specified by MED file.
6560 * \sa MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder
6562 bool MEDCouplingUMesh::checkConsecutiveCellTypesForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6564 return checkConsecutiveCellTypesAndOrder(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6568 * This method performs the same job as checkConsecutiveCellTypes except that the order of types sequence is analyzed to check
6569 * that the order is specified in array defined by [ \a orderBg , \a orderEnd ).
6570 * If there is some geo types in \a this \b NOT in [ \a orderBg, \a orderEnd ) it is OK (return true) if contiguous.
6571 * If there is some geo types in [ \a orderBg, \a orderEnd ) \b NOT in \a this it is OK too (return true) if contiguous.
6573 bool MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const
6575 checkFullyDefined();
6576 const int *conn=_nodal_connec->getConstPointer();
6577 const int *connI=_nodal_connec_index->getConstPointer();
6578 int nbOfCells=getNumberOfCells();
6582 std::set<INTERP_KERNEL::NormalizedCellType> sg;
6583 for(const int *i=connI;i!=connI+nbOfCells;)
6585 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6586 const INTERP_KERNEL::NormalizedCellType *isTypeExists=std::find(orderBg,orderEnd,curType);
6587 if(isTypeExists!=orderEnd)
6589 int pos=(int)std::distance(orderBg,isTypeExists);
6593 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6597 if(sg.find(curType)==sg.end())
6599 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6610 * This method returns 2 newly allocated DataArrayInt instances. The first is an array of size 'this->getNumberOfCells()' with one component,
6611 * 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
6612 * 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'.
6614 DataArrayInt *MEDCouplingUMesh::getLevArrPerCellTypes(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd, DataArrayInt *&nbPerType) const throw(INTERP_KERNEL::Exception)
6616 checkConnectivityFullyDefined();
6617 int nbOfCells=getNumberOfCells();
6618 const int *conn=_nodal_connec->getConstPointer();
6619 const int *connI=_nodal_connec_index->getConstPointer();
6620 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=DataArrayInt::New();
6621 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpb=DataArrayInt::New();
6622 tmpa->alloc(nbOfCells,1);
6623 tmpb->alloc((int)std::distance(orderBg,orderEnd),1);
6624 tmpb->fillWithZero();
6625 int *tmp=tmpa->getPointer();
6626 int *tmp2=tmpb->getPointer();
6627 for(const int *i=connI;i!=connI+nbOfCells;i++)
6629 const INTERP_KERNEL::NormalizedCellType *where=std::find(orderBg,orderEnd,(INTERP_KERNEL::NormalizedCellType)conn[*i]);
6632 int pos=(int)std::distance(orderBg,where);
6634 tmp[std::distance(connI,i)]=pos;
6638 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)conn[*i]);
6639 std::ostringstream oss; oss << "MEDCouplingUMesh::getLevArrPerCellTypes : Cell #" << std::distance(connI,i);
6640 oss << " has a type " << cm.getRepr() << " not in input array of type !";
6641 throw INTERP_KERNEL::Exception(oss.str().c_str());
6644 nbPerType=tmpb.retn();
6649 * This method behaves exactly as MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec but the order is those defined in MED file spec.
6651 * \return a new object containing the old to new correspondance.
6653 * \sa MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec, MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6655 DataArrayInt *MEDCouplingUMesh::getRenumArrForMEDFileFrmt() const throw(INTERP_KERNEL::Exception)
6657 return getRenumArrForConsecutiveCellTypesSpec(MEDMEM_ORDER,MEDMEM_ORDER+N_MEDMEM_ORDER);
6661 * 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.
6662 * This method returns an array of size getNumberOfCells() that gives a renumber array old2New that can be used as input of MEDCouplingMesh::renumberCells.
6663 * The mesh after this call to MEDCouplingMesh::renumberCells will pass the test of MEDCouplingUMesh::checkConsecutiveCellTypesAndOrder with the same inputs.
6664 * The returned array minimizes the permutations that is to say the order of cells inside same geometric type remains the same.
6666 DataArrayInt *MEDCouplingUMesh::getRenumArrForConsecutiveCellTypesSpec(const INTERP_KERNEL::NormalizedCellType *orderBg, const INTERP_KERNEL::NormalizedCellType *orderEnd) const throw(INTERP_KERNEL::Exception)
6668 DataArrayInt *nbPerType=0;
6669 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmpa=getLevArrPerCellTypes(orderBg,orderEnd,nbPerType);
6670 nbPerType->decrRef();
6671 return tmpa->buildPermArrPerLevel();
6675 * This method reorganize the cells of \a this so that the cells with same geometric types are put together.
6676 * The number of cells remains unchanged after the call of this method.
6677 * This method tries to minimizes the number of needed permutations. So, this method behaves not exactly as
6678 * MEDCouplingUMesh::sortCellsInMEDFileFrmt.
6680 * \return the array giving the correspondance old to new.
6682 DataArrayInt *MEDCouplingUMesh::rearrange2ConsecutiveCellTypes()
6684 checkFullyDefined();
6686 const int *conn=_nodal_connec->getConstPointer();
6687 const int *connI=_nodal_connec_index->getConstPointer();
6688 int nbOfCells=getNumberOfCells();
6689 std::vector<INTERP_KERNEL::NormalizedCellType> types;
6690 for(const int *i=connI;i!=connI+nbOfCells && (types.size()!=_types.size());)
6691 if(std::find(types.begin(),types.end(),(INTERP_KERNEL::NormalizedCellType)conn[*i])==types.end())
6693 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6694 types.push_back(curType);
6695 for(i++;i!=connI+nbOfCells && (INTERP_KERNEL::NormalizedCellType)conn[*i]==curType;i++);
6697 DataArrayInt *ret=DataArrayInt::New();
6698 ret->alloc(nbOfCells,1);
6699 int *retPtr=ret->getPointer();
6700 std::fill(retPtr,retPtr+nbOfCells,-1);
6702 for(std::vector<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6704 for(const int *i=connI;i!=connI+nbOfCells;i++)
6705 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6706 retPtr[std::distance(connI,i)]=newCellId++;
6708 renumberCells(retPtr,false);
6713 * This method splits \a this into as mush as untructured meshes that consecutive set of same type cells.
6714 * So this method has typically a sense if MEDCouplingUMesh::checkConsecutiveCellTypes has a sense.
6715 * This method makes asumption that connectivity is correctly set before calling.
6717 std::vector<MEDCouplingUMesh *> MEDCouplingUMesh::splitByType() const
6719 checkConnectivityFullyDefined();
6720 const int *conn=_nodal_connec->getConstPointer();
6721 const int *connI=_nodal_connec_index->getConstPointer();
6722 int nbOfCells=getNumberOfCells();
6723 std::vector<MEDCouplingUMesh *> ret;
6724 for(const int *i=connI;i!=connI+nbOfCells;)
6726 INTERP_KERNEL::NormalizedCellType curType=(INTERP_KERNEL::NormalizedCellType)conn[*i];
6727 int beginCellId=(int)std::distance(connI,i);
6728 i=std::find_if(i+1,connI+nbOfCells,ParaMEDMEMImpl::ConnReader(conn,(int)curType));
6729 int endCellId=(int)std::distance(connI,i);
6730 int sz=endCellId-beginCellId;
6731 int *cells=new int[sz];
6732 for(int j=0;j<sz;j++)
6733 cells[j]=beginCellId+j;
6734 MEDCouplingUMesh *m=(MEDCouplingUMesh *)buildPartOfMySelf(cells,cells+sz,true);
6742 * This method performs the opposite operation than those in MEDCoupling1SGTUMesh::buildUnstructured.
6743 * If \a this is a single geometric type unstructured mesh, it will be converted into a more compact data structure,
6744 * MEDCoupling1GTUMesh instance. The returned instance will aggregate the same DataArrayDouble instance of coordinates than \a this.
6746 * \return a newly allocated instance, that the caller must manage.
6747 * \throw If \a this contains more than one geometric type.
6748 * \throw If the nodal connectivity of \a this is not fully defined.
6749 * \throw If the internal data is not coherent.
6751 MEDCoupling1GTUMesh *MEDCouplingUMesh::convertIntoSingleGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6753 checkConnectivityFullyDefined();
6754 if(_types.size()!=1)
6755 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6756 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6757 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1GTUMesh> ret=MEDCoupling1GTUMesh::New(getName().c_str(),typ);
6758 ret->setCoords(getCoords());
6759 MEDCoupling1SGTUMesh *retC=dynamic_cast<MEDCoupling1SGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6762 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=convertNodalConnectivityToStaticGeoTypeMesh();
6763 retC->setNodalConnectivity(c);
6767 MEDCoupling1DGTUMesh *retD=dynamic_cast<MEDCoupling1DGTUMesh *>((MEDCoupling1GTUMesh*)ret);
6769 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertIntoSingleGeoTypeMesh : Internal error !");
6770 DataArrayInt *c=0,*ci=0;
6771 convertNodalConnectivityToDynamicGeoTypeMesh(c,ci);
6772 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cs(c),cis(ci);
6773 retD->setNodalConnectivity(cs,cis);
6778 DataArrayInt *MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh() const throw(INTERP_KERNEL::Exception)
6780 checkConnectivityFullyDefined();
6781 if(_types.size()!=1)
6782 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6783 INTERP_KERNEL::NormalizedCellType typ=*_types.begin();
6784 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
6787 std::ostringstream oss; oss << "MEDCouplingUMesh::convertNodalConnectivityToStaticGeoTypeMesh : this contains a single geo type (" << cm.getRepr() << ") but ";
6788 oss << "this type is dynamic ! Only static geometric type is possible for that type ! call convertNodalConnectivityToDynamicGeoTypeMesh instead !";
6789 throw INTERP_KERNEL::Exception(oss.str().c_str());
6791 int nbCells=getNumberOfCells();
6793 int nbNodesPerCell=(int)cm.getNumberOfNodes();
6794 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connOut=DataArrayInt::New(); connOut->alloc(nbCells*nbNodesPerCell,1);
6795 int *outPtr=connOut->getPointer();
6796 const int *conn=_nodal_connec->begin();
6797 const int *connI=_nodal_connec_index->begin();
6799 for(int i=0;i<nbCells;i++,connI++)
6801 if(conn[connI[0]]==typi && connI[1]-connI[0]==nbNodesPerCell)
6802 outPtr=std::copy(conn+connI[0]+1,conn+connI[1],outPtr);
6805 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 << ") !";
6806 throw INTERP_KERNEL::Exception(oss.str().c_str());
6809 return connOut.retn();
6812 void MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh(DataArrayInt *&nodalConn, DataArrayInt *&nodalConnIndex) const throw(INTERP_KERNEL::Exception)
6814 static const char msg0[]="MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : nodal connectivity in this are invalid ! Call checkCoherency2 !";
6815 checkConnectivityFullyDefined();
6816 if(_types.size()!=1)
6817 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::convertNodalConnectivityToDynamicGeoTypeMesh : current mesh does not contain exactly one geometric type !");
6818 int nbCells=getNumberOfCells(),lgth=_nodal_connec->getNumberOfTuples();
6820 throw INTERP_KERNEL::Exception(msg0);
6821 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c(DataArrayInt::New()),ci(DataArrayInt::New());
6822 c->alloc(lgth-nbCells,1); ci->alloc(nbCells+1,1);
6823 int *cp(c->getPointer()),*cip(ci->getPointer());
6824 const int *incp(_nodal_connec->begin()),*incip(_nodal_connec_index->begin());
6826 for(int i=0;i<nbCells;i++,cip++,incip++)
6828 int strt(incip[0]+1),stop(incip[1]);//+1 to skip geo type
6829 int delta(stop-strt);
6832 if((strt>=0 && strt<lgth) && (stop>=0 && stop<=lgth))
6833 cp=std::copy(incp+strt,incp+stop,cp);
6835 throw INTERP_KERNEL::Exception(msg0);
6838 throw INTERP_KERNEL::Exception(msg0);
6839 cip[1]=cip[0]+delta;
6841 nodalConn=c.retn(); nodalConnIndex=ci.retn();
6845 * This method takes in input a vector of MEDCouplingUMesh instances lying on the same coordinates with same mesh dimensions.
6846 * Each mesh in \b ms must be sorted by type with the same order (typically using MEDCouplingUMesh::sortCellsInMEDFileFrmt).
6847 * This method is particulary useful for MED file interaction. It allows to aggregate several meshes and keeping the type sorting
6848 * and the track of the permutation by chunk of same geotype cells to retrieve it. The traditional formats old2new and new2old
6849 * are not used here to avoid the build of big permutation array.
6851 * \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
6852 * those specified in MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6853 * \param [out] szOfCellGrpOfSameType is a newly allocated DataArrayInt instance whose number of tuples is equal to the number of chunks of same geotype
6854 * in all meshes in \b ms. The accumulation of all values of this array is equal to the number of cells of returned mesh.
6855 * \param [out] idInMsOfCellGrpOfSameType is a newly allocated DataArrayInt instance having the same size than \b szOfCellGrpOfSameType. This
6856 * output array gives for each chunck of same type the corresponding mesh id in \b ms.
6857 * \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
6858 * is sorted by type following the geo cell types order of MEDCouplingUMesh::sortCellsInMEDFileFrmt method.
6860 MEDCouplingUMesh *MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& ms,
6861 DataArrayInt *&szOfCellGrpOfSameType,
6862 DataArrayInt *&idInMsOfCellGrpOfSameType) throw(INTERP_KERNEL::Exception)
6864 std::vector<const MEDCouplingUMesh *> ms2;
6865 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms.begin();it!=ms.end();it++)
6868 (*it)->checkConnectivityFullyDefined();
6872 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : input vector is empty !");
6873 const DataArrayDouble *refCoo=ms2[0]->getCoords();
6874 int meshDim=ms2[0]->getMeshDimension();
6875 std::vector<const MEDCouplingUMesh *> m1ssm;
6876 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmAuto;
6878 std::vector<const MEDCouplingUMesh *> m1ssmSingle;
6879 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > m1ssmSingleAuto;
6881 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret1(DataArrayInt::New()),ret2(DataArrayInt::New());
6882 ret1->alloc(0,1); ret2->alloc(0,1);
6883 for(std::vector<const MEDCouplingUMesh *>::const_iterator it=ms2.begin();it!=ms2.end();it++,rk++)
6885 if(meshDim!=(*it)->getMeshDimension())
6886 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshdims mismatch !");
6887 if(refCoo!=(*it)->getCoords())
6888 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AggregateSortedByTypeMeshesOnSameCoords : meshes are not shared by a single coordinates coords !");
6889 std::vector<MEDCouplingUMesh *> sp=(*it)->splitByType();
6890 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<const MEDCouplingUMesh *> >(m1ssm));
6891 std::copy(sp.begin(),sp.end(),std::back_insert_iterator< std::vector<MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > >(m1ssmAuto));
6892 for(std::vector<MEDCouplingUMesh *>::const_iterator it2=sp.begin();it2!=sp.end();it2++)
6894 MEDCouplingUMesh *singleCell=static_cast<MEDCouplingUMesh *>((*it2)->buildPartOfMySelf(&fake,&fake+1,true));
6895 m1ssmSingleAuto.push_back(singleCell);
6896 m1ssmSingle.push_back(singleCell);
6897 ret1->pushBackSilent((*it2)->getNumberOfCells()); ret2->pushBackSilent(rk);
6900 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m1ssmSingle2=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmSingle);
6901 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> renum=m1ssmSingle2->sortCellsInMEDFileFrmt();
6902 std::vector<const MEDCouplingUMesh *> m1ssmfinal(m1ssm.size());
6903 for(std::size_t i=0;i<m1ssm.size();i++)
6904 m1ssmfinal[renum->getIJ(i,0)]=m1ssm[i];
6905 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret0=MEDCouplingUMesh::MergeUMeshesOnSameCoords(m1ssmfinal);
6906 szOfCellGrpOfSameType=ret1->renumber(renum->getConstPointer());
6907 idInMsOfCellGrpOfSameType=ret2->renumber(renum->getConstPointer());
6912 * This method returns a newly created DataArrayInt instance.
6913 * This method retrieves cell ids in [ \a begin, \a end ) that have the type \a type.
6915 DataArrayInt *MEDCouplingUMesh::keepCellIdsByType(INTERP_KERNEL::NormalizedCellType type, const int *begin, const int *end) const throw(INTERP_KERNEL::Exception)
6917 checkFullyDefined();
6918 const int *conn=_nodal_connec->getConstPointer();
6919 const int *connIndex=_nodal_connec_index->getConstPointer();
6920 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(0,1);
6921 for(const int *w=begin;w!=end;w++)
6922 if((INTERP_KERNEL::NormalizedCellType)conn[connIndex[*w]]==type)
6923 ret->pushBackSilent(*w);
6928 * This method makes the assumption that da->getNumberOfTuples()<this->getNumberOfCells(). This method makes the assumption that ids contained in 'da'
6929 * are in [0:getNumberOfCells())
6931 DataArrayInt *MEDCouplingUMesh::convertCellArrayPerGeoType(const DataArrayInt *da) const throw(INTERP_KERNEL::Exception)
6933 checkFullyDefined();
6934 const int *conn=_nodal_connec->getConstPointer();
6935 const int *connI=_nodal_connec_index->getConstPointer();
6936 int nbOfCells=getNumberOfCells();
6937 std::set<INTERP_KERNEL::NormalizedCellType> types=getAllTypes();
6938 int *tmp=new int[nbOfCells];
6939 for(std::set<INTERP_KERNEL::NormalizedCellType>::const_iterator iter=types.begin();iter!=types.end();iter++)
6942 for(const int *i=connI;i!=connI+nbOfCells;i++)
6943 if((INTERP_KERNEL::NormalizedCellType)conn[*i]==(*iter))
6944 tmp[std::distance(connI,i)]=j++;
6946 DataArrayInt *ret=DataArrayInt::New();
6947 ret->alloc(da->getNumberOfTuples(),da->getNumberOfComponents());
6948 ret->copyStringInfoFrom(*da);
6949 int *retPtr=ret->getPointer();
6950 const int *daPtr=da->getConstPointer();
6951 int nbOfElems=da->getNbOfElems();
6952 for(int k=0;k<nbOfElems;k++)
6953 retPtr[k]=tmp[daPtr[k]];
6959 * This method reduced number of cells of this by keeping cells whose type is different from 'type' and if type=='type'
6960 * This method \b works \b for mesh sorted by type.
6961 * cells whose ids is in 'idsPerGeoType' array.
6962 * This method conserves coords and name of mesh.
6964 MEDCouplingUMesh *MEDCouplingUMesh::keepSpecifiedCells(INTERP_KERNEL::NormalizedCellType type, const int *idsPerGeoTypeBg, const int *idsPerGeoTypeEnd) const
6966 std::vector<int> code=getDistributionOfTypes();
6967 std::size_t nOfTypesInThis=code.size()/3;
6968 int sz=0,szOfType=0;
6969 for(std::size_t i=0;i<nOfTypesInThis;i++)
6974 szOfType=code[3*i+1];
6976 for(const int *work=idsPerGeoTypeBg;work!=idsPerGeoTypeEnd;work++)
6977 if(*work<0 || *work>=szOfType)
6979 std::ostringstream oss; oss << "MEDCouplingUMesh::keepSpecifiedCells : Request on type " << type << " at place #" << std::distance(idsPerGeoTypeBg,work) << " value " << *work;
6980 oss << ". It should be in [0," << szOfType << ") !";
6981 throw INTERP_KERNEL::Exception(oss.str().c_str());
6983 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsTokeep=DataArrayInt::New(); idsTokeep->alloc(sz+(int)std::distance(idsPerGeoTypeBg,idsPerGeoTypeEnd),1);
6984 int *idsPtr=idsTokeep->getPointer();
6986 for(std::size_t i=0;i<nOfTypesInThis;i++)
6989 for(int j=0;j<code[3*i+1];j++)
6992 idsPtr=std::transform(idsPerGeoTypeBg,idsPerGeoTypeEnd,idsPtr,std::bind2nd(std::plus<int>(),offset));
6993 offset+=code[3*i+1];
6995 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf(idsTokeep->begin(),idsTokeep->end(),true));
6996 ret->copyTinyInfoFrom(this);
7001 * This method returns a vector of size 'this->getNumberOfCells()'.
7002 * This method retrieves for each cell in \a this if it is linear (false) or quadratic(true).
7004 std::vector<bool> MEDCouplingUMesh::getQuadraticStatus() const throw(INTERP_KERNEL::Exception)
7006 int ncell=getNumberOfCells();
7007 std::vector<bool> ret(ncell);
7008 const int *cI=getNodalConnectivityIndex()->getConstPointer();
7009 const int *c=getNodalConnectivity()->getConstPointer();
7010 for(int i=0;i<ncell;i++)
7012 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)c[cI[i]];
7013 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
7014 ret[i]=cm.isQuadratic();
7020 * Returns a newly created mesh (with ref count ==1) that contains merge of \a this and \a other.
7022 MEDCouplingMesh *MEDCouplingUMesh::mergeMyselfWith(const MEDCouplingMesh *other) const
7024 if(other->getType()!=UNSTRUCTURED)
7025 throw INTERP_KERNEL::Exception("Merge of umesh only available with umesh each other !");
7026 const MEDCouplingUMesh *otherC=static_cast<const MEDCouplingUMesh *>(other);
7027 return MergeUMeshes(this,otherC);
7031 * Returns a new DataArrayDouble holding barycenters of all cells. The barycenter is
7032 * computed by averaging coordinates of cell nodes, so this method is not a right
7033 * choice for degnerated meshes (not well oriented, cells with measure close to zero).
7034 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size \a
7035 * this->getNumberOfCells() tuples per \a this->getSpaceDimension()
7036 * components. The caller is to delete this array using decrRef() as it is
7038 * \throw If the coordinates array is not set.
7039 * \throw If the nodal connectivity of cells is not defined.
7040 * \sa MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell
7042 DataArrayDouble *MEDCouplingUMesh::getBarycenterAndOwner() const
7044 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7045 int spaceDim=getSpaceDimension();
7046 int nbOfCells=getNumberOfCells();
7047 ret->alloc(nbOfCells,spaceDim);
7048 ret->copyStringInfoFrom(*getCoords());
7049 double *ptToFill=ret->getPointer();
7050 const int *nodal=_nodal_connec->getConstPointer();
7051 const int *nodalI=_nodal_connec_index->getConstPointer();
7052 const double *coor=_coords->getConstPointer();
7053 for(int i=0;i<nbOfCells;i++)
7055 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7056 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[i]+1,nodalI[i+1]-nodalI[i]-1,coor,spaceDim,ptToFill);
7063 * This method computes for each cell in \a this, the location of the iso barycenter of nodes constituting
7064 * the cell. Contrary to badly named MEDCouplingUMesh::getBarycenterAndOwner method that returns the center of inertia of the
7066 * \return a newly allocated DataArrayDouble instance that the caller has to deal with. The returned
7067 * DataArrayDouble instance will have \c this->getNumberOfCells() tuples and \c this->getSpaceDimension() components.
7069 * \sa MEDCouplingUMesh::getBarycenterAndOwner
7070 * \throw If \a this is not fully defined (coordinates and connectivity)
7071 * \throw If there is presence in nodal connectivity in \a this of node ids not in [0, \c this->getNumberOfNodes() )
7073 DataArrayDouble *MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell() const throw(INTERP_KERNEL::Exception)
7075 checkFullyDefined();
7076 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> ret=DataArrayDouble::New();
7077 int spaceDim=getSpaceDimension();
7078 int nbOfCells=getNumberOfCells();
7079 int nbOfNodes=getNumberOfNodes();
7080 ret->alloc(nbOfCells,spaceDim);
7081 double *ptToFill=ret->getPointer();
7082 const int *nodal=_nodal_connec->getConstPointer();
7083 const int *nodalI=_nodal_connec_index->getConstPointer();
7084 const double *coor=_coords->getConstPointer();
7085 for(int i=0;i<nbOfCells;i++,ptToFill+=spaceDim)
7087 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[i]];
7088 std::fill(ptToFill,ptToFill+spaceDim,0.);
7089 if(type!=INTERP_KERNEL::NORM_POLYHED)
7091 for(const int *conn=nodal+nodalI[i]+1;conn!=nodal+nodalI[i+1];conn++)
7093 if(*conn>=0 && *conn<nbOfNodes)
7094 std::transform(coor+spaceDim*conn[0],coor+spaceDim*(conn[0]+1),ptToFill,ptToFill,std::plus<double>());
7097 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of nodeId #" << *conn << " should be in [0," << nbOfNodes << ") !";
7098 throw INTERP_KERNEL::Exception(oss.str().c_str());
7101 int nbOfNodesInCell=nodalI[i+1]-nodalI[i]-1;
7102 if(nbOfNodesInCell>0)
7103 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)nbOfNodesInCell));
7106 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell #" << i << " presence of cell with no nodes !";
7107 throw INTERP_KERNEL::Exception(oss.str().c_str());
7112 std::set<int> s(nodal+nodalI[i]+1,nodal+nodalI[i+1]);
7114 for(std::set<int>::const_iterator it=s.begin();it!=s.end();it++)
7116 if(*it>=0 && *it<nbOfNodes)
7117 std::transform(coor+spaceDim*(*it),coor+spaceDim*((*it)+1),ptToFill,ptToFill,std::plus<double>());
7120 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on cell polyhedron cell #" << i << " presence of nodeId #" << *it << " should be in [0," << nbOfNodes << ") !";
7121 throw INTERP_KERNEL::Exception(oss.str().c_str());
7125 std::transform(ptToFill,ptToFill+spaceDim,ptToFill,std::bind2nd(std::multiplies<double>(),1./(double)s.size()));
7128 std::ostringstream oss; oss << "MEDCouplingUMesh::computeIsoBarycenterOfNodesPerCell : on polyhedron cell #" << i << " there are no nodes !";
7129 throw INTERP_KERNEL::Exception(oss.str().c_str());
7137 * Returns a new DataArrayDouble holding barycenters of specified cells. The
7138 * barycenter is computed by averaging coordinates of cell nodes. The cells to treat
7139 * are specified via an array of cell ids.
7140 * \warning Validity of the specified cell ids is not checked!
7141 * Valid range is [ 0, \a this->getNumberOfCells() ).
7142 * \param [in] begin - an array of cell ids of interest.
7143 * \param [in] end - the end of \a begin, i.e. a pointer to its (last+1)-th element.
7144 * \return DataArrayDouble * - a new instance of DataArrayDouble, of size ( \a
7145 * end - \a begin ) tuples per \a this->getSpaceDimension() components. The
7146 * caller is to delete this array using decrRef() as it is no more needed.
7147 * \throw If the coordinates array is not set.
7148 * \throw If the nodal connectivity of cells is not defined.
7150 * \ref cpp_mcumesh_getPartBarycenterAndOwner "Here is a C++ example".<br>
7151 * \ref py_mcumesh_getPartBarycenterAndOwner "Here is a Python example".
7153 DataArrayDouble *MEDCouplingUMesh::getPartBarycenterAndOwner(const int *begin, const int *end) const
7155 DataArrayDouble *ret=DataArrayDouble::New();
7156 int spaceDim=getSpaceDimension();
7157 int nbOfTuple=(int)std::distance(begin,end);
7158 ret->alloc(nbOfTuple,spaceDim);
7159 double *ptToFill=ret->getPointer();
7160 double *tmp=new double[spaceDim];
7161 const int *nodal=_nodal_connec->getConstPointer();
7162 const int *nodalI=_nodal_connec_index->getConstPointer();
7163 const double *coor=_coords->getConstPointer();
7164 for(const int *w=begin;w!=end;w++)
7166 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)nodal[nodalI[*w]];
7167 INTERP_KERNEL::computeBarycenter2<int,INTERP_KERNEL::ALL_C_MODE>(type,nodal+nodalI[*w]+1,nodalI[*w+1]-nodalI[*w]-1,coor,spaceDim,ptToFill);
7175 * This method expects as input a DataArrayDouble non nul instance 'da' that should be allocated. If not an exception is thrown.
7178 MEDCouplingUMesh *MEDCouplingUMesh::Build0DMeshFromCoords(DataArrayDouble *da) throw(INTERP_KERNEL::Exception)
7181 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Build0DMeshFromCoords : instance of DataArrayDouble must be not null !");
7182 da->checkAllocated();
7183 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(da->getName().c_str(),0);
7185 int nbOfTuples=da->getNumberOfTuples();
7186 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7187 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7188 c->alloc(2*nbOfTuples,1);
7189 cI->alloc(nbOfTuples+1,1);
7190 int *cp=c->getPointer();
7191 int *cip=cI->getPointer();
7193 for(int i=0;i<nbOfTuples;i++)
7195 *cp++=INTERP_KERNEL::NORM_POINT1;
7199 ret->setConnectivity(c,cI,true);
7203 * Creates a new MEDCouplingUMesh by concatenating two given meshes of the same dimension.
7204 * Cells and nodes of
7205 * the first mesh precede cells and nodes of the second mesh within the result mesh.
7206 * \param [in] mesh1 - the first mesh.
7207 * \param [in] mesh2 - the second mesh.
7208 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7209 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7210 * is no more needed.
7211 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7212 * \throw If the coordinates array is not set in none of the meshes.
7213 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7214 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7216 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7218 std::vector<const MEDCouplingUMesh *> tmp(2);
7219 tmp[0]=const_cast<MEDCouplingUMesh *>(mesh1); tmp[1]=const_cast<MEDCouplingUMesh *>(mesh2);
7220 return MergeUMeshes(tmp);
7224 * Creates a new MEDCouplingUMesh by concatenating all given meshes of the same dimension.
7225 * Cells and nodes of
7226 * the *i*-th mesh precede cells and nodes of the (*i*+1)-th mesh within the result mesh.
7227 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7228 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7229 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7230 * is no more needed.
7231 * \throw If \a a.size() == 0.
7232 * \throw If \a a[ *i* ] == NULL.
7233 * \throw If the coordinates array is not set in none of the meshes.
7234 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7235 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7237 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshes(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7239 std::size_t sz=a.size();
7241 return MergeUMeshesLL(a);
7242 for(std::size_t ii=0;ii<sz;ii++)
7245 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshes : item #" << ii << " in input array of size "<< sz << " is empty !";
7246 throw INTERP_KERNEL::Exception(oss.str().c_str());
7248 std::vector< MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> > bb(sz);
7249 std::vector< const MEDCouplingUMesh * > aa(sz);
7251 for(std::size_t i=0;i<sz && spaceDim==-3;i++)
7253 const MEDCouplingUMesh *cur=a[i];
7254 const DataArrayDouble *coo=cur->getCoords();
7256 spaceDim=coo->getNumberOfComponents();
7259 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : no spaceDim specified ! unable to perform merge !");
7260 for(std::size_t i=0;i<sz;i++)
7262 bb[i]=a[i]->buildSetInstanceFromThis(spaceDim);
7265 return MergeUMeshesLL(aa);
7270 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesLL(std::vector<const MEDCouplingUMesh *>& a) throw(INTERP_KERNEL::Exception)
7273 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::MergeUMeshes : input array must be NON EMPTY !");
7274 std::vector<const MEDCouplingUMesh *>::const_iterator it=a.begin();
7275 int meshDim=(*it)->getMeshDimension();
7276 int nbOfCells=(*it)->getNumberOfCells();
7277 int meshLgth=(*it++)->getMeshLength();
7278 for(;it!=a.end();it++)
7280 if(meshDim!=(*it)->getMeshDimension())
7281 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, MergeUMeshes impossible !");
7282 nbOfCells+=(*it)->getNumberOfCells();
7283 meshLgth+=(*it)->getMeshLength();
7285 std::vector<const MEDCouplingPointSet *> aps(a.size());
7286 std::copy(a.begin(),a.end(),aps.begin());
7287 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> pts=MergeNodesArray(aps);
7288 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("merge",meshDim);
7289 ret->setCoords(pts);
7290 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c=DataArrayInt::New();
7291 c->alloc(meshLgth,1);
7292 int *cPtr=c->getPointer();
7293 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cI=DataArrayInt::New();
7294 cI->alloc(nbOfCells+1,1);
7295 int *cIPtr=cI->getPointer();
7299 for(it=a.begin();it!=a.end();it++)
7301 int curNbOfCell=(*it)->getNumberOfCells();
7302 const int *curCI=(*it)->_nodal_connec_index->getConstPointer();
7303 const int *curC=(*it)->_nodal_connec->getConstPointer();
7304 cIPtr=std::transform(curCI+1,curCI+curNbOfCell+1,cIPtr,std::bind2nd(std::plus<int>(),offset));
7305 for(int j=0;j<curNbOfCell;j++)
7307 const int *src=curC+curCI[j];
7309 for(;src!=curC+curCI[j+1];src++,cPtr++)
7317 offset+=curCI[curNbOfCell];
7318 offset2+=(*it)->getNumberOfNodes();
7321 ret->setConnectivity(c,cI,true);
7328 * Creates a new MEDCouplingUMesh by concatenating cells of two given meshes of same
7329 * dimension and sharing the node coordinates array.
7330 * All cells of the first mesh precede all cells of the second mesh
7331 * within the result mesh.
7332 * \param [in] mesh1 - the first mesh.
7333 * \param [in] mesh2 - the second mesh.
7334 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7335 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7336 * is no more needed.
7337 * \throw If \a mesh1 == NULL or \a mesh2 == NULL.
7338 * \throw If the meshes do not share the node coordinates array.
7339 * \throw If \a mesh1->getMeshDimension() < 0 or \a mesh2->getMeshDimension() < 0.
7340 * \throw If \a mesh1->getMeshDimension() != \a mesh2->getMeshDimension().
7342 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const MEDCouplingUMesh *mesh1, const MEDCouplingUMesh *mesh2) throw(INTERP_KERNEL::Exception)
7344 std::vector<const MEDCouplingUMesh *> tmp(2);
7345 tmp[0]=mesh1; tmp[1]=mesh2;
7346 return MergeUMeshesOnSameCoords(tmp);
7350 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7351 * dimension and sharing the node coordinates array.
7352 * All cells of the *i*-th mesh precede all cells of the
7353 * (*i*+1)-th mesh within the result mesh.
7354 * \param [in] a - a vector of meshes (MEDCouplingUMesh) to concatenate.
7355 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7356 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7357 * is no more needed.
7358 * \throw If \a a.size() == 0.
7359 * \throw If \a a[ *i* ] == NULL.
7360 * \throw If the meshes do not share the node coordinates array.
7361 * \throw If \a a[ *i* ]->getMeshDimension() < 0.
7362 * \throw If the meshes in \a a are of different dimension (getMeshDimension()).
7364 MEDCouplingUMesh *MEDCouplingUMesh::MergeUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes)
7367 throw INTERP_KERNEL::Exception("meshes input parameter is expected to be non empty.");
7368 for(std::size_t ii=0;ii<meshes.size();ii++)
7371 std::ostringstream oss; oss << "MEDCouplingUMesh::MergeUMeshesOnSameCoords : item #" << ii << " in input array of size "<< meshes.size() << " is empty !";
7372 throw INTERP_KERNEL::Exception(oss.str().c_str());
7374 const DataArrayDouble *coords=meshes.front()->getCoords();
7375 int meshDim=meshes.front()->getMeshDimension();
7376 std::vector<const MEDCouplingUMesh *>::const_iterator iter=meshes.begin();
7378 int meshIndexLgth=0;
7379 for(;iter!=meshes.end();iter++)
7381 if(coords!=(*iter)->getCoords())
7382 throw INTERP_KERNEL::Exception("meshes does not share the same coords ! Try using tryToShareSameCoords method !");
7383 if(meshDim!=(*iter)->getMeshDimension())
7384 throw INTERP_KERNEL::Exception("Mesh dimensions mismatches, FuseUMeshesOnSameCoords impossible !");
7385 meshLgth+=(*iter)->getMeshLength();
7386 meshIndexLgth+=(*iter)->getNumberOfCells();
7388 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodal=DataArrayInt::New();
7389 nodal->alloc(meshLgth,1);
7390 int *nodalPtr=nodal->getPointer();
7391 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> nodalIndex=DataArrayInt::New();
7392 nodalIndex->alloc(meshIndexLgth+1,1);
7393 int *nodalIndexPtr=nodalIndex->getPointer();
7395 for(iter=meshes.begin();iter!=meshes.end();iter++)
7397 const int *nod=(*iter)->getNodalConnectivity()->getConstPointer();
7398 const int *index=(*iter)->getNodalConnectivityIndex()->getConstPointer();
7399 int nbOfCells=(*iter)->getNumberOfCells();
7400 int meshLgth2=(*iter)->getMeshLength();
7401 nodalPtr=std::copy(nod,nod+meshLgth2,nodalPtr);
7402 if(iter!=meshes.begin())
7403 nodalIndexPtr=std::transform(index+1,index+nbOfCells+1,nodalIndexPtr,std::bind2nd(std::plus<int>(),offset));
7405 nodalIndexPtr=std::copy(index,index+nbOfCells+1,nodalIndexPtr);
7408 MEDCouplingUMesh *ret=MEDCouplingUMesh::New();
7409 ret->setName("merge");
7410 ret->setMeshDimension(meshDim);
7411 ret->setConnectivity(nodal,nodalIndex,true);
7412 ret->setCoords(coords);
7417 * Creates a new MEDCouplingUMesh by concatenating cells of all given meshes of same
7418 * dimension and sharing the node coordinates array. Cells of the *i*-th mesh precede
7419 * cells of the (*i*+1)-th mesh within the result mesh. Duplicates of cells are
7420 * removed from \a this mesh and arrays mapping between new and old cell ids in "Old to
7421 * New" mode are returned for each input mesh.
7422 * \param [in] meshes - a vector of meshes (MEDCouplingUMesh) to concatenate.
7423 * \param [in] compType - specifies a cell comparison technique. For meaning of its
7424 * valid values [0,1,2], see zipConnectivityTraducer().
7425 * \param [in,out] corr - an array of DataArrayInt, of the same size as \a
7426 * meshes. The *i*-th array describes cell ids mapping for \a meshes[ *i* ]
7427 * mesh. The caller is to delete each of the arrays using decrRef() as it is
7429 * \return MEDCouplingUMesh * - the result mesh. It is a new instance of
7430 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
7431 * is no more needed.
7432 * \throw If \a meshes.size() == 0.
7433 * \throw If \a meshes[ *i* ] == NULL.
7434 * \throw If the meshes do not share the node coordinates array.
7435 * \throw If \a meshes[ *i* ]->getMeshDimension() < 0.
7436 * \throw If the \a meshes are of different dimension (getMeshDimension()).
7437 * \throw If the nodal connectivity of cells of any of \a meshes is not defined.
7438 * \throw If the nodal connectivity any of \a meshes includes an invalid id.
7440 MEDCouplingUMesh *MEDCouplingUMesh::FuseUMeshesOnSameCoords(const std::vector<const MEDCouplingUMesh *>& meshes, int compType, std::vector<DataArrayInt *>& corr)
7442 //All checks are delegated to MergeUMeshesOnSameCoords
7443 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MergeUMeshesOnSameCoords(meshes);
7444 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=ret->zipConnectivityTraducer(compType);
7445 corr.resize(meshes.size());
7446 std::size_t nbOfMeshes=meshes.size();
7448 const int *o2nPtr=o2n->getConstPointer();
7449 for(std::size_t i=0;i<nbOfMeshes;i++)
7451 DataArrayInt *tmp=DataArrayInt::New();
7452 int curNbOfCells=meshes[i]->getNumberOfCells();
7453 tmp->alloc(curNbOfCells,1);
7454 std::copy(o2nPtr+offset,o2nPtr+offset+curNbOfCells,tmp->getPointer());
7455 offset+=curNbOfCells;
7456 tmp->setName(meshes[i]->getName().c_str());
7463 * Makes all given meshes share the nodal connectivity array. The common connectivity
7464 * array is created by concatenating the connectivity arrays of all given meshes. All
7465 * the given meshes must be of the same space dimension but dimension of cells **can
7466 * differ**. This method is particulary useful in MEDLoader context to build a \ref
7467 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7468 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7469 * \param [in,out] meshes - a vector of meshes to update.
7470 * \throw If any of \a meshes is NULL.
7471 * \throw If the coordinates array is not set in any of \a meshes.
7472 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7473 * \throw If \a meshes are of different space dimension.
7475 void MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords(const std::vector<MEDCouplingUMesh *>& meshes) throw(INTERP_KERNEL::Exception)
7477 std::size_t sz=meshes.size();
7480 std::vector< const DataArrayDouble * > coords(meshes.size());
7481 std::vector< const DataArrayDouble * >::iterator it2=coords.begin();
7482 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++,it2++)
7486 (*it)->checkConnectivityFullyDefined();
7487 const DataArrayDouble *coo=(*it)->getCoords();
7492 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7493 oss << " has no coordinate array defined !";
7494 throw INTERP_KERNEL::Exception(oss.str().c_str());
7499 std::ostringstream oss; oss << " MEDCouplingUMesh::PutUMeshesOnSameAggregatedCoords : Item #" << std::distance(meshes.begin(),it) << " inside the vector of length " << meshes.size();
7500 oss << " is null !";
7501 throw INTERP_KERNEL::Exception(oss.str().c_str());
7504 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> res=DataArrayDouble::Aggregate(coords);
7505 std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();
7506 int offset=(*it)->getNumberOfNodes();
7507 (*it++)->setCoords(res);
7508 for(;it!=meshes.end();it++)
7510 int oldNumberOfNodes=(*it)->getNumberOfNodes();
7511 (*it)->setCoords(res);
7512 (*it)->shiftNodeNumbersInConn(offset);
7513 offset+=oldNumberOfNodes;
7518 * Merges nodes coincident with a given precision within all given meshes that share
7519 * the nodal connectivity array. The given meshes **can be of different** mesh
7520 * dimension. This method is particulary useful in MEDLoader context to build a \ref
7521 * ParaMEDMEM::MEDFileUMesh "MEDFileUMesh" instance that expects that underlying
7522 * MEDCouplingUMesh'es of different dimension share the same nodal connectivity array.
7523 * \param [in,out] meshes - a vector of meshes to update.
7524 * \param [in] eps - the precision used to detect coincident nodes (infinite norm).
7525 * \throw If any of \a meshes is NULL.
7526 * \throw If the \a meshes do not share the same node coordinates array.
7527 * \throw If the nodal connectivity of cells is not defined in any of \a meshes.
7529 void MEDCouplingUMesh::MergeNodesOnUMeshesSharingSameCoords(const std::vector<MEDCouplingUMesh *>& meshes, double eps) throw(INTERP_KERNEL::Exception)
7533 std::set<const DataArrayDouble *> s;
7534 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7537 s.insert((*it)->getCoords());
7540 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 !";
7541 throw INTERP_KERNEL::Exception(oss.str().c_str());
7546 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 !";
7547 throw INTERP_KERNEL::Exception(oss.str().c_str());
7549 const DataArrayDouble *coo=*(s.begin());
7553 DataArrayInt *comm,*commI;
7554 coo->findCommonTuples(eps,-1,comm,commI);
7555 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> tmp1(comm),tmp2(commI);
7556 int oldNbOfNodes=coo->getNumberOfTuples();
7558 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=DataArrayInt::BuildOld2NewArrayFromSurjectiveFormat2(oldNbOfNodes,comm->begin(),commI->begin(),commI->end(),newNbOfNodes);
7559 if(oldNbOfNodes==newNbOfNodes)
7561 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> newCoords=coo->renumberAndReduce(o2n->getConstPointer(),newNbOfNodes);
7562 for(std::vector<MEDCouplingUMesh *>::const_iterator it=meshes.begin();it!=meshes.end();it++)
7564 (*it)->renumberNodesInConn(o2n->getConstPointer());
7565 (*it)->setCoords(newCoords);
7570 * 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.
7571 * \param nbOfNodesPerLev in parameter that specifies the number of nodes of one slice of global dataset
7572 * \param isQuad specifies the policy of connectivity.
7573 * @ret in/out parameter in which the result will be append
7575 void MEDCouplingUMesh::AppendExtrudedCell(const int *connBg, const int *connEnd, int nbOfNodesPerLev, bool isQuad, std::vector<int>& ret)
7577 INTERP_KERNEL::NormalizedCellType flatType=(INTERP_KERNEL::NormalizedCellType)connBg[0];
7578 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(flatType);
7579 ret.push_back(cm.getExtrudedType());
7580 int deltaz=isQuad?2*nbOfNodesPerLev:nbOfNodesPerLev;
7583 case INTERP_KERNEL::NORM_POINT1:
7585 ret.push_back(connBg[1]);
7586 ret.push_back(connBg[1]+nbOfNodesPerLev);
7589 case INTERP_KERNEL::NORM_SEG2:
7591 int conn[4]={connBg[1],connBg[2],connBg[2]+deltaz,connBg[1]+deltaz};
7592 ret.insert(ret.end(),conn,conn+4);
7595 case INTERP_KERNEL::NORM_SEG3:
7597 int conn[8]={connBg[1],connBg[3],connBg[3]+deltaz,connBg[1]+deltaz,connBg[2],connBg[3]+nbOfNodesPerLev,connBg[2]+deltaz,connBg[1]+nbOfNodesPerLev};
7598 ret.insert(ret.end(),conn,conn+8);
7601 case INTERP_KERNEL::NORM_QUAD4:
7603 int conn[8]={connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz};
7604 ret.insert(ret.end(),conn,conn+8);
7607 case INTERP_KERNEL::NORM_TRI3:
7609 int conn[6]={connBg[1],connBg[2],connBg[3],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz};
7610 ret.insert(ret.end(),conn,conn+6);
7613 case INTERP_KERNEL::NORM_TRI6:
7615 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,
7616 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev};
7617 ret.insert(ret.end(),conn,conn+15);
7620 case INTERP_KERNEL::NORM_QUAD8:
7623 connBg[1],connBg[2],connBg[3],connBg[4],connBg[1]+deltaz,connBg[2]+deltaz,connBg[3]+deltaz,connBg[4]+deltaz,
7624 connBg[5],connBg[6],connBg[7],connBg[8],connBg[5]+deltaz,connBg[6]+deltaz,connBg[7]+deltaz,connBg[8]+deltaz,
7625 connBg[1]+nbOfNodesPerLev,connBg[2]+nbOfNodesPerLev,connBg[3]+nbOfNodesPerLev,connBg[4]+nbOfNodesPerLev
7627 ret.insert(ret.end(),conn,conn+20);
7630 case INTERP_KERNEL::NORM_POLYGON:
7632 std::back_insert_iterator< std::vector<int> > ii(ret);
7633 std::copy(connBg+1,connEnd,ii);
7635 std::reverse_iterator<const int *> rConnBg(connEnd);
7636 std::reverse_iterator<const int *> rConnEnd(connBg+1);
7637 std::transform(rConnBg,rConnEnd,ii,std::bind2nd(std::plus<int>(),deltaz));
7638 std::size_t nbOfRadFaces=std::distance(connBg+1,connEnd);
7639 for(std::size_t i=0;i<nbOfRadFaces;i++)
7642 int conn[4]={connBg[(i+1)%nbOfRadFaces+1],connBg[i+1],connBg[i+1]+deltaz,connBg[(i+1)%nbOfRadFaces+1]+deltaz};
7643 std::copy(conn,conn+4,ii);
7648 throw INTERP_KERNEL::Exception("A flat type has been detected that has not its extruded representation !");
7653 * This static operates only for coords in 3D. The polygon is specfied by its connectivity nodes in [ \a begin , \a end ).
7655 bool MEDCouplingUMesh::IsPolygonWellOriented(bool isQuadratic, const double *vec, const int *begin, const int *end, const double *coords)
7657 double v[3]={0.,0.,0.};
7658 std::size_t sz=std::distance(begin,end);
7661 for(std::size_t i=0;i<sz;i++)
7663 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];
7664 v[1]+=coords[3*begin[i]+2]*coords[3*begin[(i+1)%sz]]-coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+2];
7665 v[2]+=coords[3*begin[i]]*coords[3*begin[(i+1)%sz]+1]-coords[3*begin[i]+1]*coords[3*begin[(i+1)%sz]];
7667 return vec[0]*v[0]+vec[1]*v[1]+vec[2]*v[2]>0.;
7671 * The polyhedron is specfied by its connectivity nodes in [ \a begin , \a end ).
7673 bool MEDCouplingUMesh::IsPolyhedronWellOriented(const int *begin, const int *end, const double *coords)
7675 std::vector<std::pair<int,int> > edges;
7676 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7677 const int *bgFace=begin;
7678 for(std::size_t i=0;i<nbOfFaces;i++)
7680 const int *endFace=std::find(bgFace+1,end,-1);
7681 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7682 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7684 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7685 if(std::find(edges.begin(),edges.end(),p1)!=edges.end())
7687 edges.push_back(p1);
7691 return INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)>-EPS_FOR_POLYH_ORIENTATION;
7695 * The 3D extruded static cell (PENTA6,HEXA8,HEXAGP12...) its connectivity nodes in [ \a begin , \a end ).
7697 bool MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented(const int *begin, const int *end, const double *coords)
7699 double vec0[3],vec1[3];
7700 std::size_t sz=std::distance(begin,end);
7702 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Is3DExtrudedStaticCellWellOriented : the length of nodal connectivity of extruded cell is not even !");
7703 int nbOfNodes=(int)sz/2;
7704 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,nbOfNodes,coords,vec0);
7705 const double *pt0=coords+3*begin[0];
7706 const double *pt1=coords+3*begin[nbOfNodes];
7707 vec1[0]=pt1[0]-pt0[0]; vec1[1]=pt1[1]-pt0[1]; vec1[2]=pt1[2]-pt0[2];
7708 return (vec0[0]*vec1[0]+vec0[1]*vec1[1]+vec0[2]*vec1[2])<0.;
7711 void MEDCouplingUMesh::CorrectExtrudedStaticCell(int *begin, int *end)
7713 std::size_t sz=std::distance(begin,end);
7714 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
7715 std::size_t nbOfNodes(sz/2);
7716 std::copy(begin,end,(int *)tmp);
7717 for(std::size_t j=1;j<nbOfNodes;j++)
7719 begin[j]=tmp[nbOfNodes-j];
7720 begin[j+nbOfNodes]=tmp[nbOfNodes+nbOfNodes-j];
7724 bool MEDCouplingUMesh::IsTetra4WellOriented(const int *begin, const int *end, const double *coords)
7726 std::size_t sz=std::distance(begin,end);
7728 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsTetra4WellOriented : Tetra4 cell with not 4 nodes ! Call checkCoherency2 !");
7729 double vec0[3],vec1[3];
7730 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[1],*pt2=coords+3*begin[2],*pt3=coords+3*begin[3];
7731 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];
7732 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;
7735 bool MEDCouplingUMesh::IsPyra5WellOriented(const int *begin, const int *end, const double *coords)
7737 std::size_t sz=std::distance(begin,end);
7739 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::IsPyra5WellOriented : Pyra5 cell with not 5 nodes ! Call checkCoherency2 !");
7741 INTERP_KERNEL::areaVectorOfPolygon<int,INTERP_KERNEL::ALL_C_MODE>(begin,4,coords,vec0);
7742 const double *pt0=coords+3*begin[0],*pt1=coords+3*begin[4];
7743 return (vec0[0]*(pt1[0]-pt0[0])+vec0[1]*(pt1[1]-pt0[1])+vec0[2]*(pt1[2]-pt0[2]))<0.;
7747 * 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 )
7748 * 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
7751 * \param [in] eps is a relative precision that allows to establish if some 3D plane are coplanar or not.
7752 * \param [in] coords the coordinates with nb of components exactly equal to 3
7753 * \param [in] begin begin of the nodal connectivity (geometric type included) of a single polyhedron cell
7754 * \param [in] end end of nodal connectivity of a single polyhedron cell (excluded)
7755 * \param [out] res the result is put at the end of the vector without any alteration of the data.
7757 void MEDCouplingUMesh::SimplifyPolyhedronCell(double eps, const DataArrayDouble *coords, const int *begin, const int *end, DataArrayInt *res) throw(INTERP_KERNEL::Exception)
7759 int nbFaces=std::count(begin+1,end,-1)+1;
7760 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> v=DataArrayDouble::New(); v->alloc(nbFaces,3);
7761 double *vPtr=v->getPointer();
7762 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> p=DataArrayDouble::New(); p->alloc(nbFaces,1);
7763 double *pPtr=p->getPointer();
7764 const int *stFaceConn=begin+1;
7765 for(int i=0;i<nbFaces;i++,vPtr+=3,pPtr++)
7767 const int *endFaceConn=std::find(stFaceConn,end,-1);
7768 ComputeVecAndPtOfFace(eps,coords->getConstPointer(),stFaceConn,endFaceConn,vPtr,pPtr);
7769 stFaceConn=endFaceConn+1;
7771 pPtr=p->getPointer(); vPtr=v->getPointer();
7772 DataArrayInt *comm1=0,*commI1=0;
7773 v->findCommonTuples(eps,-1,comm1,commI1);
7774 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm1Auto(comm1),commI1Auto(commI1);
7775 const int *comm1Ptr=comm1->getConstPointer();
7776 const int *commI1Ptr=commI1->getConstPointer();
7777 int nbOfGrps1=commI1Auto->getNumberOfTuples()-1;
7778 res->pushBackSilent((int)INTERP_KERNEL::NORM_POLYHED);
7780 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm=MEDCouplingUMesh::New("",3);
7781 mm->setCoords(const_cast<DataArrayDouble *>(coords)); mm->allocateCells(1); mm->insertNextCell(INTERP_KERNEL::NORM_POLYHED,(int)std::distance(begin+1,end),begin+1);
7782 mm->finishInsertingCells();
7784 for(int i=0;i<nbOfGrps1;i++)
7786 int vecId=comm1Ptr[commI1Ptr[i]];
7787 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> tmpgrp2=p->selectByTupleId(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7788 DataArrayInt *comm2=0,*commI2=0;
7789 tmpgrp2->findCommonTuples(eps,-1,comm2,commI2);
7790 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> comm2Auto(comm2),commI2Auto(commI2);
7791 const int *comm2Ptr=comm2->getConstPointer();
7792 const int *commI2Ptr=commI2->getConstPointer();
7793 int nbOfGrps2=commI2Auto->getNumberOfTuples()-1;
7794 for(int j=0;j<nbOfGrps2;j++)
7796 if(commI2Ptr[j+1]-commI2Ptr[j]<=1)
7798 res->insertAtTheEnd(begin,end);
7799 res->pushBackSilent(-1);
7803 int pointId=comm1Ptr[commI1Ptr[i]+comm2Ptr[commI2Ptr[j]]];
7804 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ids2=comm2->selectByTupleId2(commI2Ptr[j],commI2Ptr[j+1],1);
7805 ids2->transformWithIndArr(comm1Ptr+commI1Ptr[i],comm1Ptr+commI1Ptr[i+1]);
7806 DataArrayInt *tmp0=DataArrayInt::New(),*tmp1=DataArrayInt::New(),*tmp2=DataArrayInt::New(),*tmp3=DataArrayInt::New();
7807 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm2=mm->buildDescendingConnectivity(tmp0,tmp1,tmp2,tmp3); tmp0->decrRef(); tmp1->decrRef(); tmp2->decrRef(); tmp3->decrRef();
7808 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm3=static_cast<MEDCouplingUMesh *>(mm2->buildPartOfMySelf(ids2->begin(),ids2->end(),true));
7809 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNodeTmp=mm3->zipCoordsTraducer();
7810 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> idsNode=idsNodeTmp->invertArrayO2N2N2O(mm3->getNumberOfNodes());
7811 const int *idsNodePtr=idsNode->getConstPointer();
7812 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];
7813 double vec[3]; vec[0]=vPtr[3*vecId+1]; vec[1]=-vPtr[3*vecId]; vec[2]=0.;
7814 double norm=vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2];
7815 if(std::abs(norm)>eps)
7817 double angle=INTERP_KERNEL::EdgeArcCircle::SafeAsin(norm);
7818 mm3->rotate(center,vec,angle);
7820 mm3->changeSpaceDimension(2);
7821 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> mm4=mm3->buildSpreadZonesWithPoly();
7822 const int *conn4=mm4->getNodalConnectivity()->getConstPointer();
7823 const int *connI4=mm4->getNodalConnectivityIndex()->getConstPointer();
7824 int nbOfCells=mm4->getNumberOfCells();
7825 for(int k=0;k<nbOfCells;k++)
7828 for(const int *work=conn4+connI4[k]+1;work!=conn4+connI4[k+1];work++,l++)
7829 res->pushBackSilent(idsNodePtr[*work]);
7830 res->pushBackSilent(-1);
7835 res->popBackSilent();
7839 * 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
7840 * through origin. The plane is defined by its nodal connectivity [ \b begin, \b end ).
7842 * \param [in] eps below that value the dot product of 2 vectors is considered as colinears
7843 * \param [in] coords coordinates expected to have 3 components.
7844 * \param [in] begin start of the nodal connectivity of the face.
7845 * \param [in] end end of the nodal connectivity (excluded) of the face.
7846 * \param [out] v the normalized vector of size 3
7847 * \param [out] p the pos of plane
7849 void MEDCouplingUMesh::ComputeVecAndPtOfFace(double eps, const double *coords, const int *begin, const int *end, double *v, double *p) throw(INTERP_KERNEL::Exception)
7851 std::size_t nbPoints=std::distance(begin,end);
7853 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeVecAndPtOfFace : < of 3 points in face ! not able to find a plane on that face !");
7854 double vec[3]={0.,0.,0.};
7856 bool refFound=false;
7857 for(;j<nbPoints-1 && !refFound;j++)
7859 vec[0]=coords[3*begin[j+1]]-coords[3*begin[j]];
7860 vec[1]=coords[3*begin[j+1]+1]-coords[3*begin[j]+1];
7861 vec[2]=coords[3*begin[j+1]+2]-coords[3*begin[j]+2];
7862 double norm=sqrt(vec[0]*vec[0]+vec[1]*vec[1]+vec[2]*vec[2]);
7866 vec[0]/=norm; vec[1]/=norm; vec[2]/=norm;
7869 for(std::size_t i=j;i<nbPoints-1;i++)
7872 curVec[0]=coords[3*begin[i+1]]-coords[3*begin[i]];
7873 curVec[1]=coords[3*begin[i+1]+1]-coords[3*begin[i]+1];
7874 curVec[2]=coords[3*begin[i+1]+2]-coords[3*begin[i]+2];
7875 double norm=sqrt(curVec[0]*curVec[0]+curVec[1]*curVec[1]+curVec[2]*curVec[2]);
7878 curVec[0]/=norm; curVec[1]/=norm; curVec[2]/=norm;
7879 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];
7880 norm=sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
7883 v[0]/=norm; v[1]/=norm; v[2]/=norm;
7884 *p=v[0]*coords[3*begin[i]]+v[1]*coords[3*begin[i]+1]+v[2]*coords[3*begin[i]+2];
7888 throw INTERP_KERNEL::Exception("Not able to find a normal vector of that 3D face !");
7892 * This method tries to obtain a well oriented polyhedron.
7893 * If the algorithm fails, an exception will be thrown.
7895 void MEDCouplingUMesh::TryToCorrectPolyhedronOrientation(int *begin, int *end, const double *coords) throw(INTERP_KERNEL::Exception)
7897 std::list< std::pair<int,int> > edgesOK,edgesFinished;
7898 std::size_t nbOfFaces=std::count(begin,end,-1)+1;
7899 std::vector<bool> isPerm(nbOfFaces,false);//field on faces False: I don't know, True : oriented
7901 int *bgFace=begin,*endFace=std::find(begin+1,end,-1);
7902 std::size_t nbOfEdgesInFace=std::distance(bgFace,endFace);
7903 for(std::size_t l=0;l<nbOfEdgesInFace;l++) { std::pair<int,int> p1(bgFace[l],bgFace[(l+1)%nbOfEdgesInFace]); edgesOK.push_back(p1); }
7905 while(std::find(isPerm.begin(),isPerm.end(),false)!=isPerm.end())
7908 std::size_t smthChanged=0;
7909 for(std::size_t i=0;i<nbOfFaces;i++)
7911 endFace=std::find(bgFace+1,end,-1);
7912 nbOfEdgesInFace=std::distance(bgFace,endFace);
7916 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7918 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7919 std::pair<int,int> p2(p1.second,p1.first);
7920 bool b1=std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end();
7921 bool b2=std::find(edgesOK.begin(),edgesOK.end(),p2)!=edgesOK.end();
7922 if(b1 || b2) { b=b2; isPerm[i]=true; smthChanged++; break; }
7927 std::reverse(bgFace+1,endFace);
7928 for(std::size_t j=0;j<nbOfEdgesInFace;j++)
7930 std::pair<int,int> p1(bgFace[j],bgFace[(j+1)%nbOfEdgesInFace]);
7931 std::pair<int,int> p2(p1.second,p1.first);
7932 if(std::find(edgesOK.begin(),edgesOK.end(),p1)!=edgesOK.end())
7933 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7934 if(std::find(edgesFinished.begin(),edgesFinished.end(),p1)!=edgesFinished.end() || std::find(edgesFinished.begin(),edgesFinished.end(),p2)!=edgesFinished.end())
7935 { std::ostringstream oss; oss << "Face #" << j << " of polyhedron looks bad !"; throw INTERP_KERNEL::Exception(oss.str().c_str()); }
7936 std::list< std::pair<int,int> >::iterator it=std::find(edgesOK.begin(),edgesOK.end(),p2);
7937 if(it!=edgesOK.end())
7940 edgesFinished.push_back(p1);
7943 edgesOK.push_back(p1);
7950 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired !"); }
7952 if(!edgesOK.empty())
7953 { throw INTERP_KERNEL::Exception("The polyhedron looks too bad to be repaired : Some edges are shared only once !"); }
7954 if(INTERP_KERNEL::calculateVolumeForPolyh2<int,INTERP_KERNEL::ALL_C_MODE>(begin,(int)std::distance(begin,end),coords)<-EPS_FOR_POLYH_ORIENTATION)
7955 {//not lucky ! The first face was not correctly oriented : reorient all faces...
7957 for(std::size_t i=0;i<nbOfFaces;i++)
7959 endFace=std::find(bgFace+1,end,-1);
7960 std::reverse(bgFace+1,endFace);
7967 * This method makes the assumption spacedimension == meshdimension == 2.
7968 * This method works only for linear cells.
7970 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYGON in pos#0)
7972 DataArrayInt *MEDCouplingUMesh::buildUnionOf2DMesh() const throw(INTERP_KERNEL::Exception)
7974 if(getMeshDimension()!=2 || getSpaceDimension()!=2)
7975 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : meshdimension, spacedimension must be equal to 2 !");
7976 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
7977 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> o2n=m->zipCoordsTraducer();
7978 int nbOfNodesExpected=m->getNumberOfNodes();
7979 if(m->getNumberOfCells()!=nbOfNodesExpected)
7980 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : the mesh 2D in input appears to be not in a single part or a quadratic 2D mesh !");
7981 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> n2o=o2n->invertArrayO2N2N2O(m->getNumberOfNodes());
7982 const int *n2oPtr=n2o->getConstPointer();
7983 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> revNodal(DataArrayInt::New()),revNodalI(DataArrayInt::New());
7984 m->getReverseNodalConnectivity(revNodal,revNodalI);
7985 const int *revNodalPtr=revNodal->getConstPointer(),*revNodalIPtr=revNodalI->getConstPointer();
7986 const int *nodalPtr=m->getNodalConnectivity()->getConstPointer();
7987 const int *nodalIPtr=m->getNodalConnectivityIndex()->getConstPointer();
7988 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(nbOfNodesExpected+1,1);
7989 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYGON;
7990 if(nbOfNodesExpected<1)
7993 int prevNode=nodalPtr[nodalIPtr[0]+1];
7994 *work++=n2oPtr[prevNode];
7995 for(int i=1;i<nbOfNodesExpected;i++)
7997 if(nodalIPtr[prevCell+1]-nodalIPtr[prevCell]==3)
7999 std::set<int> conn(nodalPtr+nodalIPtr[prevCell]+1,nodalPtr+nodalIPtr[prevCell]+3);
8000 conn.erase(prevNode);
8003 int curNode=*(conn.begin());
8004 *work++=n2oPtr[curNode];
8005 std::set<int> shar(revNodalPtr+revNodalIPtr[curNode],revNodalPtr+revNodalIPtr[curNode+1]);
8006 shar.erase(prevCell);
8009 prevCell=*(shar.begin());
8013 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 2 !");
8016 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected 1 !");
8019 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf2DMesh : presence of unexpected cell !");
8025 * This method makes the assumption spacedimension == meshdimension == 3.
8026 * This method works only for linear cells.
8028 * \return a newly allocated array containing the connectivity of a polygon type enum included (NORM_POLYHED in pos#0)
8030 DataArrayInt *MEDCouplingUMesh::buildUnionOf3DMesh() const throw(INTERP_KERNEL::Exception)
8032 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8033 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildUnionOf3DMesh : meshdimension, spacedimension must be equal to 2 !");
8034 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> m=computeSkin();
8035 const int *conn=m->getNodalConnectivity()->getConstPointer();
8036 const int *connI=m->getNodalConnectivityIndex()->getConstPointer();
8037 int nbOfCells=m->getNumberOfCells();
8038 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(m->getNodalConnectivity()->getNumberOfTuples(),1);
8039 int *work=ret->getPointer(); *work++=INTERP_KERNEL::NORM_POLYHED;
8042 work=std::copy(conn+connI[0]+1,conn+connI[1],work);
8043 for(int i=1;i<nbOfCells;i++)
8046 work=std::copy(conn+connI[i]+1,conn+connI[i+1],work);
8052 * This method put in zip format into parameter 'zipFrmt' in full interlace mode.
8053 * This format is often asked by INTERP_KERNEL algorithms to avoid many indirections into coordinates array.
8055 void MEDCouplingUMesh::FillInCompact3DMode(int spaceDim, int nbOfNodesInCell, const int *conn, const double *coo, double *zipFrmt) throw(INTERP_KERNEL::Exception)
8059 for(int i=0;i<nbOfNodesInCell;i++)
8060 w=std::copy(coo+3*conn[i],coo+3*conn[i]+3,w);
8061 else if(spaceDim==2)
8063 for(int i=0;i<nbOfNodesInCell;i++)
8065 w=std::copy(coo+2*conn[i],coo+2*conn[i]+2,w);
8070 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::FillInCompact3DMode : Invalid spaceDim specified : must be 2 or 3 !");
8073 void MEDCouplingUMesh::writeVTKLL(std::ostream& ofs, const std::string& cellData, const std::string& pointData) const throw(INTERP_KERNEL::Exception)
8075 int nbOfCells=getNumberOfCells();
8077 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::writeVTK : the unstructured mesh has no cells !");
8078 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};
8079 ofs << " <" << getVTKDataSetType() << ">\n";
8080 ofs << " <Piece NumberOfPoints=\"" << getNumberOfNodes() << "\" NumberOfCells=\"" << nbOfCells << "\">\n";
8081 ofs << " <PointData>\n" << pointData << std::endl;
8082 ofs << " </PointData>\n";
8083 ofs << " <CellData>\n" << cellData << std::endl;
8084 ofs << " </CellData>\n";
8085 ofs << " <Points>\n";
8086 if(getSpaceDimension()==3)
8087 _coords->writeVTK(ofs,8,"Points");
8090 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=_coords->changeNbOfComponents(3,0.);
8091 coo->writeVTK(ofs,8,"Points");
8093 ofs << " </Points>\n";
8094 ofs << " <Cells>\n";
8095 const int *cPtr=_nodal_connec->getConstPointer();
8096 const int *cIPtr=_nodal_connec_index->getConstPointer();
8097 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faceoffsets=DataArrayInt::New(); faceoffsets->alloc(nbOfCells,1);
8098 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> types=DataArrayInt::New(); types->alloc(nbOfCells,1);
8099 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> offsets=DataArrayInt::New(); offsets->alloc(nbOfCells,1);
8100 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connectivity=DataArrayInt::New(); connectivity->alloc(_nodal_connec->getNumberOfTuples()-nbOfCells,1);
8101 int *w1=faceoffsets->getPointer(),*w2=types->getPointer(),*w3=offsets->getPointer(),*w4=connectivity->getPointer();
8102 int szFaceOffsets=0,szConn=0;
8103 for(int i=0;i<nbOfCells;i++,w1++,w2++,w3++)
8106 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]!=INTERP_KERNEL::NORM_POLYHED)
8109 *w3=szConn+cIPtr[i+1]-cIPtr[i]-1; szConn+=cIPtr[i+1]-cIPtr[i]-1;
8110 w4=std::copy(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],w4);
8114 int deltaFaceOffset=cIPtr[i+1]-cIPtr[i]+1;
8115 *w1=szFaceOffsets+deltaFaceOffset; szFaceOffsets+=deltaFaceOffset;
8116 std::set<int> c(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1]); c.erase(-1);
8117 *w3=szConn+(int)c.size(); szConn+=(int)c.size();
8118 w4=std::copy(c.begin(),c.end(),w4);
8121 types->transformWithIndArr(PARAMEDMEM2VTKTYPETRADUCER,PARAMEDMEM2VTKTYPETRADUCER+INTERP_KERNEL::NORM_MAXTYPE);
8122 types->writeVTK(ofs,8,"UInt8","types");
8123 offsets->writeVTK(ofs,8,"Int32","offsets");
8124 if(szFaceOffsets!=0)
8125 {//presence of Polyhedra
8126 connectivity->reAlloc(szConn);
8127 faceoffsets->writeVTK(ofs,8,"Int32","faceoffsets");
8128 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> faces=DataArrayInt::New(); faces->alloc(szFaceOffsets,1);
8129 w1=faces->getPointer();
8130 for(int i=0;i<nbOfCells;i++)
8131 if((INTERP_KERNEL::NormalizedCellType)cPtr[cIPtr[i]]==INTERP_KERNEL::NORM_POLYHED)
8133 int nbFaces=std::count(cPtr+cIPtr[i]+1,cPtr+cIPtr[i+1],-1)+1;
8135 const int *w6=cPtr+cIPtr[i]+1,*w5=0;
8136 for(int j=0;j<nbFaces;j++)
8138 w5=std::find(w6,cPtr+cIPtr[i+1],-1);
8139 *w1++=(int)std::distance(w6,w5);
8140 w1=std::copy(w6,w5,w1);
8144 faces->writeVTK(ofs,8,"Int32","faces");
8146 connectivity->writeVTK(ofs,8,"Int32","connectivity");
8147 ofs << " </Cells>\n";
8148 ofs << " </Piece>\n";
8149 ofs << " </" << getVTKDataSetType() << ">\n";
8152 void MEDCouplingUMesh::reprQuickOverview(std::ostream& stream) const throw(INTERP_KERNEL::Exception)
8154 stream << "MEDCouplingUMesh C++ instance at " << this << ". Name : \"" << getName() << "\".";
8156 { stream << " Not set !"; return ; }
8157 stream << " Mesh dimension : " << _mesh_dim << ".";
8161 { stream << " No coordinates set !"; return ; }
8162 if(!_coords->isAllocated())
8163 { stream << " Coordinates set but not allocated !"; return ; }
8164 stream << " Space dimension : " << _coords->getNumberOfComponents() << "." << std::endl;
8165 stream << "Number of nodes : " << _coords->getNumberOfTuples() << ".";
8166 if(!_nodal_connec_index)
8167 { stream << std::endl << "Nodal connectivity NOT set !"; return ; }
8168 if(!_nodal_connec_index->isAllocated())
8169 { stream << std::endl << "Nodal connectivity set but not allocated !"; return ; }
8170 int lgth=_nodal_connec_index->getNumberOfTuples();
8171 int cpt=_nodal_connec_index->getNumberOfComponents();
8172 if(cpt!=1 || lgth<1)
8174 stream << std::endl << "Number of cells : " << lgth-1 << ".";
8177 std::string MEDCouplingUMesh::getVTKDataSetType() const throw(INTERP_KERNEL::Exception)
8179 return std::string("UnstructuredGrid");
8183 * Partitions the first given 2D mesh using the second given 2D mesh as a tool, and
8184 * returns a result mesh constituted by polygons. The meshes should be in 2D space. In
8185 * addition, returns two arrays mapping cells of the result mesh to cells of the input
8187 * \param [in] m1 - the first input mesh which is a partitioned object.
8188 * \param [in] m2 - the second input mesh which is a partition tool.
8189 * \param [in] eps - precision used to detect coincident mesh entities.
8190 * \param [out] cellNb1 - a new instance of DataArrayInt holding for each result
8191 * cell an id of the cell of \a m1 it comes from. The caller is to delete
8192 * this array using decrRef() as it is no more needed.
8193 * \param [out] cellNb2 - a new instance of DataArrayInt holding for each result
8194 * cell an id of the cell of \a m2 it comes from. -1 value means that a
8195 * result cell comes from a cell (or part of cell) of \a m1 not overlapped by
8196 * any cell of \a m2. The caller is to delete this array using decrRef() as
8197 * it is no more needed.
8198 * \return MEDCouplingUMesh * - the result 2D mesh which is a new instance of
8199 * MEDCouplingUMesh. The caller is to delete this mesh using decrRef() as it
8200 * is no more needed.
8201 * \throw If the coordinates array is not set in any of the meshes.
8202 * \throw If the nodal connectivity of cells is not defined in any of the meshes.
8203 * \throw If any of the meshes is not a 2D mesh in 2D space.
8205 MEDCouplingUMesh *MEDCouplingUMesh::Intersect2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps, DataArrayInt *&cellNb1, DataArrayInt *&cellNb2) throw(INTERP_KERNEL::Exception)
8207 m1->checkFullyDefined();
8208 m2->checkFullyDefined();
8209 if(m1->getMeshDimension()!=2 || m1->getSpaceDimension()!=2 || m2->getMeshDimension()!=2 || m2->getSpaceDimension()!=2)
8210 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::Intersect2DMeshes works on umeshes m1 AND m2 with meshdim equal to 2 and spaceDim equal to 2 too!");
8211 std::vector< std::vector<int> > intersectEdge1, colinear2, subDiv2;
8212 MEDCouplingUMesh *m1Desc=0,*m2Desc=0;
8213 DataArrayInt *desc1=0,*descIndx1=0,*revDesc1=0,*revDescIndx1=0,*desc2=0,*descIndx2=0,*revDesc2=0,*revDescIndx2=0;
8214 std::vector<double> addCoo,addCoordsQuadratic;
8215 INTERP_KERNEL::QUADRATIC_PLANAR::_precision=eps;
8216 INTERP_KERNEL::QUADRATIC_PLANAR::_arc_detection_precision=eps;
8217 IntersectDescending2DMeshes(m1,m2,eps,intersectEdge1,colinear2, subDiv2,m1Desc,desc1,descIndx1,revDesc1,revDescIndx1,
8218 m2Desc,desc2,descIndx2,revDesc2,revDescIndx2,addCoo);
8219 revDesc1->decrRef(); revDescIndx1->decrRef(); revDesc2->decrRef(); revDescIndx2->decrRef();
8220 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(desc2),dd4(descIndx2);
8221 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd5(m1Desc),dd6(m2Desc);
8222 std::vector< std::vector<int> > intersectEdge2;
8223 BuildIntersectEdges(m1Desc,m2Desc,addCoo,subDiv2,intersectEdge2);
8224 subDiv2.clear(); dd5=0; dd6=0;
8225 std::vector<int> cr,crI; //no DataArrayInt because interface with Geometric2D
8226 std::vector<int> cNb1,cNb2; //no DataArrayInt because interface with Geometric2D
8227 BuildIntersecting2DCellsFromEdges(eps,m1,desc1->getConstPointer(),descIndx1->getConstPointer(),intersectEdge1,colinear2,m2,desc2->getConstPointer(),descIndx2->getConstPointer(),intersectEdge2,addCoo,
8228 /* outputs -> */addCoordsQuadratic,cr,crI,cNb1,cNb2);
8230 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCooDa=DataArrayDouble::New();
8231 addCooDa->alloc((int)(addCoo.size())/2,2);
8232 std::copy(addCoo.begin(),addCoo.end(),addCooDa->getPointer());
8233 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addCoordsQuadraticDa=DataArrayDouble::New();
8234 addCoordsQuadraticDa->alloc((int)(addCoordsQuadratic.size())/2,2);
8235 std::copy(addCoordsQuadratic.begin(),addCoordsQuadratic.end(),addCoordsQuadraticDa->getPointer());
8236 std::vector<const DataArrayDouble *> coordss(4);
8237 coordss[0]=m1->getCoords(); coordss[1]=m2->getCoords(); coordss[2]=addCooDa; coordss[3]=addCoordsQuadraticDa;
8238 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> coo=DataArrayDouble::Aggregate(coordss);
8239 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New("Intersect2D",2);
8240 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> conn=DataArrayInt::New(); conn->alloc((int)cr.size(),1); std::copy(cr.begin(),cr.end(),conn->getPointer());
8241 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> connI=DataArrayInt::New(); connI->alloc((int)crI.size(),1); std::copy(crI.begin(),crI.end(),connI->getPointer());
8242 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c1=DataArrayInt::New(); c1->alloc((int)cNb1.size(),1); std::copy(cNb1.begin(),cNb1.end(),c1->getPointer());
8243 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> c2=DataArrayInt::New(); c2->alloc((int)cNb2.size(),1); std::copy(cNb2.begin(),cNb2.end(),c2->getPointer());
8244 ret->setConnectivity(conn,connI,true);
8245 ret->setCoords(coo);
8246 cellNb1=c1.retn(); cellNb2=c2.retn();
8250 void MEDCouplingUMesh::BuildIntersecting2DCellsFromEdges(double eps, const MEDCouplingUMesh *m1, const int *desc1, const int *descIndx1,
8251 const std::vector<std::vector<int> >& intesctEdges1, const std::vector< std::vector<int> >& colinear2,
8252 const MEDCouplingUMesh *m2, const int *desc2, const int *descIndx2, const std::vector<std::vector<int> >& intesctEdges2,
8253 const std::vector<double>& addCoords,
8254 std::vector<double>& addCoordsQuadratic, std::vector<int>& cr, std::vector<int>& crI, std::vector<int>& cNb1, std::vector<int>& cNb2)
8256 static const int SPACEDIM=2;
8257 const double *coo1=m1->getCoords()->getConstPointer();
8258 const int *conn1=m1->getNodalConnectivity()->getConstPointer();
8259 const int *connI1=m1->getNodalConnectivityIndex()->getConstPointer();
8260 int offset1=m1->getNumberOfNodes();
8261 const double *coo2=m2->getCoords()->getConstPointer();
8262 const int *conn2=m2->getNodalConnectivity()->getConstPointer();
8263 const int *connI2=m2->getNodalConnectivityIndex()->getConstPointer();
8264 int offset2=offset1+m2->getNumberOfNodes();
8265 int offset3=offset2+((int)addCoords.size())/2;
8266 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1->getBoundingBoxForBBTree()),bbox2Arr(m2->getBoundingBoxForBBTree());
8267 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8268 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2->getNumberOfCells(),eps);
8269 int ncell1=m1->getNumberOfCells();
8271 for(int i=0;i<ncell1;i++)
8273 std::vector<int> candidates2;
8274 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8275 std::map<INTERP_KERNEL::Node *,int> mapp;
8276 std::map<int,INTERP_KERNEL::Node *> mappRev;
8277 INTERP_KERNEL::QuadraticPolygon pol1;
8278 INTERP_KERNEL::NormalizedCellType typ=(INTERP_KERNEL::NormalizedCellType)conn1[connI1[i]];
8279 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel(typ);
8280 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,/* output */mapp,mappRev);
8281 pol1.buildFromCrudeDataArray(mappRev,cm.isQuadratic(),conn1+connI1[i]+1,coo1,
8282 desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1);
8284 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
8285 std::set<INTERP_KERNEL::Edge *> edgesBoundary2;// store all edges that are on boundary of (pol2 intersect pol1) minus edges on pol1.
8286 INTERP_KERNEL::IteratorOnComposedEdge it1(&pol1);
8287 for(it1.first();!it1.finished();it1.next())
8288 edges1.insert(it1.current()->getPtr());
8290 std::map<int,std::vector<INTERP_KERNEL::ElementaryEdge *> > edgesIn2ForShare;
8291 std::vector<INTERP_KERNEL::QuadraticPolygon> pol2s(candidates2.size());
8293 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8295 INTERP_KERNEL::NormalizedCellType typ2=(INTERP_KERNEL::NormalizedCellType)conn2[connI2[*it2]];
8296 const INTERP_KERNEL::CellModel& cm2=INTERP_KERNEL::CellModel::GetCellModel(typ2);
8297 MEDCouplingUMeshBuildQPFromMesh3(coo1,offset1,coo2,offset2,addCoords,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,/* output */mapp,mappRev);
8298 pol2s[ii].buildFromCrudeDataArray2(mappRev,cm2.isQuadratic(),conn2+connI2[*it2]+1,coo2,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,
8299 pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2,edgesIn2ForShare);
8302 for(std::vector<int>::const_iterator it2=candidates2.begin();it2!=candidates2.end();it2++,ii++)
8304 pol1.initLocationsWithOther(pol2s[ii]);
8305 pol2s[ii].updateLocOfEdgeFromCrudeDataArray2(desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,pol1,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,colinear2);
8306 //MEDCouplingUMeshAssignOnLoc(pol1,pol2,desc1+descIndx1[i],desc1+descIndx1[i+1],intesctEdges1,desc2+descIndx2[*it2],desc2+descIndx2[*it2+1],intesctEdges2,colinear2);
8307 pol1.buildPartitionsAbs(pol2s[ii],edges1,edgesBoundary2,mapp,i,*it2,offset3,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8313 INTERP_KERNEL::QuadraticPolygon::ComputeResidual(pol1,edges1,edgesBoundary2,mapp,offset3,i,addCoordsQuadratic,cr,crI,cNb1,cNb2);
8315 catch(INTERP_KERNEL::Exception& e)
8317 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();
8318 throw INTERP_KERNEL::Exception(oss.str().c_str());
8321 for(std::map<int,INTERP_KERNEL::Node *>::const_iterator it=mappRev.begin();it!=mappRev.end();it++)
8322 (*it).second->decrRef();
8327 * This method is private and is the first step of Partition of 2D mesh (spaceDim==2 and meshDim==2).
8330 void MEDCouplingUMesh::IntersectDescending2DMeshes(const MEDCouplingUMesh *m1, const MEDCouplingUMesh *m2, double eps,
8331 std::vector< std::vector<int> >& intersectEdge1, std::vector< std::vector<int> >& colinear2, std::vector< std::vector<int> >& subDiv2,
8332 MEDCouplingUMesh *& m1Desc, DataArrayInt *&desc1, DataArrayInt *&descIndx1, DataArrayInt *&revDesc1, DataArrayInt *&revDescIndx1,
8333 MEDCouplingUMesh *& m2Desc, DataArrayInt *&desc2, DataArrayInt *&descIndx2, DataArrayInt *&revDesc2, DataArrayInt *&revDescIndx2,
8334 std::vector<double>& addCoo) throw(INTERP_KERNEL::Exception)
8336 static const int SPACEDIM=2;
8337 desc1=DataArrayInt::New(); descIndx1=DataArrayInt::New(); revDesc1=DataArrayInt::New(); revDescIndx1=DataArrayInt::New();
8338 desc2=DataArrayInt::New();
8339 descIndx2=DataArrayInt::New();
8340 revDesc2=DataArrayInt::New();
8341 revDescIndx2=DataArrayInt::New();
8342 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd1(desc1),dd2(descIndx1),dd3(revDesc1),dd4(revDescIndx1);
8343 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> dd5(desc2),dd6(descIndx2),dd7(revDesc2),dd8(revDescIndx2);
8344 m1Desc=m1->buildDescendingConnectivity2(desc1,descIndx1,revDesc1,revDescIndx1);
8345 m2Desc=m2->buildDescendingConnectivity2(desc2,descIndx2,revDesc2,revDescIndx2);
8346 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> dd9(m1Desc),dd10(m2Desc);
8347 const int *c1=m1Desc->getNodalConnectivity()->getConstPointer();
8348 const int *ci1=m1Desc->getNodalConnectivityIndex()->getConstPointer();
8349 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> bbox1Arr(m1Desc->getBoundingBoxForBBTree()),bbox2Arr(m2Desc->getBoundingBoxForBBTree());
8350 const double *bbox1(bbox1Arr->begin()),*bbox2(bbox2Arr->begin());
8351 int ncell1=m1Desc->getNumberOfCells();
8352 int ncell2=m2Desc->getNumberOfCells();
8353 intersectEdge1.resize(ncell1);
8354 colinear2.resize(ncell2);
8355 subDiv2.resize(ncell2);
8356 BBTree<SPACEDIM,int> myTree(bbox2,0,0,m2Desc->getNumberOfCells(),-eps);
8357 std::vector<int> candidates1(1);
8358 int offset1=m1->getNumberOfNodes();
8359 int offset2=offset1+m2->getNumberOfNodes();
8360 for(int i=0;i<ncell1;i++)
8362 std::vector<int> candidates2;
8363 myTree.getIntersectingElems(bbox1+i*2*SPACEDIM,candidates2);
8364 if(!candidates2.empty())
8366 std::map<INTERP_KERNEL::Node *,int> map1,map2;
8367 INTERP_KERNEL::QuadraticPolygon *pol2=MEDCouplingUMeshBuildQPFromMesh(m2Desc,candidates2,map2);
8369 INTERP_KERNEL::QuadraticPolygon *pol1=MEDCouplingUMeshBuildQPFromMesh(m1Desc,candidates1,map1);
8370 pol1->splitAbs(*pol2,map1,map2,offset1,offset2,candidates2,intersectEdge1[i],i,colinear2,subDiv2,addCoo);
8375 intersectEdge1[i].insert(intersectEdge1[i].end(),c1+ci1[i]+1,c1+ci1[i+1]);
8377 m1Desc->incrRef(); desc1->incrRef(); descIndx1->incrRef(); revDesc1->incrRef(); revDescIndx1->incrRef();
8378 m2Desc->incrRef(); desc2->incrRef(); descIndx2->incrRef(); revDesc2->incrRef(); revDescIndx2->incrRef();
8382 * This method performs the 2nd step of Partition of 2D mesh.
8383 * This method has 4 inputs :
8384 * - a mesh 'm1' with meshDim==1 and a SpaceDim==2
8385 * - a mesh 'm2' with meshDim==1 and a SpaceDim==2
8386 * - subDiv of size 'm2->getNumberOfCells()' that lists for each seg cell in 'm' the splitting node ids in randomly sorted.
8387 * 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'
8388 * \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'
8389 * \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.
8390 * \param addCoo input parameter with additionnal nodes linked to intersection of the 2 meshes.
8392 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)
8394 int offset1=m1->getNumberOfNodes();
8395 int ncell=m2->getNumberOfCells();
8396 const int *c=m2->getNodalConnectivity()->getConstPointer();
8397 const int *cI=m2->getNodalConnectivityIndex()->getConstPointer();
8398 const double *coo=m2->getCoords()->getConstPointer();
8399 const double *cooBis=m1->getCoords()->getConstPointer();
8400 int offset2=offset1+m2->getNumberOfNodes();
8401 intersectEdge.resize(ncell);
8402 for(int i=0;i<ncell;i++,cI++)
8404 const std::vector<int>& divs=subDiv[i];
8405 int nnode=cI[1]-cI[0]-1;
8406 std::map<int, std::pair<INTERP_KERNEL::Node *,bool> > mapp2;
8407 std::map<INTERP_KERNEL::Node *, int> mapp22;
8408 for(int j=0;j<nnode;j++)
8410 INTERP_KERNEL::Node *nn=new INTERP_KERNEL::Node(coo[2*c[(*cI)+j+1]],coo[2*c[(*cI)+j+1]+1]);
8411 int nnid=c[(*cI)+j+1];
8412 mapp2[nnid]=std::pair<INTERP_KERNEL::Node *,bool>(nn,true);
8413 mapp22[nn]=nnid+offset1;
8415 INTERP_KERNEL::Edge *e=MEDCouplingUMeshBuildQPFromEdge((INTERP_KERNEL::NormalizedCellType)c[*cI],mapp2,c+(*cI)+1);
8416 for(std::map<int, std::pair<INTERP_KERNEL::Node *,bool> >::const_iterator it=mapp2.begin();it!=mapp2.end();it++)
8417 ((*it).second.first)->decrRef();
8418 std::vector<INTERP_KERNEL::Node *> addNodes(divs.size());
8419 std::map<INTERP_KERNEL::Node *,int> mapp3;
8420 for(std::size_t j=0;j<divs.size();j++)
8423 INTERP_KERNEL::Node *tmp=0;
8425 tmp=new INTERP_KERNEL::Node(cooBis[2*id],cooBis[2*id+1]);
8427 tmp=new INTERP_KERNEL::Node(coo[2*(id-offset1)],coo[2*(id-offset1)+1]);//if it happens, bad news mesh 'm2' is non conform.
8429 tmp=new INTERP_KERNEL::Node(addCoo[2*(id-offset2)],addCoo[2*(id-offset2)+1]);
8433 e->sortIdsAbs(addNodes,mapp22,mapp3,intersectEdge[i]);
8434 for(std::vector<INTERP_KERNEL::Node *>::const_iterator it=addNodes.begin();it!=addNodes.end();it++)
8441 * 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).
8442 * 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
8443 * with a plane. The result will be put in 'cut3DSuf' out parameter.
8444 * \param [in] cut3DCurve input paramter that gives for each 3DCurve cell if it owns fully to the plane or partially.
8445 * \param [out] nodesOnPlane, returns all the nodes that are on the plane.
8446 * \param [in] nodal3DSurf is the nodal connectivity of 3D surf mesh.
8447 * \param [in] nodalIndx3DSurf is the nodal connectivity index of 3D surf mesh.
8448 * \param [in] nodal3DCurve is the nodal connectivity of 3D curve mesh.
8449 * \param [in] nodal3DIndxCurve is the nodal connectivity index of 3D curve mesh.
8450 * \param [in] desc is the descending connectivity 3DSurf->3DCurve
8451 * \param [in] descIndx is the descending connectivity index 3DSurf->3DCurve
8452 * \param [out] cut3DSuf input/output param.
8454 void MEDCouplingUMesh::AssemblyForSplitFrom3DCurve(const std::vector<int>& cut3DCurve, std::vector<int>& nodesOnPlane, const int *nodal3DSurf, const int *nodalIndx3DSurf,
8455 const int *nodal3DCurve, const int *nodalIndx3DCurve,
8456 const int *desc, const int *descIndx,
8457 std::vector< std::pair<int,int> >& cut3DSurf) throw(INTERP_KERNEL::Exception)
8459 std::set<int> nodesOnP(nodesOnPlane.begin(),nodesOnPlane.end());
8460 int nbOf3DSurfCell=(int)cut3DSurf.size();
8461 for(int i=0;i<nbOf3DSurfCell;i++)
8463 std::vector<int> res;
8464 int offset=descIndx[i];
8465 int nbOfSeg=descIndx[i+1]-offset;
8466 for(int j=0;j<nbOfSeg;j++)
8468 int edgeId=desc[offset+j];
8469 int status=cut3DCurve[edgeId];
8473 res.push_back(status);
8476 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+1]);
8477 res.push_back(nodal3DCurve[nodalIndx3DCurve[edgeId]+2]);
8485 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8491 std::set<int> s1(nodal3DSurf+nodalIndx3DSurf[i]+1,nodal3DSurf+nodalIndx3DSurf[i+1]);
8492 std::set_intersection(nodesOnP.begin(),nodesOnP.end(),s1.begin(),s1.end(),std::back_insert_iterator< std::vector<int> >(res));
8495 cut3DSurf[i].first=res[0]; cut3DSurf[i].second=res[1];
8499 cut3DSurf[i].first=-1; cut3DSurf[i].second=-1;
8504 {// case when plane is on a multi colinear edge of a polyhedron
8505 if((int)res.size()==2*nbOfSeg)
8507 cut3DSurf[i].first=-2; cut3DSurf[i].second=i;
8510 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::AssemblyPointsFrom3DCurve : unexpected situation !");
8517 * \a this is expected to be a mesh with spaceDim==3 and meshDim==3. If not an exception will be thrown.
8518 * 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).
8519 * 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
8520 * with a plane. The result will be put in 'nodalRes' 'nodalResIndx' and 'cellIds' out parameters.
8521 * \param cut3DSurf input paramter that gives for each 3DSurf its intersection with plane (result of MEDCouplingUMesh::AssemblyForSplitFrom3DCurve).
8522 * \param desc is the descending connectivity 3D->3DSurf
8523 * \param descIndx is the descending connectivity index 3D->3DSurf
8525 void MEDCouplingUMesh::assemblyForSplitFrom3DSurf(const std::vector< std::pair<int,int> >& cut3DSurf,
8526 const int *desc, const int *descIndx,
8527 DataArrayInt *nodalRes, DataArrayInt *nodalResIndx, DataArrayInt *cellIds) const throw(INTERP_KERNEL::Exception)
8529 checkFullyDefined();
8530 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
8531 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::assemblyForSplitFrom3DSurf works on umeshes with meshdim equal to 3 and spaceDim equal to 3 too!");
8532 const int *nodal3D=_nodal_connec->getConstPointer();
8533 const int *nodalIndx3D=_nodal_connec_index->getConstPointer();
8534 int nbOfCells=getNumberOfCells();
8535 for(int i=0;i<nbOfCells;i++)
8537 std::map<int, std::set<int> > m;
8538 int offset=descIndx[i];
8539 int nbOfFaces=descIndx[i+1]-offset;
8542 for(int j=0;j<nbOfFaces;j++)
8544 const std::pair<int,int>& p=cut3DSurf[desc[offset+j]];
8545 if(p.first!=-1 && p.second!=-1)
8549 start=p.first; end=p.second;
8550 m[p.first].insert(p.second);
8551 m[p.second].insert(p.first);
8555 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)nodal3D[nodalIndx3D[i]]);
8556 int sz=nodalIndx3D[i+1]-nodalIndx3D[i]-1;
8557 INTERP_KERNEL::AutoPtr<int> tmp=new int[sz];
8558 INTERP_KERNEL::NormalizedCellType cmsId;
8559 unsigned nbOfNodesSon=cm.fillSonCellNodalConnectivity2(j,nodal3D+nodalIndx3D[i]+1,sz,tmp,cmsId);
8560 start=tmp[0]; end=tmp[nbOfNodesSon-1];
8561 for(unsigned k=0;k<nbOfNodesSon;k++)
8563 m[tmp[k]].insert(tmp[(k+1)%nbOfNodesSon]);
8564 m[tmp[(k+1)%nbOfNodesSon]].insert(tmp[k]);
8571 std::vector<int> conn(1,(int)INTERP_KERNEL::NORM_POLYGON);
8575 std::map<int, std::set<int> >::const_iterator it=m.find(start);
8576 const std::set<int>& s=(*it).second;
8577 std::set<int> s2; s2.insert(prev);
8579 std::set_difference(s.begin(),s.end(),s2.begin(),s2.end(),inserter(s3,s3.begin()));
8582 int val=*s3.begin();
8583 conn.push_back(start);
8590 conn.push_back(end);
8593 nodalRes->insertAtTheEnd(conn.begin(),conn.end());
8594 nodalResIndx->pushBackSilent(nodalRes->getNumberOfTuples());
8595 cellIds->pushBackSilent(i);
8601 * 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
8602 * 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
8603 * the geometric cell type set to INTERP_KERNEL::NORM_POLYGON.
8604 * 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
8605 * 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.
8607 * \return false if the input connectivity represents already the convex hull, true if the input cell needs to be reordered.
8609 bool MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis(const double *coords, const int *nodalConnBg, const int *nodalConnEnd, DataArrayInt *nodalConnecOut) throw(INTERP_KERNEL::Exception)
8611 std::size_t sz=std::distance(nodalConnBg,nodalConnEnd);
8614 const INTERP_KERNEL::CellModel& cm=INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)*nodalConnBg);
8615 if(cm.getDimension()==2)
8617 const int *node=nodalConnBg+1;
8618 int startNode=*node++;
8619 double refX=coords[2*startNode];
8620 for(;node!=nodalConnEnd;node++)
8622 if(coords[2*(*node)]<refX)
8625 refX=coords[2*startNode];
8628 std::vector<int> tmpOut; tmpOut.reserve(sz); tmpOut.push_back(startNode);
8632 double angle0=-M_PI/2;
8637 double angleNext=0.;
8638 while(nextNode!=startNode)
8642 for(node=nodalConnBg+1;node!=nodalConnEnd;node++)
8644 if(*node!=tmpOut.back() && *node!=prevNode)
8646 tmp2[0]=coords[2*(*node)]-coords[2*tmpOut.back()]; tmp2[1]=coords[2*(*node)+1]-coords[2*tmpOut.back()+1];
8647 double angleM=INTERP_KERNEL::EdgeArcCircle::GetAbsoluteAngle(tmp2,tmp1);
8652 res=angle0-angleM+2.*M_PI;
8661 if(nextNode!=startNode)
8663 angle0=angleNext-M_PI;
8666 prevNode=tmpOut.back();
8667 tmpOut.push_back(nextNode);
8670 std::vector<int> tmp3(2*(sz-1));
8671 std::vector<int>::iterator it=std::copy(nodalConnBg+1,nodalConnEnd,tmp3.begin());
8672 std::copy(nodalConnBg+1,nodalConnEnd,it);
8673 if(std::search(tmp3.begin(),tmp3.end(),tmpOut.begin(),tmpOut.end())!=tmp3.end())
8675 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8678 if(std::search(tmp3.rbegin(),tmp3.rend(),tmpOut.begin(),tmpOut.end())!=tmp3.rend())
8680 nodalConnecOut->insertAtTheEnd(nodalConnBg,nodalConnEnd);
8685 nodalConnecOut->pushBackSilent((int)INTERP_KERNEL::NORM_POLYGON);
8686 nodalConnecOut->insertAtTheEnd(tmpOut.begin(),tmpOut.end());
8691 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8694 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::BuildConvexEnvelopOf2DCellJarvis : invalid 2D cell connectivity !");
8698 * This method works on an input pair (\b arr, \b arrIndx) where \b arr indexes is in \b arrIndx.
8699 * 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.
8701 * \param [in] idsToRemoveBg begin of set of ids to remove in \b arr (included)
8702 * \param [in] idsToRemoveEnd end of set of ids to remove in \b arr (excluded)
8703 * \param [in,out] arr array in which the remove operation will be done.
8704 * \param [in,out] arrIndx array in the remove operation will modify
8705 * \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])
8706 * \return true if \b arr and \b arrIndx have been modified, false if not.
8708 bool MEDCouplingUMesh::RemoveIdsFromIndexedArrays(const int *idsToRemoveBg, const int *idsToRemoveEnd, DataArrayInt *arr, DataArrayInt *arrIndx, int offsetForRemoval) throw(INTERP_KERNEL::Exception)
8710 if(!arrIndx || !arr)
8711 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : some input arrays are empty !");
8712 if(offsetForRemoval<0)
8713 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::RemoveIdsFromIndexedArrays : offsetForRemoval should be >=0 !");
8714 std::set<int> s(idsToRemoveBg,idsToRemoveEnd);
8715 int nbOfGrps=arrIndx->getNumberOfTuples()-1;
8716 int *arrIPtr=arrIndx->getPointer();
8719 const int *arrPtr=arr->getConstPointer();
8720 std::vector<int> arrOut;//no utility to switch to DataArrayInt because copy always needed
8721 for(int i=0;i<nbOfGrps;i++,arrIPtr++)
8723 if(*arrIPtr-previousArrI>offsetForRemoval)
8725 for(const int *work=arrPtr+previousArrI+offsetForRemoval;work!=arrPtr+*arrIPtr;work++)
8727 if(s.find(*work)==s.end())
8728 arrOut.push_back(*work);
8731 previousArrI=*arrIPtr;
8732 *arrIPtr=(int)arrOut.size();
8734 if(arr->getNumberOfTuples()==(int)arrOut.size())
8736 arr->alloc((int)arrOut.size(),1);
8737 std::copy(arrOut.begin(),arrOut.end(),arr->getPointer());
8742 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8743 * This method returns the result of the extraction ( specified by a set of ids in [\b idsOfSelectBg , \b idsOfSelectEnd ) ).
8744 * The selection of extraction is done standardly in new2old format.
8745 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8747 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8748 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8749 * \param [in] arrIn arr origin array from which the extraction will be done.
8750 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8751 * \param [out] arrOut the resulting array
8752 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8753 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays2
8755 void MEDCouplingUMesh::ExtractFromIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8756 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8758 if(!arrIn || !arrIndxIn)
8759 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input pointer is NULL !");
8760 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8761 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8762 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : input arrays must have exactly one component !");
8763 std::size_t sz=std::distance(idsOfSelectBg,idsOfSelectEnd);
8764 const int *arrInPtr=arrIn->getConstPointer();
8765 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8766 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8768 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8769 int maxSizeOfArr=arrIn->getNumberOfTuples();
8770 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8771 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8772 arrIo->alloc((int)(sz+1),1);
8773 const int *idsIt=idsOfSelectBg;
8774 int *work=arrIo->getPointer();
8777 for(std::size_t i=0;i<sz;i++,work++,idsIt++)
8779 if(*idsIt>=0 && *idsIt<nbOfGrps)
8780 lgth+=arrIndxPtr[*idsIt+1]-arrIndxPtr[*idsIt];
8783 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8784 throw INTERP_KERNEL::Exception(oss.str().c_str());
8790 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " and at this pos arrIndxIn[" << *idsIt;
8791 oss << "+1]-arrIndxIn[" << *idsIt << "] < 0 ! The input index array is bugged !";
8792 throw INTERP_KERNEL::Exception(oss.str().c_str());
8795 arro->alloc(lgth,1);
8796 work=arro->getPointer();
8797 idsIt=idsOfSelectBg;
8798 for(std::size_t i=0;i<sz;i++,idsIt++)
8800 if(arrIndxPtr[*idsIt]>=0 && arrIndxPtr[*idsIt+1]<=maxSizeOfArr)
8801 work=std::copy(arrInPtr+arrIndxPtr[*idsIt],arrInPtr+arrIndxPtr[*idsIt+1],work);
8804 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays : id located on pos #" << i << " value is " << *idsIt << " arrIndx[" << *idsIt << "] must be >= 0 and arrIndx[";
8805 oss << *idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8806 throw INTERP_KERNEL::Exception(oss.str().c_str());
8810 arrIndexOut=arrIo.retn();
8814 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8815 * 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 ).
8816 * The selection of extraction is done standardly in new2old format.
8817 * This method returns indexed arrays using 2 arrays (arrOut,arrIndexOut).
8819 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8820 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8821 * \param [in] arrIn arr origin array from which the extraction will be done.
8822 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8823 * \param [out] arrOut the resulting array
8824 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8825 * \sa MEDCouplingUMesh::ExtractFromIndexedArrays
8827 void MEDCouplingUMesh::ExtractFromIndexedArrays2(int idsOfSelectStart, int idsOfSelectStop, int idsOfSelectStep, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8828 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8830 if(!arrIn || !arrIndxIn)
8831 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input pointer is NULL !");
8832 arrIn->checkAllocated(); arrIndxIn->checkAllocated();
8833 if(arrIn->getNumberOfComponents()!=1 || arrIndxIn->getNumberOfComponents()!=1)
8834 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : input arrays must have exactly one component !");
8835 int sz=DataArrayInt::GetNumberOfItemGivenBESRelative(idsOfSelectStart,idsOfSelectStop,idsOfSelectStep,"MEDCouplingUMesh::ExtractFromIndexedArrays2 : Input slice ");
8836 const int *arrInPtr=arrIn->getConstPointer();
8837 const int *arrIndxPtr=arrIndxIn->getConstPointer();
8838 int nbOfGrps=arrIndxIn->getNumberOfTuples()-1;
8840 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ExtractFromIndexedArrays2 : The format of \"arrIndxIn\" is invalid ! Its nb of tuples should be >=1 !");
8841 int maxSizeOfArr=arrIn->getNumberOfTuples();
8842 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8843 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8844 arrIo->alloc((int)(sz+1),1);
8845 int idsIt=idsOfSelectStart;
8846 int *work=arrIo->getPointer();
8849 for(std::size_t i=0;i<sz;i++,work++,idsIt+=idsOfSelectStep)
8851 if(idsIt>=0 && idsIt<nbOfGrps)
8852 lgth+=arrIndxPtr[idsIt+1]-arrIndxPtr[idsIt];
8855 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " ! Must be in [0," << nbOfGrps << ") !";
8856 throw INTERP_KERNEL::Exception(oss.str().c_str());
8862 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " and at this pos arrIndxIn[" << idsIt;
8863 oss << "+1]-arrIndxIn[" << idsIt << "] < 0 ! The input index array is bugged !";
8864 throw INTERP_KERNEL::Exception(oss.str().c_str());
8867 arro->alloc(lgth,1);
8868 work=arro->getPointer();
8869 idsIt=idsOfSelectStart;
8870 for(std::size_t i=0;i<sz;i++,idsIt+=idsOfSelectStep)
8872 if(arrIndxPtr[idsIt]>=0 && arrIndxPtr[idsIt+1]<=maxSizeOfArr)
8873 work=std::copy(arrInPtr+arrIndxPtr[idsIt],arrInPtr+arrIndxPtr[idsIt+1],work);
8876 std::ostringstream oss; oss << "MEDCouplingUMesh::ExtractFromIndexedArrays2 : id located on pos #" << i << " value is " << idsIt << " arrIndx[" << idsIt << "] must be >= 0 and arrIndx[";
8877 oss << idsIt << "+1] <= " << maxSizeOfArr << " (the size of arrIn)!";
8878 throw INTERP_KERNEL::Exception(oss.str().c_str());
8882 arrIndexOut=arrIo.retn();
8886 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8887 * 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
8888 * cellIds \b in [ \b idsOfSelectBg , \b idsOfSelectEnd ) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
8889 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
8891 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8892 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8893 * \param [in] arrIn arr origin array from which the extraction will be done.
8894 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8895 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg, \b idsOfSelectEnd )
8896 * \param [in] srcArrIndex index array of \b srcArr
8897 * \param [out] arrOut the resulting array
8898 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
8900 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
8902 void MEDCouplingUMesh::SetPartOfIndexedArrays(const int *idsOfSelectBg, const int *idsOfSelectEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
8903 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
8904 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
8906 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8907 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays : presence of null pointer in input parameter !");
8908 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
8909 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
8910 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8911 std::vector<bool> v(nbOfTuples,true);
8913 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8914 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8915 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8917 if(*it>=0 && *it<nbOfTuples)
8920 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[*it+1]-arrIndxInPtr[*it]);
8924 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8925 throw INTERP_KERNEL::Exception(oss.str().c_str());
8928 srcArrIndexPtr=srcArrIndex->getConstPointer();
8929 arrIo->alloc(nbOfTuples+1,1);
8930 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
8931 const int *arrInPtr=arrIn->getConstPointer();
8932 const int *srcArrPtr=srcArr->getConstPointer();
8933 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
8934 int *arroPtr=arro->getPointer();
8935 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
8939 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
8940 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
8944 std::size_t pos=std::distance(idsOfSelectBg,std::find(idsOfSelectBg,idsOfSelectEnd,ii));
8945 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
8946 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
8950 arrIndexOut=arrIo.retn();
8954 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
8955 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
8957 * \param [in] idsOfSelectBg begin of set of ids of the input extraction (included)
8958 * \param [in] idsOfSelectEnd end of set of ids of the input extraction (excluded)
8959 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
8960 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
8961 * \param [in] srcArr input array that will be used as source of copy for ids in [ \b idsOfSelectBg , \b idsOfSelectEnd )
8962 * \param [in] srcArrIndex index array of \b srcArr
8964 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays
8966 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx(const int *idsOfSelectBg, const int *idsOfSelectEnd, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
8967 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
8969 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
8970 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : presence of null pointer in input parameter !");
8971 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
8972 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
8973 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
8974 int *arrInOutPtr=arrInOut->getPointer();
8975 const int *srcArrPtr=srcArr->getConstPointer();
8976 for(const int *it=idsOfSelectBg;it!=idsOfSelectEnd;it++,srcArrIndexPtr++)
8978 if(*it>=0 && *it<nbOfTuples)
8980 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[*it+1]-arrIndxInPtr[*it])
8981 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[*it]);
8984 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] !";
8985 throw INTERP_KERNEL::Exception(oss.str().c_str());
8990 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx : On pos #" << std::distance(idsOfSelectBg,it) << " value is " << *it << " not in [0," << nbOfTuples << ") !";
8991 throw INTERP_KERNEL::Exception(oss.str().c_str());
8997 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
8998 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
8999 * 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]].
9000 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9001 * A negative value in \b arrIn means that it is ignored.
9002 * 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.
9004 * \param [in] arrIn arr origin array from which the extraction will be done.
9005 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9006 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9007 * \sa MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed, MEDCouplingUMesh::partitionBySpreadZone
9009 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGradually(const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn) throw(INTERP_KERNEL::Exception)
9011 int seed=0,nbOfDepthPeelingPerformed=0;
9012 return ComputeSpreadZoneGraduallyFromSeed(&seed,&seed+1,arrIn,arrIndxIn,-1,nbOfDepthPeelingPerformed);
9016 * This method works on a pair input (\b arrIn, \b arrIndxIn) where \b arr indexes is in \b arrIndxIn.
9017 * This method expects that these two input arrays come from the output of MEDCouplingUMesh::computeNeighborsOfCells method.
9018 * 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]].
9019 * Then it is repeated recursively until either all ids are fetched or no more ids are reachable step by step.
9020 * A negative value in \b arrIn means that it is ignored.
9021 * 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.
9022 * \param [in] seedBg the begin pointer (included) of an array containing the seed of the search zone
9023 * \param [in] seedEnd the end pointer (not included) of an array containing the seed of the search zone
9024 * \param [in] arrIn arr origin array from which the extraction will be done.
9025 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9026 * \param [in] nbOfDepthPeeling the max number of peels requested in search. By default -1, that is to say, no limit.
9027 * \param [out] nbOfDepthPeelingPerformed the number of peels effectively performed. May be different from \a nbOfDepthPeeling
9028 * \return a newly allocated DataArray that stores all ids fetched by the gradually spread process.
9029 * \sa MEDCouplingUMesh::partitionBySpreadZone
9031 DataArrayInt *MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed(const int *seedBg, const int *seedEnd, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn, int nbOfDepthPeeling, int& nbOfDepthPeelingPerformed) throw(INTERP_KERNEL::Exception)
9033 nbOfDepthPeelingPerformed=0;
9035 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeed : arrIndxIn input pointer is NULL !");
9036 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9039 DataArrayInt *ret=DataArrayInt::New(); ret->alloc(0,1);
9043 std::vector<bool> fetched(nbOfTuples,false);
9044 return ComputeSpreadZoneGraduallyFromSeedAlg(fetched,seedBg,seedEnd,arrIn,arrIndxIn,nbOfDepthPeeling,nbOfDepthPeelingPerformed);
9047 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)
9049 nbOfDepthPeelingPerformed=0;
9050 if(!seedBg || !seedEnd || !arrIn || !arrIndxIn)
9051 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeSpreadZoneGraduallyFromSeedAlg : some input pointer is NULL !");
9052 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9053 std::vector<bool> fetched2(nbOfTuples,false);
9055 for(const int *seedElt=seedBg;seedElt!=seedEnd;seedElt++,i++)
9057 if(*seedElt>=0 && *seedElt<nbOfTuples)
9058 { fetched[*seedElt]=true; fetched2[*seedElt]=true; }
9060 { 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()); }
9062 const int *arrInPtr=arrIn->getConstPointer();
9063 const int *arrIndxPtr=arrIndxIn->getConstPointer();
9064 int targetNbOfDepthPeeling=nbOfDepthPeeling!=-1?nbOfDepthPeeling:std::numeric_limits<int>::max();
9065 std::vector<int> idsToFetch1(seedBg,seedEnd);
9066 std::vector<int> idsToFetch2;
9067 std::vector<int> *idsToFetch=&idsToFetch1;
9068 std::vector<int> *idsToFetchOther=&idsToFetch2;
9069 while(!idsToFetch->empty() && nbOfDepthPeelingPerformed<targetNbOfDepthPeeling)
9071 for(std::vector<int>::const_iterator it=idsToFetch->begin();it!=idsToFetch->end();it++)
9072 for(const int *it2=arrInPtr+arrIndxPtr[*it];it2!=arrInPtr+arrIndxPtr[*it+1];it2++)
9074 { fetched[*it2]=true; fetched2[*it2]=true; idsToFetchOther->push_back(*it2); }
9075 std::swap(idsToFetch,idsToFetchOther);
9076 idsToFetchOther->clear();
9077 nbOfDepthPeelingPerformed++;
9079 int lgth=(int)std::count(fetched2.begin(),fetched2.end(),true);
9081 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New(); ret->alloc(lgth,1);
9082 int *retPtr=ret->getPointer();
9083 for(std::vector<bool>::const_iterator it=fetched2.begin();it!=fetched2.end();it++,i++)
9090 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9091 * 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
9092 * cellIds \b in [\b idsOfSelectBg, \b idsOfSelectEnd) a copy coming from the corresponding values in input pair (\b srcArr, \b srcArrIndex).
9093 * This method is an generalization of MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx that performs the same thing but by without building explicitely a result output arrays.
9095 * \param [in] start begin of set of ids of the input extraction (included)
9096 * \param [in] end end of set of ids of the input extraction (excluded)
9097 * \param [in] step step of the set of ids in range mode.
9098 * \param [in] arrIn arr origin array from which the extraction will be done.
9099 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9100 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9101 * \param [in] srcArrIndex index array of \b srcArr
9102 * \param [out] arrOut the resulting array
9103 * \param [out] arrIndexOut the index array of the resulting array \b arrOut
9105 * \sa MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx MEDCouplingUMesh::SetPartOfIndexedArrays
9107 void MEDCouplingUMesh::SetPartOfIndexedArrays2(int start, int end, int step, const DataArrayInt *arrIn, const DataArrayInt *arrIndxIn,
9108 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex,
9109 DataArrayInt* &arrOut, DataArrayInt* &arrIndexOut) throw(INTERP_KERNEL::Exception)
9111 if(arrIn==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9112 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArrays2 : presence of null pointer in input parameter !");
9113 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arro=DataArrayInt::New();
9114 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> arrIo=DataArrayInt::New();
9115 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9117 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9118 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9119 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArrays2 : ");
9121 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9123 if(it>=0 && it<nbOfTuples)
9124 offset+=(srcArrIndexPtr[1]-srcArrIndexPtr[0])-(arrIndxInPtr[it+1]-arrIndxInPtr[it]);
9127 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArrays2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9128 throw INTERP_KERNEL::Exception(oss.str().c_str());
9131 srcArrIndexPtr=srcArrIndex->getConstPointer();
9132 arrIo->alloc(nbOfTuples+1,1);
9133 arro->alloc(arrIn->getNumberOfTuples()+offset,1);
9134 const int *arrInPtr=arrIn->getConstPointer();
9135 const int *srcArrPtr=srcArr->getConstPointer();
9136 int *arrIoPtr=arrIo->getPointer(); *arrIoPtr++=0;
9137 int *arroPtr=arro->getPointer();
9138 for(int ii=0;ii<nbOfTuples;ii++,arrIoPtr++)
9140 int pos=DataArray::GetPosOfItemGivenBESRelativeNoThrow(ii,start,end,step);
9143 arroPtr=std::copy(arrInPtr+arrIndxInPtr[ii],arrInPtr+arrIndxInPtr[ii+1],arroPtr);
9144 *arrIoPtr=arrIoPtr[-1]+(arrIndxInPtr[ii+1]-arrIndxInPtr[ii]);
9148 arroPtr=std::copy(srcArrPtr+srcArrIndexPtr[pos],srcArrPtr+srcArrIndexPtr[pos+1],arroPtr);
9149 *arrIoPtr=arrIoPtr[-1]+(srcArrIndexPtr[pos+1]-srcArrIndexPtr[pos]);
9153 arrIndexOut=arrIo.retn();
9157 * This method works on an input pair (\b arrIn, \b arrIndxIn) where \b arrIn indexes is in \b arrIndxIn.
9158 * This method is an specialization of MEDCouplingUMesh::SetPartOfIndexedArrays in the case of assignement do not modify the index in \b arrIndxIn.
9160 * \param [in] start begin of set of ids of the input extraction (included)
9161 * \param [in] end end of set of ids of the input extraction (excluded)
9162 * \param [in] step step of the set of ids in range mode.
9163 * \param [in,out] arrInOut arr origin array from which the extraction will be done.
9164 * \param [in] arrIndxIn is the input index array allowing to walk into \b arrIn
9165 * \param [in] srcArr input array that will be used as source of copy for ids in [\b idsOfSelectBg, \b idsOfSelectEnd)
9166 * \param [in] srcArrIndex index array of \b srcArr
9168 * \sa MEDCouplingUMesh::SetPartOfIndexedArrays2 MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx
9170 void MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2(int start, int end, int step, DataArrayInt *arrInOut, const DataArrayInt *arrIndxIn,
9171 const DataArrayInt *srcArr, const DataArrayInt *srcArrIndex) throw(INTERP_KERNEL::Exception)
9173 if(arrInOut==0 || arrIndxIn==0 || srcArr==0 || srcArrIndex==0)
9174 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : presence of null pointer in input parameter !");
9175 int nbOfTuples=arrIndxIn->getNumberOfTuples()-1;
9176 const int *arrIndxInPtr=arrIndxIn->getConstPointer();
9177 const int *srcArrIndexPtr=srcArrIndex->getConstPointer();
9178 int *arrInOutPtr=arrInOut->getPointer();
9179 const int *srcArrPtr=srcArr->getConstPointer();
9180 int nbOfElemsToSet=DataArray::GetNumberOfItemGivenBESRelative(start,end,step,"MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : ");
9182 for(int i=0;i<nbOfElemsToSet;i++,srcArrIndexPtr++,it+=step)
9184 if(it>=0 && it<nbOfTuples)
9186 if(srcArrIndexPtr[1]-srcArrIndexPtr[0]==arrIndxInPtr[it+1]-arrIndxInPtr[it])
9187 std::copy(srcArrPtr+srcArrIndexPtr[0],srcArrPtr+srcArrIndexPtr[1],arrInOutPtr+arrIndxInPtr[it]);
9190 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " id (idsOfSelectBg[" << i << "]) is " << it << " arrIndxIn[id+1]-arrIndxIn[id]!=srcArrIndex[pos+1]-srcArrIndex[pos] !";
9191 throw INTERP_KERNEL::Exception(oss.str().c_str());
9196 std::ostringstream oss; oss << "MEDCouplingUMesh::SetPartOfIndexedArraysSameIdx2 : On pos #" << i << " value is " << it << " not in [0," << nbOfTuples << ") !";
9197 throw INTERP_KERNEL::Exception(oss.str().c_str());
9203 * \b this is expected to be a mesh fully defined whose spaceDim==meshDim.
9204 * It returns a new allocated mesh having the same mesh dimension and lying on same coordinates.
9205 * The returned mesh contains as poly cells as number of contiguous zone (regarding connectivity).
9206 * A spread contiguous zone is built using poly cells (polyhedra in 3D, polygons in 2D and polyline in 1D).
9207 * The sum of measure field of returned mesh is equal to the sum of measure field of this.
9209 * \return a newly allocated mesh lying on the same coords than \b this with same meshdimension than \b this.
9211 MEDCouplingUMesh *MEDCouplingUMesh::buildSpreadZonesWithPoly() const throw(INTERP_KERNEL::Exception)
9213 checkFullyDefined();
9214 int mdim=getMeshDimension();
9215 int spaceDim=getSpaceDimension();
9217 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension and spacedimension do not match !");
9218 std::vector<DataArrayInt *> partition=partitionBySpreadZone();
9219 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > partitionAuto; partitionAuto.reserve(partition.size());
9220 std::copy(partition.begin(),partition.end(),std::back_insert_iterator<std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > >(partitionAuto));
9221 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> ret=MEDCouplingUMesh::New(getName().c_str(),mdim);
9222 ret->setCoords(getCoords());
9223 ret->allocateCells((int)partition.size());
9225 for(std::vector<DataArrayInt *>::const_iterator it=partition.begin();it!=partition.end();it++)
9227 MEDCouplingAutoRefCountObjectPtr<MEDCouplingUMesh> tmp=static_cast<MEDCouplingUMesh *>(buildPartOfMySelf((*it)->begin(),(*it)->end(),true));
9228 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> cell;
9232 cell=tmp->buildUnionOf2DMesh();
9235 cell=tmp->buildUnionOf3DMesh();
9238 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::buildSpreadZonesWithPoly : meshdimension supported are [2,3] ! Not implemented yet for others !");
9241 ret->insertNextCell((INTERP_KERNEL::NormalizedCellType)cell->getIJSafe(0,0),cell->getNumberOfTuples()-1,cell->getConstPointer()+1);
9244 ret->finishInsertingCells();
9249 * This method partitions \b this into contiguous zone.
9250 * This method only needs a well defined connectivity. Coordinates are not considered here.
9251 * This method returns a vector of \b newly allocated arrays that the caller has to deal with.
9253 std::vector<DataArrayInt *> MEDCouplingUMesh::partitionBySpreadZone() const throw(INTERP_KERNEL::Exception)
9255 int nbOfCellsCur=getNumberOfCells();
9256 std::vector<DataArrayInt *> ret;
9259 DataArrayInt *neigh=0,*neighI=0;
9260 computeNeighborsOfCells(neigh,neighI);
9261 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> neighAuto(neigh),neighIAuto(neighI);
9262 std::vector<bool> fetchedCells(nbOfCellsCur,false);
9263 std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> > ret2;
9265 while(seed<nbOfCellsCur)
9267 int nbOfPeelPerformed=0;
9268 ret2.push_back(ComputeSpreadZoneGraduallyFromSeedAlg(fetchedCells,&seed,&seed+1,neigh,neighI,-1,nbOfPeelPerformed));
9269 seed=(int)std::distance(fetchedCells.begin(),std::find(fetchedCells.begin()+seed,fetchedCells.end(),false));
9271 for(std::vector< MEDCouplingAutoRefCountObjectPtr<DataArrayInt> >::iterator it=ret2.begin();it!=ret2.end();it++)
9272 ret.push_back((*it).retn());
9277 * This method returns given a distribution of cell type (returned for example by MEDCouplingUMesh::getDistributionOfTypes method and customized after) a
9278 * newly allocated DataArrayInt instance with 2 components ready to be interpreted as input of DataArrayInt::findRangeIdForEachTuple method.
9280 * \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.
9281 * \return a newly allocated DataArrayInt to be managed by the caller.
9282 * \throw In case of \a code has not the right format (typically of size 3*n)
9284 DataArrayInt *MEDCouplingUMesh::ComputeRangesFromTypeDistribution(const std::vector<int>& code) throw(INTERP_KERNEL::Exception)
9286 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret=DataArrayInt::New();
9287 std::size_t nb=code.size()/3;
9288 if(code.size()%3!=0)
9289 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::ComputeRangesFromTypeDistribution : invalid input code !");
9290 ret->alloc((int)nb,2);
9291 int *retPtr=ret->getPointer();
9292 for(std::size_t i=0;i<nb;i++,retPtr+=2)
9294 retPtr[0]=code[3*i+2];
9295 retPtr[1]=code[3*i+2]+code[3*i+1];
9301 * This method expects that \a this a 3D mesh (spaceDim=3 and meshDim=3) with all coordinates and connectivities set.
9302 * All cells in \a this are expected to be linear 3D cells.
9303 * This method will split **all** 3D cells in \a this into INTERP_KERNEL::NORM_TETRA4 cells and put them in the returned mesh.
9304 * It leads to an increase to number of cells.
9305 * This method contrary to MEDCouplingUMesh::simplexize can append coordinates in \a this to perform its work.
9306 * The \a nbOfAdditionalPoints returned value informs about it. If > 0, the coordinates array in returned mesh will have \a nbOfAdditionalPoints
9307 * more tuples (nodes) than in \a this. Anyway, all the nodes in \a this (with the same order) will be in the returned mesh.
9309 * \param [in] policy - the policy of splitting that must be in (PLANAR_FACE_5, PLANAR_FACE_6, GENERAL_24, GENERAL_48). The policy will be used only for INTERP_KERNEL::NORM_HEXA8 cells.
9310 * For all other cells, the splitting policy will be ignored.
9311 * \param [out] nbOfAdditionalPoints - number of nodes added to \c this->_coords. If > 0 a new coordinates object will be constructed result of the aggregation of the old one and the new points added.
9312 * \param [out] n2oCells - A new instance of DataArrayInt holding, for each new cell,
9313 * an id of old cell producing it. The caller is to delete this array using
9314 * decrRef() as it is no more needed.
9315 * \return MEDCoupling1SGTUMesh * - the mesh containing only INTERP_KERNEL::NORM_TETRA4 cells.
9317 * \throw If \a this is not a 3D mesh (spaceDim==3 and meshDim==3).
9318 * \throw If \a this is not fully constituted with linear 3D cells.
9319 * \sa MEDCouplingUMesh::simplexize
9321 MEDCoupling1SGTUMesh *MEDCouplingUMesh::tetrahedrize(int policy, DataArrayInt *& n2oCells, int& nbOfAdditionalPoints) const throw(INTERP_KERNEL::Exception)
9323 INTERP_KERNEL::SplittingPolicy pol((INTERP_KERNEL::SplittingPolicy)policy);
9324 checkConnectivityFullyDefined();
9325 if(getMeshDimension()!=3 || getSpaceDimension()!=3)
9326 throw INTERP_KERNEL::Exception("MEDCouplingUMesh::tetrahedrize : only available for mesh with meshdim == 3 and spacedim == 3 !");
9327 int nbOfCells(getNumberOfCells()),nbNodes(getNumberOfNodes());
9328 MEDCouplingAutoRefCountObjectPtr<MEDCoupling1SGTUMesh> ret0(MEDCoupling1SGTUMesh::New(getName().c_str(),INTERP_KERNEL::NORM_TETRA4));
9329 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> ret(DataArrayInt::New()); ret->alloc(nbOfCells,1);
9330 int *retPt(ret->getPointer());
9331 MEDCouplingAutoRefCountObjectPtr<DataArrayInt> newConn(DataArrayInt::New()); newConn->alloc(0,1);
9332 MEDCouplingAutoRefCountObjectPtr<DataArrayDouble> addPts(DataArrayDouble::New()); addPts->alloc(0,1);
9333 const int *oldc(_nodal_connec->begin());
9334 const int *oldci(_nodal_connec_index->begin());
9335 const double *coords(_coords->begin());
9336 for(int i=0;i<nbOfCells;i++,oldci++,retPt++)
9338 std::vector<int> a; std::vector<double> b;
9339 INTERP_KERNEL::SplitIntoTetras(pol,(INTERP_KERNEL::NormalizedCellType)oldc[oldci[0]],oldc+oldci[0]+1,oldc+oldci[1],coords,a,b);
9340 std::size_t nbOfTet(a.size()/4); *retPt=(int)nbOfTet;
9341 const int *aa(&a[0]);
9344 for(std::vector<int>::iterator it=a.begin();it!=a.end();it++)
9346 *it=(-(*(it))-1+nbNodes);
9347 addPts->insertAtTheEnd(b.begin(),b.end());
9348 nbNodes+=(int)b.size()/3;
9350 for(std::size_t j=0;j<nbOfTet;j++,aa+=4)
9351 newConn->insertAtTheEnd(aa,aa+4);
9353 if(!addPts->empty())
9355 addPts->rearrange(3);
9356 nbOfAdditionalPoints=addPts->getNumberOfTuples();
9357 addPts=DataArrayDouble::Aggregate(getCoords(),addPts);
9358 ret0->setCoords(addPts);
9362 nbOfAdditionalPoints=0;
9363 ret0->setCoords(getCoords());
9365 ret0->setNodalConnectivity(newConn);
9367 ret->computeOffsets2();
9368 n2oCells=ret->buildExplicitArrOfSliceOnScaledArr(0,nbOfCells,1);
9372 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),
9373 _own_cell(true),_cell_id(-1),_nb_cell(0)
9378 _nb_cell=mesh->getNumberOfCells();
9382 MEDCouplingUMeshCellIterator::~MEDCouplingUMeshCellIterator()
9390 MEDCouplingUMeshCellIterator::MEDCouplingUMeshCellIterator(MEDCouplingUMesh *mesh, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_cell(itc),
9391 _own_cell(false),_cell_id(bg-1),
9398 MEDCouplingUMeshCell *MEDCouplingUMeshCellIterator::nextt()
9401 if(_cell_id<_nb_cell)
9410 MEDCouplingUMeshCellByTypeEntry::MEDCouplingUMeshCellByTypeEntry(MEDCouplingUMesh *mesh):_mesh(mesh)
9416 MEDCouplingUMeshCellByTypeIterator *MEDCouplingUMeshCellByTypeEntry::iterator()
9418 return new MEDCouplingUMeshCellByTypeIterator(_mesh);
9421 MEDCouplingUMeshCellByTypeEntry::~MEDCouplingUMeshCellByTypeEntry()
9427 MEDCouplingUMeshCellEntry::MEDCouplingUMeshCellEntry(MEDCouplingUMesh *mesh, INTERP_KERNEL::NormalizedCellType type, MEDCouplingUMeshCell *itc, int bg, int end):_mesh(mesh),_type(type),
9435 MEDCouplingUMeshCellEntry::~MEDCouplingUMeshCellEntry()
9441 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCellEntry::getType() const
9446 int MEDCouplingUMeshCellEntry::getNumberOfElems() const
9451 MEDCouplingUMeshCellIterator *MEDCouplingUMeshCellEntry::iterator()
9453 return new MEDCouplingUMeshCellIterator(_mesh,_itc,_bg,_end);
9456 MEDCouplingUMeshCellByTypeIterator::MEDCouplingUMeshCellByTypeIterator(MEDCouplingUMesh *mesh):_mesh(mesh),_cell(new MEDCouplingUMeshCell(mesh)),_cell_id(0),_nb_cell(0)
9461 _nb_cell=mesh->getNumberOfCells();
9465 MEDCouplingUMeshCellByTypeIterator::~MEDCouplingUMeshCellByTypeIterator()
9472 MEDCouplingUMeshCellEntry *MEDCouplingUMeshCellByTypeIterator::nextt()
9474 const int *c=_mesh->getNodalConnectivity()->getConstPointer();
9475 const int *ci=_mesh->getNodalConnectivityIndex()->getConstPointer();
9476 if(_cell_id<_nb_cell)
9478 INTERP_KERNEL::NormalizedCellType type=(INTERP_KERNEL::NormalizedCellType)c[ci[_cell_id]];
9479 int nbOfElems=(int)std::distance(ci+_cell_id,std::find_if(ci+_cell_id,ci+_nb_cell,ParaMEDMEMImpl::ConnReader(c,type)));
9480 int startId=_cell_id;
9481 _cell_id+=nbOfElems;
9482 return new MEDCouplingUMeshCellEntry(_mesh,type,_cell,startId,_cell_id);
9488 MEDCouplingUMeshCell::MEDCouplingUMeshCell(MEDCouplingUMesh *mesh):_conn(0),_conn_indx(0),_conn_lgth(NOTICABLE_FIRST_VAL)
9492 _conn=mesh->getNodalConnectivity()->getPointer();
9493 _conn_indx=mesh->getNodalConnectivityIndex()->getPointer();
9497 void MEDCouplingUMeshCell::next()
9499 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9504 _conn_lgth=_conn_indx[1]-_conn_indx[0];
9507 std::string MEDCouplingUMeshCell::repr() const
9509 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9511 std::ostringstream oss; oss << "Cell Type " << INTERP_KERNEL::CellModel::GetCellModel((INTERP_KERNEL::NormalizedCellType)_conn[0]).getRepr();
9513 std::copy(_conn+1,_conn+_conn_lgth,std::ostream_iterator<int>(oss," "));
9517 return std::string("MEDCouplingUMeshCell::repr : Invalid pos");
9520 INTERP_KERNEL::NormalizedCellType MEDCouplingUMeshCell::getType() const
9522 if(_conn_lgth!=NOTICABLE_FIRST_VAL)
9523 return (INTERP_KERNEL::NormalizedCellType)_conn[0];
9525 return INTERP_KERNEL::NORM_ERROR;
9528 const int *MEDCouplingUMeshCell::getAllConn(int& lgth) const
9531 if(_conn_lgth!=NOTICABLE_FIRST_VAL)